Why Is Httpcontext.Current Null

Why is HttpContext.Current null?

Clearly HttpContext.Current is not null only if you access it in a thread that handles incoming requests. That's why it works "when i use this code in another class of a page".

It won't work in the scheduling related class because relevant code is not executed on a valid thread, but a background thread, which has no HTTP context associated with.

Overall, don't use Application["Setting"] to store global stuffs, as they are not global as you discovered.

If you need to pass certain information down to business logic layer, pass as arguments to the related methods. Don't let your business logic layer access things like HttpContext or Application["Settings"], as that violates the principles of isolation and decoupling.

Update:
Due to the introduction of async/await it is more often that such issues happen, so you might consider the following tip,

In general, you should only call HttpContext.Current in only a few scenarios (within an HTTP module for example). In all other cases, you should use

  • Page.Context https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.page.context?view=netframework-4.7.2
  • Controller.HttpContext https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.controller.httpcontext?view=aspnet-mvc-5.2

instead of HttpContext.Current.

Why HttpContext is null?

System.Web.HttpContext.Current is populated by IIS which is not present/active during unit testing. Hence null. Do not tightly couple your code to HttpContext for that very reason. Instead encapsulate that behind abstractions that can be mocked when testing in isolation.

Bad design aside, for your specific design you are trying to access a static dependency external to the controller. If faking the controller's context as demonstrated in your current test, then access the controller's context instead of calling the static context.

//... code removed for brevity

var _authProvider = new AuthenticationProvider(this.HttpContext);

//... code removed for brevity

With that out of the way, the design of the controller should be refactored to explicitly depend on abstractions instead of concretions.

for example, here is an abstraction for the provider

public interface IAuthenticationProvider : IFormsAuthentication {
void CheckAuthorizationForUrl(string url);

//...other members
}

public class AuthenticationProvider : IAuthenticationProvider {

//...

}

The controller should explicitly depend on this via constructor injection

public class HomeController : Controller {
private readonly IAuthenticationProvider authProvider;

public HomeController(IAuthenticationProvider authProvider) {
this.authProvider = authProvider;
}

public ActionResult Index() {
ViewBag.Title = "Home Page";

var guidAccount = "xxxxxxxx-xxxx-xxxx-xxxx-422632e0bd95";

var userData = new CookieUserData(guidAccount) { GuidAccount = guidAccount };

authProvider.CheckAuthorizationForUrl("http://pippo");

return View();
}
}

The IAuthenticationProvider implementation should be configured to be injected into the controller at run time using the framework's DependencyResolver if using dependency injection, but can now be replaced when testing the controller in isolation so as not to be coupled to framework implementation concerns.

[TestClass]
public class HomeControllerTest {
[TestMethod]
public void Index(){
// Disposizione
var authMock = new Mock<IAuthenticationProvider>();
var controller = new HomeController(authMock.Object);

// Azione
ViewResult result = controller.Index() as ViewResult;

// Asserzione
Assert.IsNotNull(result);
Assert.AreEqual("Home Page", result.ViewBag.Title);
}
}

Why is HttpContext.Current null after await?

Please ensure you are writing an ASP.NET 4.5 application, and targeting 4.5. async and await have undefined behavior on ASP.NET unless you are running on 4.5 and are using the new "task-friendly" synchronization context.

In particular, this means you must either:

  • Set httpRuntime.targetFramework to 4.5, or
  • In your appSettings, set aspnet:UseTaskFriendlySynchronizationContext to true.

More information is available here.

System.Web.HttpContext.Current.get returned null in asp.net mvc controller

The System.Web namespace is not used in ASP.NET Core MVC, hence System.Web.HttpContext.Current property will always return null value (note that HttpContext is injected). If you want to set session variable in IActionResult controller, you can use SessionExtensions.SetString method:

string key = "cart";

HttpContext.Session.SetString(key, jsoncart);

If you want to retrieve it, use SessionExtensions.GetString method:

string jsonCart = HttpContext.Session.GetString("cart");

Note: To get HttpContext instance work, put using Microsoft.AspNetCore.Http; before namespace declaration.

Further reference: Session and app state in ASP.NET Core

HTTPContext.Current in controller is null after multiple awaits

In blogs msdn there is a full research regarding this issue and a mapping of the problem, I.E to the root of the trouble:

The HttpContext object stores all the request-relevant data, including
the pointers to the native IIS request object, the ASP.NET pipeline
instance, the Request and Response properties, the Session (and many
others). Without all of this information, we can safely tell our code
is unaware of the request context it is executing into. Designing
entirely stateless web applications is not easy and implementing them
is indeed a challenging task. Moreover, web applications are rich of
third party libraries, which are generally black boxes where
unspecified code runs.

It is a very interesting thing to ponder about, how such a crucial and fundamental object in the program, HttpContext is lost during the request execution.


The soultion provided:

It consists of TaskScheduler, the ExecutionContext and the SynchronizationContext:

  • The TaskScheduler is exactly what you would expect. A scheduler for tasks! (I would be a great teacher!) Depending on the type of .NET

    application used, a specific task scheduler might be better than

    others. ASP.NET uses the ThreadPoolTaskScheduler by default, which is
    optimized for throughput and parallel background processing.
  • The ExecutionContext (EC) is again somehow similar to what the name suggests. You can look at it as a substitute of the TLS (thread local
    storage) for multithreaded parallel execution. In extreme synthesis,

    it is the object used to persist all the environmental context needed
    for the code to run and it guarantees that a method can be

    interrupted and resumed on different threads without harm (both from

    a logical and security perspective). The key aspect to understand is

    the EC needs to "flow" (essentially, be copied over from a thread to

    another) whenever a code interrupt/resume occurs.
  • The SynchronizationContext (SC) is instead somewhat more difficult to grasp. It is related and in some ways similar to the EC, albeit
    enforcing a higher layer of abstraction. Indeed it can persist

    environmental state, but it has dedicated implementations for

    queueing/dequeuing work items in specific environments. Thanks to the
    SC, a developer can write code without bothering about how the

    runtime handles the async/await patterns.

If you consider the code from the blog's example:

   await DoStuff(doSleep, configAwait)
.ConfigureAwait(configAwait);

await Task.Factory.StartNew(
async () => await DoStuff(doSleep, configAwait)
.ConfigureAwait(configAwait),
System.Threading.CancellationToken.None,
asyncContinue ? TaskCreationOptions.RunContinuationsAsynchronously : TaskCreationOptions.None,
tsFromSyncContext ? TaskScheduler.FromCurrentSynchronizationContext() : TaskScheduler.Current)
.Unwrap().ConfigureAwait(configAwait);

The explenation:

  • configAwait: controls the ConfigureAwait behavior when awaiting tasks (read on for additional considerations)
  • tsFromSyncContext: controls the TaskScheduler option passed to the StartNew method. If true, the TaskScheduler is built from the current
    SynchronizationContext, otherwise the Current TaskScheduler is used.
  • doSleep: if True, DoStuff awaits on a Thread.Sleep. If False, it awaits on a HttpClient.GetAsync operation Useful if you want to test

    it without internet connection
  • asyncContinue: controls the TaskCreationOptions passed to the StartNew method. If true, the continuations are run asynchronously.

    Useful if you plan to test continuation tasks too and to assess the

    behavior of task inlining in case of nested awaiting operations

    (doesn't affect LegacyASPNETSynchronizationContext)

Dive into the article and see if it matches your issue, I believe you will find useful info inside.


There is another solution here, using nested container, you can check it as well.

Why is HttpContext.Current null during the Session_End event?

On Session_End there is no communication necessarily involved with the browser so there is no HttpContext to refer to which explains why it is null.

Looking at your code you seem to be intersted in the Application cache. That is available via Application property on the HttpApplication instance.

If you create an overload on your UserCount class that takes an HttpApplicationState you'll be fine:

public static void subtract(HttpApplicationState appstate)
{
appstate.Lock();
int count = (int) appstate["CountOfUsers"];
count--;
appstate["CountOfUsers"]=count;
appstate.UnLock();
}

You can use this from Session_End like so:

protected void Session_End(object sender, EventArgs e)
{
UserCount.subtract(Application);
}

This works because global_asax is technically an subclass from HttpApplication and so all its members are accessible from the global_asax file.

The other implementation of substract can be used when there is an HttpContext.

HttpContext.Current is null in my web service

If you want to use HttpContext because the code has already been written as so; you need to add this to your web.config where your service resides:

<configuration>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
</configuration>

HttpContext.Current is null when using IAuthenticationFilter

The solution was to include "targetFramework=4.5" in the web.config as commented by @Alfredo and more details in https://stackoverflow.com/a/32338414/3973463



Related Topics



Leave a reply



Submit