Matty
Matty

Reputation: 505

ASP.NET session is overwritten

I'm in a situation where two calls at the same time write to the session (of an asp.net core application running on the old framework), and one of the session variables gets overwritten.

Given the following controller code, assume that the long session gets called first, 200 ms later the short session gets called, and 800 ms later (when the long session is done) the result of both sessions gets called.

[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}");
}

The result of the final call (TestBothSessions) is "A: , B: true".

The question is then: Is there something I missed to make the session work (aka, return "A: true, B: true")?

Obviously, I could remove the delay and all is fine, but in the real application there's a call that potentially can take some time, and I prefer not to write the session variable at a later time (I guess I could with a bit of custom error handling, but then the problem still remains that I no longer trust the asp.net session to work with synchronous calls).

Edit: The typescript code that calls these endpoints from the browser:

this.service.testLongSession().subscribe(() => {
    this.service.testBothSessions().subscribe((result: string) => {
        console.log(result);
    });
});
setTimeout(() => {
    this.service.testShortSession().subscribe();
}, 200);

Upvotes: 6

Views: 1053

Answers (1)

Jeffrey Rennie
Jeffrey Rennie

Reputation: 3443

I believe the behavior you observe is what the ASP.NET authors intended. I look at the interfaces that session stores need to implement, namely ISession and ISessionStore, and I see no synchronization mechanisms to prevent the overwriting of data during simultaneous requests.

The benefit of such a simple interface is that it's much easier to implement, and can be easily implemented by a variety of caches and databases.

ASP.NET 4 had a much more complex session store base class SessionStateStoreProviderBase that included locking logic, but it was really challenging to implement.

Upvotes: 1

Related Questions