In my ASP.Net Core 3.1 webapi, I'm registering the IHttpContextAccessor as a singleton and injecting it into all my controllers. I have an interface that also gets injected into all my controllers and my services (which in turn connect to the db). The implementation is:
public class PrincipalProvider : IPrincipalProvider
{
private readonly UserPrincipal principal;
public PrincipalProvider(IHttpContextAccessor accessor)
{
accessor.HttpContext.Items.TryGetValue("principal", out object principal);
this.principal = principal as UserPrincipal;
}
public UserPrincipal GetPrincipal()
{
return principal;
}
}
The ctor of a service looks like:
public MyService(
IPrincipalProvider provider,
ILogger<MyService> logger,
IUnitOfWork unitOfWork) : base(provider, logger, unitOfWork)
{ }
All the above works as expected as long as I'm within the request context.
I have a controller action that starts a background task using the new IHostedService implementation with a background queue, and it gets started like this:
backgroundQueue.QueueBackgroundWorkItem(async (scope, hubContext, ct) =>
{
await hubContext.Clients.Client(provider.GetPrincipal().ConnectionId).Notify();
var myService = scope.Resolve<IMyService>();
}
where scope is ILifetimeScope and hubConext is IHubContext<MyHub, IMyHub>. The provider variable is the IPrincipalProvider that was injected into the controller ctor.
The problem is that when I try to resolve IMyService within the task, it creates an instance of IPrincipalProvider and that in turn requires IHttpContextAccessor which doesn't exist anymore.
What is the solution in this case? Do I need to have a second ctor on the service with a different IPrincipalProvider which gets the context from somewhere else? And if that's the case, from where?