This MSDN article describes how HTTP Message Handlers can effectively be used in ASP.NET Web API to 'decorate' requests. Furthermore, the article shows the following code to register your custom handlers into the Web API pipeline:
config.MessageHandlers.Add(new MessageHandler1());
The problem I have with this approach is that this registers the MessageHandler1
effectively as a singleton. This is fine when the handler itself has no state and no dependencies, but in a system that is based on the SOLID design principles, it's very likely that those handlers will have dependencies of their own and its very likely that some of those dependencies need a lifetime that is shorter than singleton.
If that's the case, such message handler should not be created as singleton, since in general, a component should never have a lifetime that is longer than the lifetime of its dependencies.
So my question is, what alternative ways do we have to register custom message handlers, in such way that they can be resolved from our IoC container on each request?
I'm not aware of a different registration API for message handlers, but you can inject a Factory into your message handler in order to make it resolve dependencies per method call:
public class LifetimeProxyMessageHandler : DelegatingHandler
{
private readonly IHttpMessageHandlerFactory factory;
public LifetimeProxyMessageHandler(IHttpMessageHandlerFactory factory)
{
if (factory == null)
throw new ArgumentNullException("factory");
this.factory = factory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpMessageHandler ephemeralHandler = factory.Create();
ephemeralHandler.InnerHandler = this.InnerHandler;
var invoker = new HttpMessageInvoker(ephemeralHandler);
return invoker.SendAsync(request, cancellationToken);
}
}
You might want to skip having an ephemeral HttpMessageHandler
, and instead just ask the factory to create an instance of whatever service you wish to invoke at that point.
IHttpMessageHandlerFactory
is a custom interface I just made up for the occasion. It could look like this:
public interface IHttpMessageHandlerFactory
{
HttpMessageHandler Create();
}
Taking cue from this article, I solved the same problem in the following way:
I created a service that will host my global variabile
public interface IPerRequestScopedService : IDisposable
{
string ClientId { get; set; }
}
public class PerRequestScopedService : IPerRequestScopedService
{
public string ClientId { get; set; }
public void Dispose()
{
Trace.TraceInformation("Object {0} disposed", this.GetType().Name);
}
}
Then I registered it in my IoC container (in my case is SimpleInjector) using per request lifetime
container.RegisterWebApiRequest<IPerRequestScopedService, PerRequestScopedService>();
Then I used the service inside the DelegatingHandler in this way
public class HeaderReaderHandler : DelegatingHandler
{
protected async override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
Trace.TraceInformation("start HeaderReaderHandler");
IEnumerable<string> headerValues;
if (request.Headers.TryGetValues("x-client-id", out headerValues))
{
string token = headerValues.First();
var requestScopedService = request.GetDependencyScope().GetService(typeof(IPerRequestScopedService)) as IPerRequestScopedService;
requestScopedService.ClientId = token;
}
// Call the inner handler.
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
I chose this implementation over the Factory because I think is more IoC oriented even if is using Service Locator pattern instead of full Dependency Injection.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With