---
title: "Don't use HttpContext.Current, especially when using async "
excerpt: "Avoid using HttpContext.Current if possible, especially in asynchronous code. Use the properties provided on the Page or Controller instead and pass them on to the asynchronous code."
publishDate: "2021-03-25T00:00:00"
createDate: "2021-03-26T05:11:23.937"
updateDate: "2021-03-26T07:19:50.537"
category: "dotnet"
categoryName: ".NET"
tags: [".NET","ASP.NET",".NET Framework"]
permalink: "/blog/dotnet/dont-use-httpcontext-current-especially-when-using-async"
canonical: "/blog/dotnet/dont-use-httpcontext-current-especially-when-using-async"
image: null
imageAlt: ""
imageBackgroundColor: ""
thumbnailImage: {"src":"/media/hwffejap/net-bot-doctor-thumbnail.png","focalPoint":{"left":0.5,"top":0.5},"crops":[{"alias":"thumbnail","width":250,"height":250,"coordinates":null}]}
thumbnailImageAlt: ".NET Bot dressed up as a doctor"
metaTitle: "Don't use HttpContext.Current, especially when using async "
metaDescription: "Avoid using HttpContext.Current if possible, especially in asynchronous code. Use the properties provided on the Page or Controller instead and pass them on to the asynchronous code."
ogTitle: "Don't use HttpContext.Current, especially when using async "
ogDescription: "Avoid using HttpContext.Current if possible, especially in asynchronous code. Use the properties provided on the Page or Controller instead and pass them on to the asynchronous code."
ogImage: null
ogImageAlt: ""
relatedPostKeys: ["3165b55d42a04f849ae5db9bd06e70c5","5c4e12e2de214755bf617878ecb92ed2","42695c92195149fbaf69998635681dc6"]
noIndex: false
noFollow: false
sitemapExclude: false
source: {"nodeId":1488,"contentKey":"2445d98be96d44fdaedf9302248b4426","sortOrder":92}
---


`HttpContext` holds on to all the information regarding the current HTTP request. It has a lot of properties but is most commonly used to get the Request, Response, Session, User, Cache, and more. In ASP.NET WebForms most of the same properties are conveniently provided to you on the `Page` class. The `HttpContext` is also available using the `Context` property on the `Page` class.<br>The same goes for MVC controllers. When possible always use the properties made available to you through the `Page` or `Controller`.


If for some reason you don't have access to the `HttpContext` or the properties on the context, you can use static `HttpContext.Current` which will return the `HttpContext` for the current HTTP request. This can be very useful, but avoid relying on static state like this, especially when writing asynchronous code or you may run into the following issue in the future.

## Static session wrapper gone wrong {#static-session-wrapper-gone-wrong}

The session is often wrapped by a class to avoid magic strings being used all over your application. The idea is to have const strings at the top of your class and provide typed properties wrapping the session like this:

<pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">static</span> <span style="color:#7f0055; font-weight:bold; ">class</span> MyStaticSessionWrapper&#10;{&#10;    <span style="color:#7f0055; font-weight:bold; ">private</span> <span style="color:#7f0055; font-weight:bold; ">const</span> <span style="color:#7f0055; font-weight:bold; ">string</span> CounterKey = <span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">MyCounter</span><span style="color:#2a00ff; ">"</span>;&#10;    <span style="color:#7f0055; font-weight:bold; ">private</span> <span style="color:#7f0055; font-weight:bold; ">static</span> HttpSessionState Session =&gt; HttpContext.Current.Session;&#10;&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">static</span> <span style="color:#7f0055; font-weight:bold; ">int</span> Counter&#10;    {&#10;        <span style="color:#7f0055; font-weight:bold; ">get</span> =&gt; (<span style="color:#7f0055; font-weight:bold; ">int</span>)(Session[CounterKey] ?? 0);&#10;        <span style="color:#7f0055; font-weight:bold; ">set</span> =&gt; Session[CounterKey] = value;&#10;    }&#10;}&#10;</pre>

In this example:


-   A constant string is defined that will be used as the index value to store the counter in session
-   A private static `Session` property returns the `Session` property from `HttpContext.Current`
-   A public static `Counter` property uses the `Session` property to set and get the counter integer value. If there's no counter in session, 0 is returned.





I've seen these types of session wrappers many times before, and find them quite useful since they centralize the retrieval, storage, and avoid magic strings.<br>This also works just fine in ASP.NET WebForms and MVC when using synchronous code. At my latest client, there was a session wrapping class just like this which worked fine for many years.<br>Until one day <code>NullReferenceException</code>'s were thrown left and right. Unfortunately, <code>NullReferenceException</code>'s aren't always as obvious as they could be. The exceptions were being logged, but there was no way of knowing which variable or property was null.<br>It wouldn't even give a line number in the stacktrace. This application was also being load balanced and experiencing session issues in the past due to misconfigured sticky sessions. <br>So initially, the assumption was that certain session properties were being initialized on one server, but then fetched on a different server leading to a <code>NullReferenceException</code>.


What was actually going wrong is that the static `HttpContext.Current` was actually null which was unexpected since this had never happened over the years it was used. But this code had never been run inside an asynchronous method before, until now.


Here is an example of a controller which has two actions incrementing the counter stored in session using the above `MyStaticSessionWrapper`:




<pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">class</span> HomeController : Controller&#10;{&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> ActionResult IncrementWithStaticSession()&#10;    {&#10;        MyStaticSessionWrapper.Counter++;&#10;        <span style="color:#7f0055; font-weight:bold; ">return</span> View(<span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">Index</span><span style="color:#2a00ff; ">"</span>);&#10;    }&#10;&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> async Task&lt;ActionResult&gt; IncrementWithStaticSessionAsync()&#10;    {&#10;        await Task.Run(() =&gt;&#10;        {&#10;            MyStaticSessionWrapper.Counter++;&#10;        });&#10;        <span style="color:#7f0055; font-weight:bold; ">return</span> View(<span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">Index</span><span style="color:#2a00ff; ">"</span>);&#10;    }&#10;}&#10;</pre>




One of the actions is incrementing the counter synchronously, and one of the actions is running the same code inside of `Task.Run`. A simple `Task.Run` is used to simulate the issue described earlier. The real code was not as clear and simple as this sample.<br>The synchronous action works as expected, but the asynchronous version throws a `NullReferenceException`  because `HttpContext.Current` is null.




## Moving away from HttpContext.Current {#moving-away-from-httpcontextcurrent}




Fixing this is relatively easy depending on your codebase. Instead of using `HttpContext.Current`, use the HttpContext provided as a property on the `Page` or `Controller`, or even better, you can simply use the `Session` property.<br>You probably do want to keep using a class that wraps the session. Instead of using a static class, use a non-static class and allow the session to be passed in as part of the constructor like this:




<pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">class</span> MySessionWrapper&#10;{&#10;    <span style="color:#7f0055; font-weight:bold; ">private</span> <span style="color:#7f0055; font-weight:bold; ">const</span> <span style="color:#7f0055; font-weight:bold; ">string</span> CounterKey = <span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">MyCounter</span><span style="color:#2a00ff; ">"</span>;&#10;    <span style="color:#7f0055; font-weight:bold; ">private</span> <span style="color:#7f0055; font-weight:bold; ">readonly</span> HttpSessionStateBase session;&#10;&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> MySessionWrapper(HttpSessionStateBase session)&#10;    {&#10;        <span style="color:#7f0055; font-weight:bold; ">this</span>.session = session;&#10;    }&#10;&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">int</span> Counter&#10;    {&#10;        <span style="color:#7f0055; font-weight:bold; ">get</span> =&gt; (<span style="color:#7f0055; font-weight:bold; ">int</span>)(session[CounterKey] ?? 0);&#10;        <span style="color:#7f0055; font-weight:bold; ">set</span> =&gt; session[CounterKey] = value;&#10;    }&#10;}&#10;</pre>

And create a new instance in your controller or have a dependency injection container take care of this for you:

<pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; font-weight:bold; ">public</span> async Task&lt;ActionResult&gt; IncrementAsync()&#10;{&#10;    await Task.Run(() =&gt;&#10;    {&#10;        <span style="color:#7f0055; font-weight:bold; ">var</span> mySession = <span style="color:#7f0055; font-weight:bold; ">new</span> MySessionWrapper(Session);&#10;        mySession.Counter++;&#10;    });&#10;    <span style="color:#7f0055; font-weight:bold; ">return</span> View(<span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">Index</span><span style="color:#2a00ff; ">"</span>);&#10;}&#10;</pre>




The above code action achieves the same as before but does not cause `NullReferenceException`'s.


Alternatively, you could add extension methods to set and get the counter on the session like this:

<pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">static</span> <span style="color:#7f0055; font-weight:bold; ">class</span> MySessionExtensions&#10;{&#10;    <span style="color:#7f0055; font-weight:bold; ">private</span> <span style="color:#7f0055; font-weight:bold; ">const</span> <span style="color:#7f0055; font-weight:bold; ">string</span> CounterKey = <span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">MyCounter</span><span style="color:#2a00ff; ">"</span>;&#10;&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">static</span> <span style="color:#7f0055; font-weight:bold; ">int</span> GetCounter(<span style="color:#7f0055; font-weight:bold; ">this</span> HttpSessionStateBase session) &#10;        =&gt; (<span style="color:#7f0055; font-weight:bold; ">int</span>)(session[CounterKey] ?? 0);&#10;&#10;    <span style="color:#7f0055; font-weight:bold; ">public</span> <span style="color:#7f0055; font-weight:bold; ">static</span> <span style="color:#7f0055; font-weight:bold; ">void</span> SetCounter(<span style="color:#7f0055; font-weight:bold; ">this</span> HttpSessionStateBase session, <span style="color:#7f0055; font-weight:bold; ">int</span> count) &#10;        =&gt; session[CounterKey] = count;&#10;}&#10;</pre>

Unfortunately, C# does not have extension properties yet, so for now you'll have to use the `GetX` and `SetX` convention which may not be very appealing to C# developers.<br>With these extension methods, you can increment the counter asynchronously in an action like this:

<pre style="color:#000000;background:#ffffff;"><span style="color:#7f0055; font-weight:bold; ">public</span> async Task&lt;ActionResult&gt; IncrementWithExtensionMethodsAsync()&#10;{&#10;    await Task.Run(() =&gt;&#10;    {&#10;        Session.SetCounter(Session.GetCounter() + 1);&#10;    });&#10;    <span style="color:#7f0055; font-weight:bold; ">return</span> View(<span style="color:#2a00ff; ">"</span><span style="color:#2a00ff; ">Index</span><span style="color:#2a00ff; ">"</span>);&#10;}&#10;</pre>

Once the usage of `HttpContext.Current` inside of async code was removed, all the errors were gone.
