How to get HttpContext.Current in ASP.NET Core?
As a general rule, converting a Web Forms or MVC5 application to ASP.NET Core will require a significant amount of refactoring.
HttpContext.Current
was removed in ASP.NET Core. Accessing the current HTTP context from a separate class library is the type of messy architecture that ASP.NET Core tries to avoid. There are a few ways to re-architect this in ASP.NET Core.
HttpContext property
You can access the current HTTP context via the HttpContext
property on any controller. The closest thing to your original code sample would be to pass HttpContext
into the method you are calling:
public class HomeController : Controller
{
public IActionResult Index()
{
MyMethod(HttpContext);
// Other code
}
}
public void MyMethod(Microsoft.AspNetCore.Http.HttpContext context)
{
var host = $"{context.Request.Scheme}://{context.Request.Host}";
// Other code
}
HttpContext parameter in middleware
If you're writing custom middleware for the ASP.NET Core pipeline, the current request's HttpContext
is passed into your Invoke
method automatically:
public Task Invoke(HttpContext context)
{
// Do something with the current HTTP context...
}
HTTP context accessor
Finally, you can use the IHttpContextAccessor
helper service to get the HTTP context in any class that is managed by the ASP.NET Core dependency injection system. This is useful when you have a common service that is used by your controllers.
Request this interface in your constructor:
public MyMiddleware(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
You can then access the current HTTP context in a safe way:
var context = _httpContextAccessor.HttpContext;
// Do something with the current HTTP context...
IHttpContextAccessor
isn't always added to the service container by default, so register it in ConfigureServices
just to be safe:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
// if < .NET Core 2.2 use this
//services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Other code...
}
Httpcontext.current in ASP.NET Core API
HttpContext
used to be a static sealed class, which was horrendous for testing. In ASP.NET Core, it is now scoped to the request (i.e. it is instantiated at the beginning of the request and disposed at the end of the request). As such, there's no such thing as HttpContext.Current
because 1) it's not a static any more and 2) it doesn't exist outside the request pipeline.
In order to access the current (i.e. in scope) HttpContext
instance, you must inject IHttpContextAccessor
. That's a singleton which must additionally be registered with the service collection if you need to make use of it:
services.AddHttpContextAccessor();
Then, in your library class, you'd simply do something like:
public class MyClass
{
private readonly IHttpContextAccessor _httpContextAccessor;
public MyClass(IHttpContextAccesor httpContextAccesor)
{
_httpContextAccesor = httpContextAccessor;
}
...
}
And later:
// WARNING: may be null
var httpContext = _httpContextAccessor.HttpContext;
As I said previously, HttpContext
only exists within the request pipeline, so you can only access it in code that is running in that scope. If you try to get it in code that is running not as a direct result of a request coming into your an ASP.NET Core app, then it will simply be null. As such, you should do proper null checking to ensure you can safely use it.
Access the current HttpContext in ASP.NET Core
HttpContext.Current
doesn't exist anymore in ASP.NET Core but there's a new IHttpContextAccessor
that you can inject in your dependencies and use to retrieve the current HttpContext
:
public class MyComponent : IMyComponent
{
private readonly IHttpContextAccessor _contextAccessor;
public MyComponent(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public string GetDataFromSession()
{
return _contextAccessor.HttpContext.Session.GetString(*KEY*);
}
}
Accessing HttpContext in ASP.NET Core 2.2 Class library
Register IHttpContextAccessor
in the Startup
class as follows:
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Or you can also register as follows
services.AddHttpContextAccessor();
}
Then in your class libray
public class Test
{
private IHttpContextAccessor _httpContextAccessor;
public Test(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void Foo()
{
_httpContextAccessor.HttpContext.Request.Path..
}
}
Asp.Net Core 2.x HttpContext.Current not really available
The problem is, you are currently using it wrong.
Inside Controller it seems the easiest, but most of this HttpContext.Current stuff is sprinkled around various places domain libraries etc..
A Domain Libarary should be independent from the frontend. It just doesn't matter if it's a website with Session or a statefull WPF App. Or a RestFull Api.
That said, a relative Quick Fix would be to inject the HttpContext into your domain class.
public DomainService(IHttpContextAccessor httpContext)
{
_httpContext = httpContext;
}
You can then obtain your DomainService via Dependency Injection. If the creation is complex, you are looking for a Factory
.
Or you could create the Service yourself in your ActionMethod (Of course in this case you need need to change the constructor of the Service to HttpContext:
public IActionResult Foo()
{
var service = new DomainService(HttpContext)
}
That said: it was removed for a reason. Please do not rely on HttpContext in your Domain! Create a business object and give it as parameter to the domain instead.
Not sure if it is the best way, but I have created a BusinessContext class and registered it as scoped. A factory is responsible for creating it with the needed data.
DON'T DO THIS:
If you are really crazy, maybe this could help you for migration.
.net core 3.1 How to add HttpContext.Current and HttpContext.Current.Application[ ]
First, register the service in Startup.cs,
services.AddHttpContextAccessor();
Then you can call below code in any class, it replaces HttpContext.Current
private HttpContext _httpContext => new HttpContextAccessor().HttpContext;
You can use _httpContext.Items[]
instead of Application. (Test this before production)
how to use HttpContext.Current in net core 5 (no necromenssing)
Inject the IHttpContextAccessor
type and read its HttpContext
property.
Related Topics
Deserializing Json Data to C# Using Json.Net
If Async-Await Doesn't Create Any Additional Threads, Then How Does It Make Applications Responsive
How to Increase the Max Upload File Size in Asp.Net
Difference Between Shadowing and Overriding in C#
Find Control by Name from Windows Forms Controls
How to Get the Cpu Usage in C#
Is There Any Significant Difference Between Using If/Else and Switch-Case in C#
How to Handle Accessviolationexception
A Generic Error Occurred in Gdi+, Jpeg Image to Memorystream
How to Specify a Custom Location to "Search For Views" in ASP.NET MVC
How to Split CSV Whose Columns May Contain ,
C# Getting the Path of %Appdata%
Best Timer For Using in a Windows Service
What's the Difference Between an Object Initializer and a Constructor
Compare Two List≪T≫ Objects For Equality, Ignoring Order
C# Constructor Execution Order