2013-05-16 48 views
2

我们有一个用户可以添加工作的工作队列。当添加工作人员项目时,上下文是用户(HttpContext)。但它是一个后台线程,轮询队列并依次执行这些项目。工作队列和用户上下文

我不能只是存储用户因为当HttpContext被布置成将委托对象

可以在工人运行所需要的主要是正确的东西像PrincipalPermissions

也代码,寿命管理(IOC)使用HttpContextInRequest范围,是否有可能重新建立一个HttpContext与正确的主体等

编辑: 假装HttpContext只是一个很好的功能,用于生命时间管理,我可以解决这个问题。 但是我们的后端代码在很大程度上依赖于拥有正确的用户主体,因为我们用这个来验证用户是否有权访问系统的那部分。 我会标记为答案如果有人能够回答如何存储用户主体身份与,角色和IsAuthenticated状态,后来使用另一个线程

回答

0
public void TestMethod1() 
{ 
    System.Net.WebClient client = new System.Net.WebClient(); 
    client.BaseAddress = "http://www.teejoo.com";    

    //Invoke your function here 
    client.OpenReadAsync(new Uri("http://www.teejoo.com/YourLogicalPage.aspx")); 
    //Pur your logical in your page, so you can use httpContext 

    client.OpenReadCompleted += new System.Net.OpenReadCompletedEventHandler(client_OpenReadCompleted); 
} 

void client_OpenReadCompleted(object sender, System.Net.OpenReadCompletedEventArgs e) 
{    
    //to Check the response HERE 
} 
+0

这不是什么林后,我并不想创建一个http请求,我想创建一个不具有一个后台工作一个HttpContext的。其实什么最重要的是,我能以某种方式存储和重复首席 – Anders

+0

你不能在后台创建一个HttpContext的,所以你可以通过创建一个HTTPRequest,并访问其应用程序中的 – Eugene

+0

并有一个页面的HttpContext越过这个问题的HttpContext的在你的逻辑页面,你会。 – Eugene

0

你为什么不使用附配班举行你需要的信息?您可以在Web请求期间使用适当的值创建它,并将其作为参数传递给后台工作人员。

克隆HTTPContext对象是不可能的,因为内部server session state。即使有可能,在真正的HTTP请求之外使用它来检查值也不是一个好的解决方案。

+0

的最低要求是,对于该线程特等是正确的,因为我们使用这种使用PrincipalAttributes验证方法访问该主体被设置。所以,如果我以某种方式可以克隆与身份,角色和IsAuthenticated状态本金,这将是足够好的 – Anders

+0

请参阅编辑 – Anders

1

您从HttpContext消费有状态数据的最佳做法是创建您自己的应用程序特定上下文,它在构造函数(Dependency Injected)中接受HttpContext

您的业务逻辑不应该依赖于HttpContext,而是您的新应用程序特定上下文(可能使用来自HttpContext的信息创建)。

这不仅可以解决上述问题,还可以提高代码的可测试性。

实施例:

public class MyApplicationContext 
{ 
    public IPrincipal ContextPrincipal { get; set; } 

    public MyApplicationContext(HttpContext httpContext) 
    { 
     // Store the current user principal & identity 
     ContextPrincipal = httpContext.User; 

     // Need to grab anything else from the HttpContext? Do it here! 
     // That could be cookies, Http request header values, query string 
     // parameters, session state variables, etc. 
     // 
     // Once you gather up any other stateful data, store it here in 
     // your application context object as the HttpRequest can't be passed 
     // to another thread. 
    } 

} 

public class MyHttpHandler : IHttpHandler 
{ 
    #region IHttpHandler Members 

    public bool IsReusable 
    { 
     // Return false in case your Managed Handler cannot be reused for another request. 
     // Usually this would be false in case you have some state information preserved per request. 
     get { return true; } 
    } 

    public void ProcessRequest(HttpContext context) 
    { 
     // Do some work on another thread using the ThreadPool 
     ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), new MyApplicationContext(context)); 
    } 

    public void DoWork(object state) 
    { 
     // Grab our state info which should be an instance of an 
     // MyApplicationContext. 
     MyApplicationContext context = (MyApplicationContext) state; 

     // Assign this ThreadPool thread's current principal according 
     // to our passed in application context. 
     Thread.CurrentPrincipal = context.ContextPrincipal; 

     // Check if this user is authenticated. 
     if (context.ContextPrincipal.Identity.IsAuthenticated) 
     { 
      var userName = context.ContextPrincipal.Identity.Name; 
     } 

     // Check if this user is an administrator. 
     if (context.ContextPrincipal.IsInRole("Administrator")) 
     { 
     } 

     // Do some long-ish process that we need to do on the threadpool 
     // after the HttpRequest has already been responded to earlier. 
     // 
     // This would normally be some fancy calculation/math, data 
     // operation or file routines. 
     for (int i = 0; i < 30; i++) 
     { 
      Thread.Sleep(1000); 
     } 
    } 

    #endregion 
} 

无论是IPrincipal也不IIdentity接口明确提供dispose方法。所以他们都应该保持对他们的参考。但是,我没有测试过上面的代码,我只是为这个问题写的。

如果通过一些糟糕的设计,他们实际上依赖于基础数据库连接来查询角色成员资格,那么您只需在早期在应用程序上下文的构造函数中进行评估,而HttpContext和asp.net形成身份验证提供程序仍然没有处理/关闭。

你总是可以拆开校长和身份并重新创建GenericPrincipalGenericIdentity的新实例,甚至创建实现IIdentity的应用程序身份类。这里有很多定制/扩展的空间。

+0

的问题是,它在你的线程睡眠循环的代码那取决于校长,校长将失败一次的HttpContext被处置。澄清我们的业务逻辑没有任何依赖于System.Web类的东西。但它使用Thread.CurrentPrincipal,它使用HttpContext(如果代码在IIS下运行)。 – Anders

+0

@Anders:再次查看代码。我上面做的第一件事是在新的ThreadPool线程中分配'Thread.CurrentPrincipal'!我还解释说,委托人本身并没有被处置 - 唯一可能的解释是,填充委托人角色列表的底层提供者不允许你检查角色。也许你应该发布你得到的异常的堆栈跟踪?无论哪种方式,只要先做这些检查并存储在您的应用程序环境中 - 或者编写您自己的IIdentity来存储更多信息。 – BenSwayne