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...
}
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..
}
}
Access the current HttpContext in ASP.NET Core with Custom
Some points you need to pay attention to:
1.You class inherit from an interface and implement a GetDataFromSession
method.You need to define an interface IMyComponent
first and register IMyComponent
in staryup if you would like use by DI
public interface IMyComponent
{
string GetDataFromSession();
}
startup.cs
services.AddSingleton<IMyComponent, MyComponent>();
2.It seems that you would like to get data from session. The "Key" represents any session name (string).You need to enable session for asp.net core and set a session value first.
_contextAccessor.HttpContext.Session.SetString("Key", "value");
3.Register IHttpContextAccessor
in your startup
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
4.Full demo:
MyComponent.cs
public class MyComponent : IMyComponent
{
private readonly IHttpContextAccessor _contextAccessor;
public MyComponent(IHttpContextAccessor contextAccessor)
{
_contextAccessor = contextAccessor;
}
public string GetDataFromSession()
{
_contextAccessor.HttpContext.Session.SetString("Key", "value");
return _contextAccessor.HttpContext.Session.GetString("Key");
}
}
public interface IMyComponent
{
string GetDataFromSession();
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
// Set a short timeout for easy testing.
options.IdleTimeout = TimeSpan.FromSeconds(10);
options.Cookie.HttpOnly = true;
// Make the session cookie essential
options.Cookie.IsEssential = true;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IMyComponent, MyComponent>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//other middlewares
app.UseSession();
app.UseMvc();
}
}
API Controller:
public class ForumsController : ControllerBase
{
private readonly IMyComponent _myComponent;
public ForumsController(IMyComponent myComponent)
{
_myComponent = myComponent;
}
// GET api/forums
[HttpGet]
public ActionResult<string> Get()
{
var data = _myComponent.GetDataFromSession();//call method and return "value"
return data;
}
How to access current HttpContext in ASP.NET Core 2 Custom Policy-Based Authorization with AuthorizationHandlerContext
You should inject an instance of an IHttpContextAccessor into your AuthorizationHandler
.
In the context of your example, this may look like the following:
public class BadgeEntryHandler : AuthorizationHandler<EnterBuildingRequirement>
{
IHttpContextAccessor _httpContextAccessor = null;
public BadgeEntryHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(
AuthorizationContext context,
EnterBuildingRequirement requirement)
{
HttpContext httpContext = _httpContextAccessor.HttpContext; // Access context here
if (context.User.HasClaim(c => c.Type == ClaimTypes.BadgeId &&
c.Issuer == "http://microsoftsecurity"))
{
context.Succeed(requirement);
return Task.FromResult(0);
}
}
}
You may need to register this in your DI setup (if one of your dependencies has not already), as follows:
services.AddHttpContextAccessor();
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.
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.
Related Topics
How to Use Reflection to Invoke a Private Method
Given a Filesystem Path, Is There a Shorter Way to Extract the Filename Without Its Extension
Deciding Between Httpclient and Webclient
What's the Difference Between the 'Ref' and 'Out' Keywords
Show/Hide the Console Window of a C# Console Application
How to Add a New Row to Datagridview Programmatically
Random.Next Returns Always the Same Values
Replacing .Net Webbrowser Control With a Better Browser, Like Chrome
Difference Between Covariance & Contra-Variance
Make a Borderless Form Movable
How Expensive Are Exceptions in C#
Why Must "Stride" in the System.Drawing.Bitmap Constructor Be a Multiple of 4
Use Linq to Xml With Xml Namespaces
Mock Httpcontext.Current in Test Init Method