我处于这样的情况:两个调用同时写入会话(运行在旧框架上的asp.net核心应用程序的会话),并且其中一个会话变量被覆盖。
给出以下控制器代码,假设首先调用长会话,然后在200毫秒后调用短会话,然后在800毫秒后(长会话完成时)调用两个会话的结果。
[HttpPost("[action]")]
public async Task<IActionResult> TestLongSession() {
HttpContext.Session.SetString("testb", "true");
// If we do this delay BEFORE the session ("testb") is set, then all is fine.
await Task.Delay(1000);
return Ok();
}
[HttpPost("[action]")]
public async Task<IActionResult> TestShortSession() {
HttpContext.Session.SetString("testa", "true");
return Ok();
}
[HttpGet("[action]")]
public async Task<IActionResult> TestResultOfBothSessions() {
string a = HttpContext.Session.GetString("testa");
string b = HttpContext.Session.GetString("testb");
return Ok($"A: {a}, B: {b}");
}
最终调用(TestBothSessions)的结果为"A: , B: true"
。
然后的问题是:是否有一些我无法使会话正常运行的东西(又名,返回"A: true, B: true"
)?
很明显,我可以消除延迟,并且一切都很好,但是在实际的应用程序中,有一个调用可能会花费一些时间,并且我不希望以后再编写会话变量(我想我可以使用自定义错误处理,但问题仍然存在,我不再信任asp.net会话可用于同步调用。
编辑:从浏览器调用这些端点的打字稿代码:
this.service.testLongSession().subscribe(() => {
this.service.testBothSessions().subscribe((result: string) => {
console.log(result);
});
});
setTimeout(() => {
this.service.testShortSession().subscribe();
}, 200);
答案 0 :(得分:1)
我相信您观察到的行为就是ASP.NET作者的意图。我查看了会话存储需要实现的接口,即ISession和ISessionStore,但没有看到同步机制来防止在同时请求期间覆盖数据。
这种简单的界面的好处是它易于实现,并且可以通过各种缓存和数据库轻松实现。
ASP.NET 4的会话存储基类SessionStateStoreProviderBase更为复杂,其中包括锁定逻辑,但是实现起来确实具有挑战性。