2014-12-31 5 views
17

У меня есть MVC WebAPI Owin проект (мягкий), размещенный который использует Unity для разрешения зависимостей контроллераКак передать Owin контекст к Repo впрыскивается в контроллер Api

, которые выглядят как этот

public class PacientaiController : ODataController 
    { 
     private readonly IEntityRepo<Ent.Pacientas> repo; 

     public PacientaiController(IEntityRepo<Ent.Pacientas> repo) 
     { 
      this.repo = repo; 
     } 

проблема, которую я пытаюсь решить - это как передать «OwinContex» в репо.

public class PacientasEntityRepo:IEntityRepo<Pacientas>,IDisposable 
    { 
     public PacientasEntityRepo(IOwinContext ctx) 
     { 
     ......... 

Если я пытаюсь зарегистрировать его, как это в Startup.cs

Container.RegisterType<IOwinContext>(new InjectionFactory(o => HttpContext.Current.GetOwinContext())); 

я получаю пустой реф, говоря, что HttpContext.Current является NULL

Основная идея здесь, чтобы пройти в настоящее время аутентифицированный пользователь для репо, поскольку репо размещает логику для запроса базы данных в зависимости от пользователя. (скажем, если пользователь является администратором, а затем верните эти данные, если пользователь гость - верните эти данные)

Суть в том, что это сам хост!

+0

Не обращайте внимания на мой ответ, я не читал * самостоятельно размещенную * часть – Jcl

+3

Я не могу быть единственным человеком, который читает это и думает, что есть запах, в частности, о том, что репо нуждается в доступе к * OWIN * контексту? Да, возможно, вам придется принять некоторые решения на основе текущего пользователя, но, несомненно, получить эту информацию и просто разоблачить «IPrincipal» или что-то похожее на репо, будет иметь больше смысла? –

+1

Да, возможно. Это никоим образом не влияет на проблему, потому что мне все еще нужно получить доступ к OwinContext или RequestContext, вынуть текущего принципала и предоставить его IoC для ввода сконструированной зависимости. Не имеет значения, является ли это IOwinContext или IPrinciple, или IUserRole. Он все еще живет в «RequestsContext». Вопрос касается принципов коммуникации в такой или подобной ситуации. – Marty

ответ

21

Позволяет отложить в сторону, почему у вас есть этот проект и сосредоточиться к проблеме: Впрыскивание IOwinContext:

вы также можете получить его из HttpRequestMessage например, с помощью метода GetOwinContext, однако вы также должны получить HttpRequestMessage каким-то образом.

Unity не поддерживает инъекцию HttpRequestMessage из коробки, но вы можете использовать пользовательские DelegatingHandler, который хранит в контейнере текущего HttpRequestMessage, как описано здесь: Inject WebAPI UrlHelper into service using Autofac

Связанный вопрос о Autofac, но вы можете передать она для работы с Unity:

CurrentRequest и CurrentRequestHandler можно использовать от ответа Andrew Davey «s, как это:

public class CurrentRequest 
{ 
    public HttpRequestMessage Value { get; set; } 
} 

public class CurrentRequestHandler : DelegatingHandler 
{ 
    protected async override System.Threading.Tasks.Task<HttpResponseMessage> 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<CurrentRequest>(
      new HierarchicalLifetimeManager()); 

container.RegisterType<IOwinContext>(
    new HierarchicalLifetimeManager(), 
    new InjectionFactory(c => c.Resolve<CurrentRequest>().Value.GetOwinContext())); 

httpConfiguration.DependencyResolver = new UnityHierarchicalDependencyResolver(container); 

Beside обработчика пользовательских делегации есть и другие места, чтобы крючок в Web.API для захвата HttpRequestMessage, например, вы можете создать свой собственный IHttpControllerActivator и использовать метод ExecuteAsync, как описано здесь: Dependency Injection in ASP.NET Web API 2

+0

Спасибо за публикацию этого чистого решения. –

2

В самодельном приложении у вас нет HttpContext. Вам нужен другой способ перемещения состояния. Вариант использовать сам реализованный HttpContext как:

https://github.com/danielcrenna/graveyard/tree/master/httpcontext-shim

+0

Я знаю, что нет HttpContext. Таким образом, вопрос. Но - там есть «OwinContext», который присутствует в каждом запросе и в каждом контроллере, в действии и т. Д. Проблема заключается в том, чтобы получить его в точке построения зависимостей! – Marty

+0

Вы можете передать контекст, используя инъекцию конструктора. Внесите owincontext в ваш логический уровень в качестве параметра конструктора. – Peter

1

Я думаю, что проблема в том, что HttpContext не существует в момент запуска называется, так что вы, вероятно, нужно, чтобы иметь Func вместо этого, как это:

public class PacientasEntityRepo:IEntityRepo<Pacientas>,IDisposable 
{ 
    public PacientasEntityRepo(Func<IOwinContext> ctx) 
    { 
    ......... 

, а затем изменить код в запуске этого:

Container.RegisterType<IOwinContext>(new InjectionFactory(() => HttpContext.Current.GetOwinContext())); 
+1

В самохостируемом приложении у вас нет 'HttpContext', потому что вы даже не ссылаетесь на' System.Web', поэтому 'HttpContext.Current.GetOwinContext()' не компилируется! Ваш anwer можно использовать только в том случае, если Web.Api размещен в IIS, но в OP явно задан сценарий самообслуживания. – nemesv

+0

Ну, ОП заявила, что HttpContext имеет значение null, поэтому я думаю, что у него есть ссылка на System.Web, поэтому я задавал вопрос –

+0

Да, возможно, OP имеет тип HttpContext, но он определенно будет всегда Нулевым в самоисследованом режиме как указано в [peer] (http://stackoverflow.com/a/27781420/872395), а также в уже удаленном ответе [Jcl] (http://stackoverflow.com/users/68972/jcl), который вдали предложил очень похожее решение, как вы. – nemesv

Смежные вопросы