ioc-containerlight-inject

Lightinject with Web API - How can I get the HttpRequestMessage?


How can I get the current HttpRequestMessage when using Lightinject with Web API?
In Simple Injector, for example, I have the following extension method on the container:

var msg = container.GetCurrentHttpRequestMessage() 

But I couldn't find a matching one in Lightinject.


Solution

  • If you take a look in the Simple Injector Web API integration source code, you'll find that the implementation is actually really straightforward. You can easily implement this yourself.

    What you need is to create a custom DelegatingHandler that stores the current HttpRequestMessage in a way that you can retrieve it later on, as follows:

    public sealed class HttpRequestMessageDelegatingHandler : DelegatingHandler {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
            CancellationToken cancellationToken) {
            CurrentMessage = request;
            return base.SendAsync(request, cancellationToken);
        }
    
        public static HttpRequestMessage CurrentMessage {
            get { return (HttpRequestMessage)CallContext.LogicalGetData("RequestMessage"); }
            private set { CallContext.LogicalSetData(value, "RequestMessage"); }
        }
    }
    
    // Register this handler as follows in Web API
    configuration.MessageHandlers.Add(new HttpRequestMessageDelegatingHandler());
    

    Now you can retrieve the request's current message as follows:

    HttpRequestMessageDelegatingHandler.CurrentMessage
    

    The Simple Injector documentation advises to hide this call behind a custom abstraction, such as a simple IRequestMessageProvider. An implementation is of course easily created:

    private sealed class RequestMessageProvider : IRequestMessageProvider {
        public HttpRequestMessage CurrentMessage {
            get { return HttpRequestMessageDelegatingHandler.CurrentMessage; }
        }
    }
    

    Instead of creating an IRequestMessageProvider abstraction plus implementation, you can register it directly as delegate as follows:

    container.Register<Func<HttpRequestMessage>>(_ =>
        () => HttpRequestMessageDelegatingHandler.CurrentMessage);
    

    My preference is to use an interface instead of a Func<T>, because such interface is much more explicit and readable.