2014-12-31 8 views
17

ich habe ein MVC WebAPI owin (Soft-hosted) Projekt, das Unity verwendet für die Lösung Controller AbhängigkeitenWie Owin Zusammenhang mit einem Repo wird in Api Controller injiziert

, die wie dieses

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

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

aussehen passieren

das Problem, das ich versuche zu lösen - ist, wie übergebe ich 'OwinContex' in ein Repo.

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

Wenn ich versuche, es so registrieren im Startup.cs

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

ich einen null ref erhalten, sagen, dass HttpContext.Current NULL ist

Die Idee hier ist die Zeit passieren authentifizierter Benutzer für den Repo, da Repo-Host die Logik für die Abfrage der Datenbank abhängig von dem Benutzer. (Sagen Sie, wenn der Benutzer Admin ist, dann geben Sie diese Daten zurück, wenn der Benutzer Gast ist - geben Sie diese Daten zurück)

Der Punkt ist - das ist ein Selbst-Host!

+0

Ignoriere meine Antwort, ich habe den * selbst gehosteten * Teil nicht gelesen – Jcl

+3

Ich kann nicht die einzige Person sein, die das liest und denkt, dass es einen Geruch gibt, speziell über den Repo, der Zugang zum * OWIN * -Kontext benötigt? Ja, es könnte notwendig sein, einige Entscheidungen basierend auf dem aktuellen Benutzer zu treffen, aber sicher diese Informationen zu erhalten und nur ein "IPrincipal" oder etwas ähnliches dem Repo auszusetzen, würde mehr Sinn machen? –

+1

Ja könnte es. Es betrifft das Problem sowieso nicht, weil ich immer noch auf den OwinContext oder RequestContext zugreifen muss, den aktuellen Principal herausnehmen muss und es dem IoC geben muss, um in die Abhängigkeit, die erstellt wird, zu injizieren. Es spielt keine Rolle, ob es sich um einen IOwinContext oder IPrinciple oder IUserRole handelt. Es lebt noch im 'RequestsContext'. Die Frage betrifft die Kommunikationsprinzipien in einer solchen oder ähnlichen Situation. – Marty

Antwort

21

Lets beiseite gelegt, warum Sie diesen Entwurf haben und konzentrieren:

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

und dann den Code in Startup um dies zu ändern für das Problem: die IOwinContext Injektion:

Sie können auch bekommen es von einer HttpRequestMessage Instanz mit dem GetOwinContext Verfahren jedoch müssen Sie auch ein HttpRequestMessage irgendwie zu bekommen.

Unity bietet keine Unterstützung für die Injektion des HttpRequestMessage aus der Box, aber Sie können eine benutzerdefinierte DelegatingHandler, die den aktuellen HttpRequestMessage im Behälter speichert verwenden, wie hier beschrieben: Inject WebAPI UrlHelper into service using Autofac

Die verknüpfte Frage ist über Autofac aber Sie können übertragen es für die Arbeit mit der Einheit:

die CurrentRequest und die CurrentRequestHandler aus Andrew Davey ‚s Antwort verwendet werden, wie es ist:

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

Dann brauchen Sie nur die DelegatingHandler mit registrieren:

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

Und die CurrentRequest und IOwinContext im Behälter

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

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

httpConfiguration.DependencyResolver = new UnityHierarchicalDependencyResolver(container); 

Neben der benutzerdefinierten Delegation Handler gibt es andere Orte in Web.API Haken registrieren um beispielsweise die HttpRequestMessage zu erfassen, können Sie Ihre eigene IHttpControllerActivator erstellen und die ExecuteAsync Methode wie hier beschrieben verwenden: Dependency Injection in ASP.NET Web API 2

+0

Vielen Dank, dass Sie diese saubere Lösung veröffentlicht haben. –

2

In einer Selfhosted-Anwendung haben Sie keinen HttpContext. Du brauchst einen anderen Weg, um den Staat herum zu bewegen. Eine Option ist ein Selbst zu verwenden implementiert Httpcontext wie:

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

+0

Ich weiß, dass es keinen HttpContext gibt. Also die Frage. Aber - es gibt "OwinContext", der in jeder Anfrage und in jedem Controller vorhanden ist, Aktion usw. Das Problem ist, es zum Zeitpunkt der Konstruktion der Abhängigkeiten zu bekommen! – Marty

+0

Sie können den Kontext übergeben, indem Sie die Konstruktorinjektion verwenden. Injizieren Sie den owincontext als Konstruktorparameter in Ihre Logikebene. – Peter

1

ich glaube, das Problem ist, dass Httpcontext nicht zum Zeitpunkt Startup existiert heißt, so, was Sie wahrscheinlich benötigen, ist eine Func statt zu haben, wie folgt aus:

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

In einer Selfhosted-Anwendung haben Sie keinen 'HttpContext', weil Sie nicht einmal auf' System.Web' verweisen, so dass 'HttpContext.Current.GetOwinContext()' nicht kompiliert wird! Ihre Antwort ist nur verwendbar, wenn das Web.Api in IIS gehostet wird, das OP jedoch explizit nach dem selbst gehosteten Szenario gefragt hat. – nemesv

+0

Nun erklärte die OP die Httpcontext null waren, so dass ich glaube, dass er einen Verweis auf System.Web hat, so dass ich die Frage zu stellen –

+0

Ja, vielleicht das OP den Httpcontext-Typen hat, aber es ist auf jeden Fall wird in selfhosted Modus immer Null sein wie in [peer] (http://stackoverflow.com/a/27781420/872395) und auch in [Jcl] (http://stackoverflow.com/users/68972/jcl) bereits gelöschte Antwort angegeben ist Auf der anderen Seite schlug eine sehr ähnliche Lösung wie Sie vor. – nemesv