如何将Owin上下文传递给注入Api控制器的Repo
我有一个MVC WebApi owin(软托管)项目,它使用Unity来解析控制器依赖项
看起来像这样
public class PacientaiController : ODataController { private readonly IEntityRepo repo; public PacientaiController(IEntityRepo repo) { this.repo = repo; }
我试图解决的问题是 – 如何将’OwinContex’传递给回购。
public class PacientasEntityRepo:IEntityRepo,IDisposable { public PacientasEntityRepo(IOwinContext ctx) { .........
如果我尝试在Startup.cs
注册它
Container.RegisterType(new InjectionFactory(o => HttpContext.Current.GetOwinContext()));
我得到一个空引用,说HttpContext.Current
是NULL
这里的主要思想是将当前经过身份validation的用户传递给repo,因为Repo托管逻辑以查询数据库,具体取决于用户。 (如果用户是Admin,则返回此数据,如果用户是guest – 返回此数据)
关键是 – 这是一个自我主持人!
让我们放下为什么你有这个设计并专注于问题:注入IOwinContext
:
您也可以使用GetOwinContext
方法从HttpRequestMessage
实例获取它,但是您还需要以某种方式获取HttpRequestMessage
。
Unity不支持开箱即用的HttpRequestMessage
注入,但您可以使用自定义DelegatingHandler
,它将当前HttpRequestMessage
存储在容器中,如下所述: 使用Autofac将WebAPI UrlHelper注入服务
链接的问题是关于Autofac,但您可以将其转移到Unity工作:
CurrentRequest
和CurrentRequestHandler
可以从Andrew Davey的答案中使用,因为它是:
public class CurrentRequest { public HttpRequestMessage Value { get; set; } } public class CurrentRequestHandler : DelegatingHandler { protected async override System.Threading.Tasks.Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { var scope = request.GetDependencyScope(); var currentRequest = (CurrentRequest)scope.GetService(typeof(CurrentRequest)); currentRequest.Value = request; return await base.SendAsync(request, cancellationToken); } }
然后你只需要注册DelegatingHandler
:
httpConfiguration.MessageHandlers.Insert(0, new CurrentRequestHandler());
并在容器中注册CurrentRequest
和IOwinContext
container.RegisterType( new HierarchicalLifetimeManager()); container.RegisterType( new HierarchicalLifetimeManager(), new InjectionFactory(c => c.Resolve().Value.GetOwinContext())); httpConfiguration.DependencyResolver = new UnityHierarchicalDependencyResolver(container);
除了自定义委托处理程序之外,还有其他地方可以挂钩到Web.API来捕获HttpRequestMessage
,例如,您可以创建自己的IHttpControllerActivator
并使用此处所述的ExecuteAsync
方法: ASP.NET Web API 2中的dependency injection
在自托管应用程序中,您没有HttpContext。 你还需要另一种方法来改变状态。 一个选项是使用自我实现的HttpContext,如:
https://github.com/danielcrenna/graveyard/tree/master/httpcontext-shim
我认为问题是在调用Startup时HttpContext不存在,所以你可能需要的是改为使用Func,如下所示:
public class PacientasEntityRepo:IEntityRepo,IDisposable { public PacientasEntityRepo(Func ctx) { .........
然后将Startup中的代码更改为:
Container.RegisterType(new InjectionFactory(() => HttpContext.Current.GetOwinContext()));