1

Ich habe eine benutzerdefinierte HttpModule, wo ich HTTP-Anfragen verfolgen, Teil der Implementierung ist wie folgt;Wird HttpContext injiziert, indem Konstruktorinjektion in HttpModule falsch verwendet wird?

private readonly HttpContextBase _httpContext; 
    private readonly ISessionContext _sessionContext; 

    public ASHttpModule(HttpContextBase httpContext, 
     ISessionContext sessionContext) 
    { 
     this._httpContext = httpContext; 
     this._sessionContext = sessionContext; 
    } 
    public void Init(HttpApplication context) 
    { 
     context.BeginRequest += Context_BeginRequest; 
     context.EndRequest += Context_EndRequest; 
    } 
    private void Context_BeginRequest(object sender, EventArgs e) 
    { 
     Stopwatch stopwatch = new Stopwatch(); 
     _httpContext.Items["Stopwatch"] = stopwatch; 
     stopwatch.Start(); 
    } 
    private void Context_EndRequest(object sender, EventArgs e) 
    { 
      Stopwatch stopwatch = (Stopwatch)_httpContext.Items["Stopwatch"]; 
      if (stopwatch == null) 
       return; 

      stopwatch.Stop(); 
      TimeSpan ts = stopwatch.Elapsed; 
      //Check current httprequest variables and log if have to 

    } 

Hier meine Abhängigkeitsregistrierung (mit Autofac);

 builder.RegisterType<WebSessionContext>() 
      .As<ISessionContext>().InstancePerRequest(); 
     builder.Register(c => (new HttpContextWrapper(HttpContext.Current) as HttpContextBase)) 
      .As<HttpContextBase>() 
      .InstancePerRequest(); 
     builder.Register(c => c.Resolve<HttpContextBase>().Request) 
      .As<HttpRequestBase>() 
      .InstancePerRequest(); 
     builder.Register(c => c.Resolve<HttpContextBase>().Server) 
      .As<HttpServerUtilityBase>() 
      .InstancePerRequest(); 
     builder.Register(c => c.Resolve<HttpContextBase>().Session) 
      .As<HttpSessionStateBase>() 
      .InstancePerRequest(); 

Problem hier ist Httpmodule nur einmal aufgebaut ist, während Httpcontext für jede Anforderung injiziert werden muss. Die Lösung, die ich gefunden habe, verwendet DependencyResolver als;

 HttpContextBase _httpContext = DependencyResolver.Current.GetService<HttpContextBase>(); 

Allerdings möchte ich diese Nutzung zu vermeiden, da Servicelocator als anti-Muster betrachtet wird.

Gibt es eine Lösung, um HttpContext in HttpModule ohne DependencyResolver zu injizieren?

+0

Die Ursache des Problems ist, dass Sie [Laufzeitdaten in Ihre Komponenten] injizieren (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99). – Steven

+1

Danke für den Blogbeitrag. Hat mir geholfen, meinen Fehler zu sehen. Elegante Lösung. –

Antwort

2

können Sie versuchen, eine Fabrik zu verwenden, um die richtige Httpcontext-Instanz zu erhalten:

private readonly Func<HttpContextBase> _httpContextFactory; 
private readonly ISessionContext _sessionContext; 

public ASHttpModule(Func<HttpContextBase> httpContextFactory, 
    ISessionContext sessionContext) 
{ 
    this._httpContextFactory = httpContextFactory; 
    this._sessionContext = sessionContext; 
} 
private void Context_BeginRequest(object sender, EventArgs e) 
{ 
    var httpContext = this._httpContextFactory(); 
    Stopwatch stopwatch = new Stopwatch(); 
    httpContext.Items["Stopwatch"] = stopwatch; 
    stopwatch.Start(); 
} 

Ich gehe davon aus Autofac Func`1 Instanzen injizieren. Wenn nicht, müssen Sie möglicherweise eine einfache Klasse erstellen, die als Factory für Ihren HttpContext fungiert.

Dann können Sie injizieren:

  • Normalbetrieb → () => HttpContextWrapper(HttpContext.Current)
  • Bei der Prüfung/spöttischen → () => new HttpContextMock()
+0

Factory verwenden ist eine der Lösungen, wie Stevens Blogpost sagen. Ich denke, die Lösung Steven Angebote klang vernünftiger und ich werde damit gehen. Danke trotzdem. –

+0

Auf einen zweiten Gedanken, eigentlich ist dies auch eine gute Lösung. –