您从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