Programming

ASP.NET Core에서 현재 HttpContext에 액세스

procodes 2020. 8. 7. 21:52
반응형

ASP.NET Core에서 현재 HttpContext에 액세스


HttpContext정적 메서드 또는 유틸리티 서비스에서 current 액세스해야합니다 .

클래식 ASP.NET MVC 및 System.Web에서는 HttpContext.Current컨텍스트에 정적으로 액세스하는 데 사용 합니다. 하지만 ASP.NET Core에서 어떻게해야합니까?


HttpContext.CurrentASP.NET Core에는 더 이상 존재하지 않지만 IHttpContextAccessor종속성에 삽입하고 현재 검색하는 데 사용할 수 있는 새로운 기능 이 있습니다 HttpContext.

public class MyComponent : IMyComponent
{
    private readonly IHttpContextAccessor _contextAccessor;

    public MyComponent(IHttpContextAccessor contextAccessor)
    {
        _contextAccessor = contextAccessor;
    }

    public string GetDataFromSession()
    {
        return _contextAccessor.HttpContext.Session.GetString(*KEY*);
    }
}

네크 로맨싱.
예,
대규모 마이그레이션을위한 비밀 팁정크코드 덩어리 (한숨, 프로이트 슬립).
다음 방법은 (.NET Core 프레임 워크 개발자의 관점에서) 사탄의 표현적인 작업을 수행하는 데 적극적으로 관여하는 해킹의 사악한 카 벙클 이지만 작동합니다 .

public class Startup

속성 추가

public IConfigurationRoot Configuration { get; }

그런 다음 ConfigureServices의 DI에 싱글 톤 IHttpContextAccessor를 추가합니다.

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

그런 다음 구성에서

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

DI 매개 변수를 추가하면 IServiceProvider svp방법은 다음과 같습니다.

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

다음으로 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 


}

이제 Configure에서를 추가 한 다음 IServiceProvider svp이 서비스 공급자를 방금 만든 더미 클래스 System.Web.HttpContext (System.Web.HttpContext.ServiceProvider)의 정적 변수 "ServiceProvider"에 저장합니다.

HostingEnvironment.IsHosted를 true로 설정하십시오.

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

이것은 본질적으로 System.Web이 한 일이며, 당신이 본 적이 없다는 것입니다 (변수가 public 대신 internal로 선언 된 것 같습니다).

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

    });

ASP.NET Web-Forms와 마찬가지로 Application_Startglobal.asax 있던 것과 같이 HttpContext가 없을 때 HttpContext에 액세스하려고 할 때 NullReference를 얻게됩니다 .

I stress again, this only works if you actually added

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

like I wrote you should.
Welcome to the ServiceLocator pattern within the DI pattern ;)
For risks and side effects, ask your resident doctor or pharmacist - or study the sources of .NET Core at github.com/aspnet, and do some testing.


Perhaps a more maintainable method would be adding 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 calling 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>()
    );

Just to add to the other answers...

In ASP.NET Core 2.1, there's the AddHttpContextAccessor extension method, that will register the IHttpContextAccessor with the correct lifetime.


The most legit way I came up with was by injecting IHttpContextAccessor in your static implementation as follow:

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

     public static HttpContext HttpContext => _accessor.HttpContext;
}

Then assigning the IHttpContextAccessor in the Startup Configure should do the job.

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

I guess you should also need to register the service singleton:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

According to this article: Accessing HttpContext outside of framework components in 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;
        }
    }
}

Then:

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

Then:

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

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

You can use it like this:

using System.Web;

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

In Startup

services.AddHttpContextAccessor();

In Controller

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

참고URL : https://stackoverflow.com/questions/31243068/access-the-current-httpcontext-in-asp-net-core

반응형