我正在构建一个ASP.NET WebApi 2.1应用程序,它需要等效的HttpContext.Items作为每个请求缓存.
即使在IIS托管下我也无法使用HttpContext,因为当我在服务/ repos层中进行异步工作(使用TPL调用,而不是async / await,因为需要匹配某些接口)时,HttpContext似乎丢失了(HttpContext.Current变为空值).
我正在使用unity 3.5并且无法实现每次请求注入.尝试了HttpControllerActivator方法:
public class HttpControllerActivator : IHttpControllerActivator
{
private readonly IUnityContainer _container;
private readonly IHttpControllerActivator _activator;
public HttpControllerActivator(IUnityContainer container, IHttpControllerActivator activator)
{
_container = container;
_activator = activator;
}
public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
IHttpController controller = _activator.Create(request, controllerDescriptor, controllerType);
_container.RegisterInstance<System.Net.Http.HttpRequestMessage>(request, new HierarchicalLifetimeManager());
return controller;
}
}
但是这会在根容器上注册HttpRequestMessage,而不是在_activator.Create中的BeginScope()调用创建的子容器.结果,我在并发加载下获得混合请求实例.
知道如何解决这个问题吗?我在网上搜索了两天,并没有找到任何真正的解决方案……
最佳答案
using TPL calls, not async/await due to some interface that needs to be matched
我建议你再看看async和await.您可以使用异步执行部分和have it interoperate with other asynchronous APIs.
也就是说,如果你想保留HttpContext.Current(以及文化等),那么关键是SynchronizationContext.我有一个MSDN article on that type你可能会觉得有帮助.由于您的代码使用的是TPL,您可能希望将请求上下文捕获到任务调度程序中:
var requestContext = TaskScheduler.FromCurrentSynchronizationContext();
然后使用它来安排任务延续.
ASP.NET上异步工作的另一个重要方面是确保运行时知道您的异步工作.您可以通过调用AsyncOperationManager.CreateOperation在启动之前注册异步工作和AsyncOperation.OperationCompleted来通知运行时异步工作已完成.或者,您可以捕获SynchronizationContext.Current并自己调用SynchronizationContext.OperationStarted和SynchronizationContext.OperationCompleted.
再次,再看看async并等待,看看是否可以使用它们;他们会为你照顾这样的所有细节.