【问题标题】:Principal.Identity.Name in Task ran from Controller ActionTask 中的 Principal.Identity.Name 从 Controller Action 运行
【发布时间】:2014-09-23 19:27:52
【问题描述】:

在我正在运行的控制器操作中

public ActionResult MyAction()
{
    Task.Factory.StartNew( () =>
    {
        myService.ExecuteMethod( someArgs );
    } );
}

该服务将调用调用其他类的其他类方法,并且在某个地方,IPrincipal 被注入到类的构造函数中。

IPrincipal 是通过 HttpContext.Current.User 创建的。

由于代码在Task 中,它在不同的线程上运行,并且操作已返回,因此HttpContext.Currentnull

如果我尝试执行Thread.CurrentPrincipal,它存在,但设置为不同于HttpContext.Current.User 的内容。另外,如果我尝试访问Thread.CurrentPrincipal.Identity.Name,我会得到一个ObjectDisposedException

我将 Ninject 用于我的 IoC 容器。 IPrincipal 绑定看起来像这样

Bind<IPrincipal>().ToMethod( x => HttpContext.Current.User );

有没有办法在控制器操作中从Task 运行的代码中获得正确甚至可用的IPrincipal

【问题讨论】:

    标签: asp.net-mvc task-parallel-library ninject task


    【解决方案1】:

    HttpContext.Current.User 基本上类似于临时的ThreadLocal。因此,您需要在启动在不同线程中运行的任务之前检索它的值。无法找出哪个线程执行了Task.Factory.StartNew 并检索它的ThreadLocal 值。 考虑一下,一旦你执行Task.Factory.StartNew,webrequest 甚至可能在任务实际开始之前就结束了。 所以你需要做的是:

    IPrincipal principal = HttpContext.Current.User;
    
    Task.Factory.StartNew( () =>
    {
        myService.ExecuteMethod(principal);
    } );
    

    但是,现在如果IPrincipal 被(ctor-)注入到myService 并且 myService 被每个请求实例化(.InTransientScope().InRequestScope()),您当前的绑定将起作用,因为控制器为每个请求实例化(另见lifecycle of an asp.net mvc5 application)。

    问题只会在注入Lazy&lt;IPrincipal&gt; 或执行IResolutionRoot.Get&lt;IPrincipal&gt; 时出现(这包括使用ninject.extensions.factory,如Func&lt;IPrincipal&gt;!),因为此时HttpContext.Current.User 可能不再有效.

    我建议如果你想要一个更准确、更中肯的答案,你需要发一个Minimal, Complete, and Verifiable example

    【讨论】:

    • 我就是这么想的。我想也许我缺少一些我可以使用的东西。那好吧。我现在只是将它传递给方法调用。
    猜你喜欢
    • 2016-12-22
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 1970-01-01
    • 2011-05-30
    • 2013-01-09
    相关资源
    最近更新 更多