2013-05-16 49 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