User session in background task in ASP.NET Core

Viewed 770

I learned that the preferred ASP.NET-Core-way for background tasks is a hosted service.

Is there any way to pass the (user) session to this background worker? Usually the session is part of the HttpContext which will not be available in the background task...

I know that I could persist data by writing to the database but I'd also like to cache some data in memory.

3 Answers

If this is all happening in-process, then you should be able to just pass the ISession object directly to your background service and have it interact with the user’s session without the user’s HttpContext having to be around.

The default session implementation is using the distributed cache to persist the information stored in the session. Each session object is then only interacted by with a session key that is stored in a user cookie. When the session object is being created, no direct or indirect reference to the HttpContext is being passed. The session store itself also does not access the HttpContext in some other way. The distributed cache itself is also independent of the context and also the DI service scope.

So at least in theory, this should work just fine. You can use the ISession object to modify the session and the next time the user makes a request with their session id, the updated information will be there waiting for them.

There is no guarantee the user session will exist when executing the background task. Encapsulate the data your task requires from the user session and pass it to the background task.

As you know session is based on this user request. User owns the session! So when we are talking about session, actually we are pointing to the end-user-request received from the client! Imagine a situation that you have a background task in an aspnetcore-based micro-service with no user requests. Never ever you wont see any sessions to capture because there is no user to send any request. In a normal sunny day, the probability of user session existence inside a background task is very low. BUT! If you have a background service that you want to use it as a cache, you should execute cache read/write operations per user request. I highly recommend you to avoid using HttpContext inside your background task, because your task will be non-extendable, tightly-coupled with http infrastructure. There is a simple SAMPLE :D to be more clarified:

public interface ICache {
    Task Write(string uniqueIdentifier, object data);
    Task<object> Read(string uniqueIdentifier);
}
public class BackgroundTaskBasedCache : ICache {
  public void Init()
  {
     //Initialize your background operations.
  }

  //IO bound
  public async Task Write(string sessionId, object data)
  {
      
      //write inside your cache.
  }

  public async Task<object> Read(string sessionId)
  {
     //read from your cache.
     return new object();//for test.
  }
}

startup.cs:

//this will add a signleton background task. (you can do it manually or using other tools/strategies.
services.AddSingleton<ICache, BackgroundTaskBasedCache>();

inside your controller:

    {
   public TestController(ICache cache, IHttpContextAccessor){//fill properties}
     public async Task<IActionResult> ExecuteSomeRequestAction()
     {
         await cache.Write(httpContextAccessor.HttpContext.SessionId, data);
     }
   }

hope to understand and best regards :)

Related