您從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形成身份驗證提供程序仍然沒有處理/關閉。
你總是可以拆開校長和身份並重新創建GenericPrincipal
和GenericIdentity
的新實例,甚至創建實現IIdentity
的應用程序身份類。這裏有很多定製/擴展的空間。
這不是什麼林後,我並不想創建一個http請求,我想創建一個不具有一個後臺工作一個HttpContext的。其實什麼最重要的是,我能以某種方式存儲和重複首席 – Anders
你不能在後臺創建一個HttpContext的,所以你可以通過創建一個HTTPRequest,並訪問其應用程序中的 – Eugene
並有一個頁面的HttpContext越過這個問題的HttpContext的在你的邏輯頁面,你會。 – Eugene