ASP.NET Web API 2 and HttpRequestContext

Β· 833 words Β· 4 minutes to read

Last week (23 August) ASP.NET Web API 2 RC (release candidate) was released on Nuget. One of the interesting changes in this version is the emergence of HttpRequestContext - which provides a shortcut, strongly typed access to the information which up to this point hidden inside of Request.Properties dictionary, as well as some additional useful bits and pieces.

Let’s explore what’s under the hood.

Getting Web API 2 RC πŸ”—

First of all, let’s install Web API 2 RC - and that you can do off nuget, simply using the -pre switch (this will grab the latest version, which no longer is Beta but RC).

Install-Package Microsoft.AspNet.WebApi.SelfHost -Pre  

This will install the latest assemblies which include the HttpRequestContext (part of System.Web.Http).

Exploring HttpRequestContext πŸ”—

The class deifnition is as follows:

public class HttpRequestContext  
{  
/// <summary>Gets or sets the client certificate.</summary> 

public virtual X509Certificate2 ClientCertificate { get; set; }

/// <summary>Gets or sets the configuration.</summary> 

public virtual HttpConfiguration Configuration { get; set; }

/// <summary> /// Gets or sets a value indicating whether error details, such as exception messages and stack traces,

  
/// should be included in the response for this request.  
/// </summary> 

public virtual bool IncludeErrorDetail { get; set; }

/// <summary>Gets or sets a value indicating whether the request originates from a local address.</summary> 

public virtual bool IsLocal { get; set; }

/// <summary>Gets or sets the route data.</summary> 

public virtual IHttpRouteData RouteData { get; set; }

/// <summary>Gets or sets the principal.</summary> 

public virtual IPrincipal Principal { get; set; }

/// <summary>Gets or sets the factory used to generate URLs to other APIs.</summary> 

public virtual UrlHelper Url { get; set; }

/// <summary>Gets or sets the virtual path root.</summary> 

public virtual string VirtualPathRoot { get; set; }  
}  

The comments in the code pretty much explain the purpose of each property.

Most of these information (i.e. IncludeErrorDetail, isLocal etc) were already available inside of the HttpRequestMessage.Properties dictionary, although had to be extracted from there through the use of a predefined key and a cast, which was hardly convenient. In fact, even on this blog we previously resorted to this very technique.

The presence of UrlHelper here is a welcome addition, as it gives us access to link generetion outside of the controller context (i.e. in the formatter or message handler), which is definitely going to be useful. IPrincipal, on the other hand, will be helpful in testing.

HttpRequestContext can be obtained from any HttpRequestMessage (you have access to the current request pretty much anywhere in the Web API pipeline) through an extension method that is part of the latest RC package too:

public static HttpRequestContext GetRequestContext(this HttpRequestMessage request)  
{  
if (request == null)  
{  
throw Error.ArgumentNull("request");  
}

return request.GetProperty<HttpRequestContext>(HttpPropertyKeys.RequestContextKey);  
}  

This also reveals to us, that internally the context itself is simply stored in the same HttpRequestMessage.Properties dictionary as all the other request-specific information.

On a side note, the Web API team also included a couple of other extension methods, that provide direct access to specific value stored inside that dictionary, i.e.:

    • public static X509Certificate2 GetClientCertificate(this HttpRequestMessage request)
    • public static IHttpRouteData GetRouteData(this HttpRequestMessage request)
    • public static bool IsLocal(this HttpRequestMessage request)
    • public static bool ShouldIncludeErrorDetail(this HttpRequestMessage request)
    • public static bool IsBatchRequest(this HttpRequestMessage request)

Internally they all go through RequestContext anyway, so they are merely convenience additions.

Redundancy of information πŸ”—

While the addition of the context is generally a good idea, it does contribute to cluttering the overall framework API a little bit.

For example: since HttpRequestContext gives you access to the current HttpConfiguration, when you are working with a controller, you now have at least 7 different ways of getting hold the configuration (there is probably more πŸ™‚

    • Configuration property on ApiController base class
    • Configuration property on the Request property on the ApiController base class
    • Configuration property on the RequestContext property on the ApiController base class
    • Configuration property on the RequestContext property obtained by calling GetRequestContext() method on the Request object on the ApiController base class
    • Configuration property on the RequestContext property on the ControllerContext on the ApiController base class
    • Configuration property on the ControllerDescriptor property on the ControllerContext on the ApiController base class
    • in Web host you can also access the static GlobalConfiguration.Configuration

while this is not necessarily bad, there is some amount of noise here, isn’t there?

IMHO, the RequestContext on the ApiController or ControllerContext are unnecessary. It would make more to keep the consistency and promote obtaining of the HttpRequestContext always through the GetRequestContext() method on the HttpRequestMessage, as that’s what you have to do in the handlers, filters, formatters anyway.

In fact, it is especially confusing to have Request and RequestContext properties side by side (again, see ApiController!

I would also like to see the RequestContext surface the IP of the caller - instead of us having to resort to homebrewed extensions.

Summary πŸ”—

Regardless of some redundancy in the API design, there is definitely some good value with the HttpRequestContext - and I’m sure it will become a good “friend” of yours in the future Web API development.

About


Hi! I'm Filip W., a software architect from ZΓΌrich πŸ‡¨πŸ‡­. I like Toronto Maple Leafs πŸ‡¨πŸ‡¦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁒󠁳󠁣󠁴󠁿.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP