I have a custom HttpModule where i trace http requests , part of the implementation is as below ;
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
}
Here my dependency registration (using 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 here is HttpModule is constructed only once while HttpContext needs to be injected for each request. The solution i've found is using DependencyResolver as ;
HttpContextBase _httpContext = DependencyResolver.Current.GetService<HttpContextBase>();
However, i want to avoid this usage since ServiceLocator is considered as anti-pattern.
Is there any solution to inject HttpContext into HttpModule without using DependencyResolver?
You can try to use a factory to get the correct HttpContext instance:
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();
}
I assume Autofac can inject Func`1
instances too. If not, you might have to create a simple class which acts as a factory for your HttpContext.
Then you can inject:
() => HttpContextWrapper(HttpContext.Current)
() => new HttpContextMock()