Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET session is overwritten

Tags:

c#

asp.net

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);
like image 610
Matty Avatar asked Jan 28 '19 16:01

Matty


People also ask

What is the use of ASP NET session state?

Session state is an ASP.NET Core scenario for storage of user data while the user browses a web app. Session state uses a store maintained by the app to persist data across requests from a client. The session data is backed by a cache and considered ephemeral data—the site should continue to function without the session data.

What happens if there is no sessionidvalue in the response?

If no SessionIDvalue is supplied, ASP.NET starts a new session and the SessionIDvalue for that session is sent to the browser with the response. By default, SessionIDvalues are stored in a cookie. However, you can also configure the application to store SessionIDvalues in the URL for a "cookieless" session.

How does ASP NET maintain the Cookieless session state?

ASP.NET maintains cookieless session state by automatically inserting a unique session ID into the page's URL. For example, the following URL has been modified by ASP.NET to include the unique session ID lit3py55t21z5v55vlm25s55:

What is sessionidmanager in ASP NET?

Description SessionIDManager Manages unique identifiers for ASP.NET session state. SessionStateItemCollection Used to store session state variables. Back to top See Also


1 Answers

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.

like image 187
Jeffrey Rennie Avatar answered Oct 17 '22 15:10

Jeffrey Rennie