Counting requests per session in ASP.NET Core

Suresh Kumar 1 Reputation point
2022-09-20T08:55:59.71+00:00

I am trying to count the number of requests a client makes to a controller action in a single session. I am storing the count in session and incrementing during each request. This works well if the client sends the requests serially but seems to not work when the client sends concurrent requests. Below is my controller:

[ApiController]  
[Route("[controller]")]  
[Produces("application/json")]  
public class SessionRequestCounterController : ControllerBase  
{  
    private readonly static string REQUEST_COUNTER = "REQUEST_COUNTER";  
    private static readonly object _lockObj = new object();  
  
    public SessionRequestCounterController(ILogger<SessionRequestCounterController> logger)  
    {  
        _logger = logger;  
    }  
  
    [HttpGet]  
    public IActionResult Get()  
    {  
        lock (_lockObj)  
        {  
            int? count = HttpContext.Session.GetInt32(REQUEST_COUNTER);  
            if (count == null)  
            {  
                count = 1;  
                HttpContext.Session.SetInt32(REQUEST_COUNTER, count.Value);  
            }  
            else  
            {  
                count++;  
                HttpContext.Session.SetInt32(REQUEST_COUNTER, count.Value);  
            }  
            return Ok(count.Value);  
        }              
    }  
}   

The HTML with JavaScript sending requests serially and concurrently is below:

<html>  
<head>  
    <script>  
        const host = "localhost:44307";  
        const requestUrl = `https://${host}/SessionRequestCounter`;  
        const options = {  
            method: "GET",  
            headers: {  
                "Content-Type": "application/json",  
            },  
            credentials: "include"  
        };  
  
        async function sendRequestsSerially() {  
            for (let i = 0; i < 15; i++) {  
                let res = await fetch(  
                    requestUrl,  
                    options  
                );  
                console.log(await res.json());  
            }  
        }  
  
        async function sendRequestsParallelly() {  
            const reqs = [];  
            for (let i = 0; i < 15; i++) {  
                reqs.push(fetch(  
                    requestUrl, options  
                ).then((res) => res.json()));  
            }  
            const allData = Promise.all(reqs);  
            allData.then((res) => console.log(res));  
        }  
    </script>  
</head>  
<body>  
    <div>  
        <button onclick="sendRequestsSerially()">SendRequest Serially</button>  
        <button onclick="sendRequestsParallelly()">SendRequest Parallelly</button>  
    </div>  
</body>  
</html>  

When the requests are sent serially, we can see the request count in console like 1, 2, 3, 4, 5,...
When the requests are send concurrently, we can see the request count increments randomly like 1,1,2,2,3,...

It does seem like the HTTP requests are queued and each request gets a copy of the session data and hence concurrent requests don't work as expected. I couldn't find any documentation which clarifies the above behaviour. Appreciate any pointers or explanation of this behaviour.

NOTE: I have tried this with ASP.NET Core 3.0, 3.1, 5.0 and 6.0 and all have the same behaviour.

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,148 questions
{count} votes