1

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.

Steven
  • 166,672
  • 24
  • 332
  • 435
Yaron Levi
  • 12,535
  • 16
  • 69
  • 118

1 Answers1

1

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.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • Thank you. And it also appears in the official docs: http://seesharper.github.io/LightInject/#webapi – Yaron Levi Apr 28 '15 at 12:01
  • @YaronLevi: It's unclear to me what `LogicalThreadStorage` is. If this uses thread-local storage, the solution is incorrect, because Web API is asynchronous and moves from thread to thread. Also, instead of injecting a `Func`, consider using the more specific `IRequestMessageProvider` interface as I suggested. – Steven Apr 28 '15 at 12:17
  • LogicalThreadStorage is to .net 4.5 what new AsyncLocal is to .net 4.6. It stores a value per logical thread of execution meaning that it flows across async points. Again, Steven, thanks for taking the time to answer :) – seesharper Apr 29 '15 at 07:17
  • Hi @seesharper: This `LogicalThreadStorage` is some type defined by LightInject? Can't find it in the .NET framework nor online. `AsyncLocal` is defined in `Microsoft.VisualStudio.Threading.dll`. Is that DLL part of the standard .NET redistributable? – Steven Apr 29 '15 at 07:41
  • The LogicalThreadStorage is a class that is defined by LightInject. In .Net 4.6 and the new CoreCLR there is a new class, AsyncLocal that basically serves the same purpose of storing a value across async points. https://msdn.microsoft.com/en-us/library/dn906268%28v=vs.110%29.aspx – seesharper Apr 29 '15 at 07:45
  • @seesharper: Ah, I see (sharper) :-). They moved this type from Microsoft.VisualStudio.Threading to System.Threading in 4.6. The reason you define your own is because LightInject is depending on .NET 4.0 or .NET 4.5 I assume? – Steven Apr 29 '15 at 08:21
  • Exactly, in fact, LightInject only supports LogicalThreadStorage on .net 4.5 as there are some issues with the CallContext on .net. 4.0. http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html. – seesharper Apr 29 '15 at 08:56