2014-12-31 9 views
17

mam (miękka) projekt jest gospodarzem MVC WebAPI owin, który używa Jedności rozwiązywania zależności kontroleraJak przekazać kontekst Owin do Repo jest wstrzykiwany do kontrolera Api

które wyglądają jak to

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

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

Problem, który próbuję rozwiązać - jak przekazać "OwinContex" do repozytorium.

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

Gdy próbuję zarejestrować go w ten sposób w Startup.cs

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

otrzymuję null ref, mówiąc, że HttpContext.Current jest NULL

Główną ideą tutaj jest przekazać aktualnie uwierzytelniony użytkownik do repozytorium, ponieważ Repo hostuje logikę do odpytywania bazy danych, w zależności od użytkownika. (powiedz, jeśli użytkownik jest administratorem, a następnie zwróć te dane, jeśli użytkownik jest gościem - zwróć te dane)

Chodzi o to, że jest to samodzielny host!

+0

Zignoruj ​​moją odpowiedź, nie przeczytałem * hostowanej * części – Jcl

+3

Nie mogę być jedyną osobą, która czyta to i myśli tam zapach, konkretnie, o Repo potrzebującym dostępu do kontekstu * OWIN *? Tak, może być konieczne podjęcie pewnych decyzji w oparciu o bieżącego użytkownika, ale z pewnością uzyskanie tych informacji i po prostu ujawnienie "IPrincipal" lub coś podobnego do repo będzie miało więcej sensu? –

+1

Tak, może. W żaden sposób nie wpływa to na problem, ponieważ nadal potrzebuję uzyskać dostęp do OwinContext lub RequestContext, wyjąć bieżącą wartość główną i przekazać ją do IoC w celu wstrzyknięcia do budowanej zależności. Nie ma znaczenia, czy jest to IOwinContext lub IPrinciple, czy IUserRole. Nadal żyje w "RequestsContext". Pytanie dotyczy zasad komunikacji w takiej lub podobnej sytuacji. – Marty

Odpowiedz

21

Lets odłożyć dlaczego masz ten projekt i skoncentrować do problemu: Wstrzykiwanie IOwinContext:

można również dostać z HttpRequestMessage przykład z metodą GetOwinContext jednak trzeba także uzyskać HttpRequestMessage jakoś.

Unity nie obsługuje wstrzyknięcie HttpRequestMessage po wyjęciu z pudełka, ale można użyć niestandardowego DelegatingHandler który przechowuje aktualną HttpRequestMessage w pojemniku jak opisano tutaj: Inject WebAPI UrlHelper into service using Autofac

prowadzi link pytanie o Autofac ale można przenieść go do pracy z Unity:

CurrentRequest i CurrentRequestHandler może być używany z odpowiedzią Andrew Davey „s, jak to jest:

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); 
    } 
} 

Potem wystarczy do zarejestrowania DelegatingHandler z:

httpConfiguration.MessageHandlers.Insert(0, new CurrentRequestHandler()); 

i zarejestrować CurrentRequest i IOwinContext w pojemniku

container.RegisterType<CurrentRequest>(
      new HierarchicalLifetimeManager()); 

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

httpConfiguration.DependencyResolver = new UnityHierarchicalDependencyResolver(container); 

obok obsługi niestandardowych delegacji są inne miejsca, aby podłączyć do Web.API do przechwytywania HttpRequestMessage na przykład można utworzyć własny IHttpControllerActivator i użyć metody ExecuteAsync, jak opisano tutaj: Dependency Injection in ASP.NET Web API 2

+0

Dziękujemy za wysłanie tego czystego rozwiązania. –

2

W aplikacji selfhosted nie masz HttpContext. Potrzebujesz innego sposobu na przeniesienie stanu. Rozwiązaniem jest użycie siebie realizowany HTTPContext jak:

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

+0

Wiem, że nie ma HttpContext. Tak więc pytanie. Ale - jest tam "OwinContext", który jest obecny w każdym żądaniu i w każdym kontrolerze, działaniu itd. Problem polega na tym, aby uzyskać go w momencie konstruowania zależności! – Marty

+0

Możesz przekazać kontekst za pomocą iniekcji konstruktora. Wstrzyknij owincontext do twojej warstwy logicznej jako parametr konstruktora. – Peter

1

Myślę, że problemem jest to, że HttpContext nie istnieje na czas uruchamiania się nazywa, więc co prawdopodobnie trzeba, to mieć Func zamiast tak:

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

a następnie zmień kod na starcie do tego:

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

W aplikacji selfhosted nie masz 'HttpContext', ponieważ nie odwołujesz się nawet do' System.Web', więc 'HttpContext.Current.GetOwinContext()' nie kompiluje się! Twój anwer jest użyteczny tylko wtedy, gdy Web.Api jest hostowany w IIS, ale OP wyraźnie poprosił o samohostowany scenariusz. – nemesv

+0

No cóż, OP stwierdził, że HttpContext ma wartość null, więc domyślam się, że ma odniesienie do System.Web, więc zadałem pytanie: –

+0

Tak, może OP ma typ HttpContext, ale z pewnością będzie zawsze Null w trybie selfhosted jak stwierdzono w odpowiedziach [peer] (http://stackoverflow.com/a/27781420/872395), a także w [Jcl] (http://stackoverflow.com/users/68972/jcl) już usuniętej z dala sugerował bardzo podobne rozwiązanie jak ty. – nemesv

Powiązane problemy