tag page net ihttpcontextaccessor for current asp c# asp.net-core

c# - page - input asp for



Acceda al HttpContext actual en ASP.NET Core (6)

Necesito acceder a HttpContext actual en un método estático o un servicio de utilidad.

Con ASP.NET MVC clásico y System.Web , simplemente usaría HttpContext.Current para acceder al contexto de forma estática. Pero, ¿cómo hago esto en ASP.NET Core?


De acuerdo con este artículo: Acceso a HttpContext fuera de los componentes del marco en ASP.NET Core

namespace System.Web { public static class HttpContext { private static IHttpContextAccessor _contextAccessor; public static Microsoft.AspNetCore.Http.HttpContext Current => _contextAccessor.HttpContext; internal static void Configure(IHttpContextAccessor contextAccessor) { _contextAccessor = contextAccessor; } } }

Entonces:

public static class StaticHttpContextExtensions { public static void AddHttpContextAccessor(this IServiceCollection services) { services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); } public static IApplicationBuilder UseStaticHttpContext(this IApplicationBuilder app) { var httpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>(); System.Web.HttpContext.Configure(httpContextAccessor); return app; } }

Entonces:

public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddHttpContextAccessor(); } public void Configure(IApplicationBuilder app) { app.UseStaticHttpContext(); app.UseMvc(); } }

Puedes usarlo así:

using System.Web; public class MyService { public void DoWork() { var context = HttpContext.Current; // continue with context instance } }


En el inicio

services.AddHttpContextAccessor();

En el controlador

public class HomeController : Controller { private readonly IHttpContextAccessor _context; public HomeController(IHttpContextAccessor context) { _context = context; } public IActionResult Index() { var context = _context.HttpContext.Request.Headers.ToList(); return View(); } }


La forma más legítima que se me ocurrió fue inyectando IHttpContextAccessor en su implementación estática de la siguiente manera:

public static class HttpHelper { private static IHttpContextAccessor _accessor; public static void Configure(IHttpContextAccessor httpContextAccessor) { _accessor = httpContextAccessor; } public static HttpContext HttpContext => _accessor.HttpContext; }

Luego, asignar el IHttpContextAccessor en la Configuración de inicio debería hacer el trabajo.

HttpHelper.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());

Supongo que también deberías necesitar registrar el servicio singleton:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();


Nigromancia
SÍ TU PUEDES
Consejo secreto para aquellos que migran grandes basura trozos (suspiro, deslizamiento freudiano) de código.
El siguiente método es un malvado truco de un hack que participa activamente en la realización del trabajo expreso de satanás (a los ojos de los desarrolladores de .NET Core Framework), pero funciona :

En public class Startup

agregar una propiedad

public IConfigurationRoot Configuration { get; }

Y luego agregue un solo IHttpContextAccessor a DI en 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>();

Luego en Configurar

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

agregue el parámetro DI IServiceProvider svp , para que el método se vea así:

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

A continuación, cree una clase de reemplazo para 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 }

Ahora en Configurar, donde agregó el IServiceProvider svp , guarde este proveedor de servicios en la variable estática "ServiceProvider" en la clase ficticia recién creada System.Web.HttpContext (System.Web.HttpContext.ServiceProvider)

y establezca HostingEnvironment.IsHosted en true

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

esto es esencialmente lo que hizo System.Web, solo que nunca lo viste (supongo que la variable se declaró como interna en lugar de pública).

// 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 });

Al igual que en los formularios web ASP.NET, obtendrá una referencia nula cuando intente acceder a un HttpContext cuando no haya ninguno, como solía estar en Application_Start en global.asax.

Insisto nuevamente, esto solo funciona si realmente agregaste

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

como te escribí deberías.
Bienvenido al patrón ServiceLocator dentro del patrón DI;)
Para conocer los riesgos y los efectos secundarios, consulte a su médico o farmacéutico residente, o estudie las fuentes de .NET Core en github.com/aspnet y realice algunas pruebas.

Quizás un método más fácil de mantener sería agregar esta clase auxiliar

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; } } } }

Y luego llamando a HttpContext.Configure en 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>() );



HttpContext.Current ya no existe en ASP.NET Core, pero hay un nuevo IHttpContextAccessor que puede inyectar en sus dependencias y usar para recuperar el HttpContext actual:

public class MyComponent : IMyComponent { private readonly IHttpContextAccessor _contextAccessor; public MyComponent(IHttpContextAccessor contextAccessor) { _contextAccessor = contextAccessor; } public string GetDataFromSession() { return _contextAccessor.HttpContext.Session.GetString(*KEY*); } }