c# - net - inject httpcontextaccessor




Accéder au contexte HttpContext actuel dans ASP.NET Core (4)

J'ai besoin d'accéder à HttpContext actuel HttpContext une méthode statique ou un service public.

Avec ASP.NET MVC et System.Web classiques, je voudrais simplement utiliser HttpContext.Current pour accéder au contexte de manière statique. Mais comment puis-je faire cela dans ASP.NET Core?

https://code.i-harness.com


En démarrage

services.AddHttpContextAccessor();

Dans le contrôleur

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


Nécromancie.
OUI, VOUS POUVEZ
Astuce secrète pour les grands migrants jonques morceaux (soupir, feuillet freudien) de code.
La méthode suivante est un méchant oncle de hack qui est activement engagé dans le travail express de satan (aux yeux des développeurs du framework .NET Core), mais cela fonctionne :

En public class Startup

ajouter une propriété

public IConfigurationRoot Configuration { get; }

Et puis ajoutez un singleton IHttpContextAccessor à DI dans 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>();

Puis dans Configure

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

ajoutez le paramètre DI IServiceProvider svp , de sorte que la méthode se présente comme IServiceProvider svp :

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

Ensuite, créez une classe de remplacement pour 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 


}

Maintenant, dans Configure, où vous avez ajouté le IServiceProvider svp , enregistrez ce fournisseur de services dans la variable statique "ServiceProvider" de la classe factice System.Web.HttpContext que vous venez de créer (System.Web.HttpContext.ServiceProvider)

et définissez HostingEnvironment.IsHosted sur true

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

c'est essentiellement ce que System.Web a fait, mais vous ne l'avez jamais vu (je suppose que la variable a été déclarée comme étant interne plutôt que publique).

// 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

    });

Comme dans les Web-Forms ASP.NET, vous obtenez un NullReference lorsque vous essayez d'accéder à un HttpContext lorsqu'il n'y en a aucun, tel qu'il était auparavant dans Application_Start dans global.asax.

Je souligne encore, cela ne fonctionne que si vous avez réellement ajouté

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

comme je l'ai écrit, tu devrais.
Bienvenue dans le modèle ServiceLocator dans le modèle DI;)
Pour github.com/aspnet risques et les effets indésirables, adressez-vous à votre médecin ou à votre pharmacien - ou étudiez les sources de .NET Core à l' github.com/aspnet , puis effectuez des tests.

Peut-être une méthode plus maintenable serait-elle d'ajouter cette classe d'aide

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


    }


}

Et puis en appelant HttpContext.Configure dans 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>()
    );

Selon cet article: Accès à HttpContext en dehors des composants d'infrastructure dans 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;
        }
    }
}

Ensuite:

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

Ensuite:

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseStaticHttpContext();
        app.UseMvc();
    }
}

Vous pouvez l'utiliser comme ceci:

using System.Web;

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






asp.net-core