How to get HttpContext.Current in ASP.NET Core?

We are currently rewriting / converting our ASP.NET WebForms application using ASP.NET Core. Try to avoid reengineering as much as possible.

There is a section in which we use the HttpContext in the class library to check the current state. How can I access HttpContext.Current in .NET Core 1.0?

  var current = HttpContext.Current; if (current == null) { // do something here // string connection = Configuration.GetConnectionString("MyDb"); } 

I need to access this in order to create the current application host.

 $"{current.Request.Url.Scheme}://{current.Request.Url.Host}{(current.Request.Url.Port == 80 ? "" : ":" + current.Request.Url.Port)}"; 
+156
c # asp.net-core .net-core
Jul 25 '16 at 2:53 on
source share
3 answers

Converting a Web Forms or MVC5 application to ASP.NET Core will typically require a significant amount of refactoring.

HttpContext.Current been removed in ASP.NET Core. Accessing the current HTTP context from a separate class library is a type of dirty architecture that ASP.NET Core is trying to avoid. There are several ways to rebuild this in ASP.NET Core.

HttpContext Property

You can access the current HTTP context through the HttpContext property on any controller. The one closest to your original HttpContext code will pass the HttpContext to the method you call:

 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 are writing custom middleware for an ASP.NET Core pipeline, the current HttpContext request HttpContext passed to your Invoke method:

 public Task Invoke(HttpContext context) { // Do something with the current HTTP context... } 

HTTP context accessor

Finally, you can use the IHttpContextAccessor helper service to retrieve the HTTP context in any class that is controlled by the ASP.NET Core dependency injection system. This is useful when you have a shared service used by your controllers.

Request this interface in your constructor:

 public MyMiddleware(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } 

Then you can access the current HTTP context in a safe way:

 var context = _httpContextAccessor.HttpContext; // Do something with the current HTTP context... 

IHttpContextAccessor not always added to the default service container, so register it with ConfigureServices just for security:

 public void ConfigureServices(IServiceCollection services) { services.AddHttpContextAccessor(); // if < .NET Core 2.2 use this //services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // Other code... } 
+199
Jul 25 '16 at 17:57
source

Necromancing.

YES YOU CAN, and here's how.

Secret advice for those who carry large pieces junks :
The next method is the evil hacking carbuncle, which is actively involved in the express work of Satan (in the eyes of the developers of the .NET Core platform) , but it works :

In public class Startup

add property

 public IConfigurationRoot Configuration { get; } 

And then add the singleton IHttpContextAccessor to the DI in ConfigureServices.

  // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>(); 

Then in Configure

  public void Configure( IApplicationBuilder app ,IHostingEnvironment env ,ILoggerFactory loggerFactory ) { 

add the DI parameter IServiceProvider svp , so the method looks like this:

  public void Configure( IApplicationBuilder app ,IHostingEnvironment env ,ILoggerFactory loggerFactory ,IServiceProvider svp) { 

Then create a replacement class for System.Web:

 namespace System.Web { namespace Hosting { public static class HostingEnvironment { public static bool m_IsHosted; static HostingEnvironment() { m_IsHosted = false; } public static bool IsHosted { get { return m_IsHosted; } } } } public static class HttpContext { public static IServiceProvider ServiceProvider; static HttpContext() { } public static Microsoft.AspNetCore.Http.HttpContext Current { get { // var factory2 = ServiceProvider.GetService<Microsoft.AspNetCore.Http.IHttpContextAccessor>(); object factory = ServiceProvider.GetService(typeof(Microsoft.AspNetCore.Http.IHttpContextAccessor)); // Microsoft.AspNetCore.Http.HttpContextAccessor fac =(Microsoft.AspNetCore.Http.HttpContextAccessor)factory; Microsoft.AspNetCore.Http.HttpContext context = ((Microsoft.AspNetCore.Http.HttpContextAccessor)factory).HttpContext; // context.Response.WriteAsync("Test"); return context; } } } // End Class HttpContext } 

Now in Configure, where you added IServiceProvider svp , save this service provider in the static variable "ServiceProvider" of the newly created dummy class System.Web.HttpContext (System.Web.HttpContext.ServiceProvider)

and set HostingEnvironment.IsHosted to true

 System.Web.Hosting.HostingEnvironment.m_IsHosted = true; 

this is essentially what System.Web did, you just never saw it (I think the variable was declared as internal, not public).

 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider svp) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); ServiceProvider = svp; System.Web.HttpContext.ServiceProvider = svp; System.Web.Hosting.HostingEnvironment.m_IsHosted = true; app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationScheme = "MyCookieMiddlewareInstance", LoginPath = new Microsoft.AspNetCore.Http.PathString("/Account/Unauthorized/"), AccessDeniedPath = new Microsoft.AspNetCore.Http.PathString("/Account/Forbidden/"), AutomaticAuthenticate = true, AutomaticChallenge = true, CookieSecure = Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest , CookieHttpOnly=false }); 

As in ASP.NET Web-Forms, you will get NullReference when you try to access the HttpContext when it is not there, for example, it was used in Application_Start in global.asax.

I emphasize again: this only works if you really added

 services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>(); 

as I wrote, you must.

Welcome to the ServiceLocator template in the DI template;)
For risks and side effects, contact your resident physician or pharmacist or study the .NET Core sources at github.com/aspnet and perform some tests.




Perhaps a more supported method will add this helper class

 namespace System.Web { public static class HttpContext { private static Microsoft.AspNetCore.Http.IHttpContextAccessor m_httpContextAccessor; public static void Configure(Microsoft.AspNetCore.Http.IHttpContextAccessor httpContextAccessor) { m_httpContextAccessor = httpContextAccessor; } public static Microsoft.AspNetCore.Http.HttpContext Current { get { return m_httpContextAccessor.HttpContext; } } } } 

And then call HttpContext.Configure in Startup-> Configure

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider svp) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); System.Web.HttpContext.Configure(app.ApplicationServices. GetRequiredService<Microsoft.AspNetCore.Http.IHttpContextAccessor>() ); 
+40
Oct 13 '16 at 19:23
source

This is the solution if you really need static access to the current context. In Startup.Configure (....)

 app.Use(async (httpContext, next) => { CallContext.LogicalSetData("CurrentContextKey", httpContext); try { await next(); } finally { CallContext.FreeNamedDataSlot("CurrentContextKey"); } }); 

And when you need it, you can get it with:

 HttpContext context = CallContext.LogicalGetData("CurrentContextKey") as HttpContext; 

Hope this helps. Keep in mind that this workaround is when you have no choice. Best practice is to use dependency injection.

+8
Sep 19 '16 at 10:28
source



All Articles