【发布时间】:2020-04-02 01:47:36
【问题描述】:
在我的 ASP.Net Core 3.1 webapi 中,我将 IHttpContextAccessor 注册为单例并将其注入到我的所有控制器中。我有一个接口,它也被注入到我的所有控制器和我的服务中(它们又连接到数据库)。实现是:
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;
}
}
服务的 ctor 看起来像:
public MyService(
IPrincipalProvider provider,
ILogger<MyService> logger,
IUnitOfWork unitOfWork) : base(provider, logger, unitOfWork)
{ }
只要我在请求上下文中,上述所有工作都会按预期工作。
我有一个控制器操作,它使用带有后台队列的新 IHostedService 实现来启动后台任务,它的启动方式如下:
backgroundQueue.QueueBackgroundWorkItem(async (scope, hubContext, ct) =>
{
await hubContext.Clients.Client(provider.GetPrincipal().ConnectionId).Notify();
var myService = scope.Resolve<IMyService>();
}
其中scope 是ILifetimeScope 而hubConext 是IHubContext<MyHub, IMyHub>。 provider 变量是注入控制器 ctor 的 IPrincipalProvider。
问题是,当我尝试在任务中解析IMyService 时,它会创建一个IPrincipalProvider 的实例,而这又需要IHttpContextAccessor,它不再存在。
在这种情况下,解决方案是什么?我是否需要在服务上使用另一个 IPrincipalProvider 从其他地方获取上下文的第二个 ctor?如果是这样的话,从哪里来?
【问题讨论】:
-
HttpContext 在请求开始时创建,在响应结束时销毁。后台任务独立于 HttpContext 运行,因此在其中获取 HttpContext 是不可行的。
-
不要在后台服务中使用 IHttpContextAccessor ;)
-
是的,我知道。那有什么选择呢?我需要一个替代方案,使我能够使用 Resolve 将主要提供者(或 ir 的变体)注入服务的 ctor)
-
您无法在后台运行的函数之外解析 IMyService 吗?那么当 HttpContextAccessor 存在并且 UserPrinciple 保存在实例中时,IMyService 就解决了吗?你只写 var myService = theResolvedService?
-
@Darm 我尝试通过将
ILifetimeScope注入到ctor 中,然后创建一个子作用域,并将任务包装在其中。问题仍然存在,因为 DbContext 也被处理掉了。
标签: c# asp.net-core autofac