Открыть текущий объект HttpContext в ASP.NET основной


мне нужно получить доступ к текущему HttpContext в статическом методе или служебной службе.

С классикой ASP.NET MVC и System.Web, Я бы просто использовать HttpContext.Current для статического доступа к контексту. Но как мне это сделать в ASP.NET ядро?

4 74

4 ответа:

HttpContext.Current больше не существует в ASP.NET ядро, но есть новый 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 framework),но он работает:

на public class Startup

добавить свойство

public IConfigurationRoot Configuration { get; }

а затем добавить синглтон IHttpContextAccessor для DI в 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>();

затем в Configure

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

добавить параметр DI IServiceProvider svp, поэтому метод выглядит так:

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

затем создайте класс замены для System.Веб-сайт:

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, сохраните этого поставщика услуг в статической переменной "ServiceProvider" в только что созданной фиктивной системе классов.Сеть.HttpContext (Система.Сеть.HttpContext.Поставщику услуги)

и установите HostingEnvironment.Размещение в true

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

это по сути системы.Веб сделал, только что вы никогда не видели его (я думаю, переменная была объявлена как внутренняя, а не публичная).

// 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 веб-формы, вы получите NullReference, когда вы пытаетесь получить доступ к HttpContext, когда его нет, например, как это было в Application_Start в глобальном.асакс.

я подчеркиваю опять же, это работает только если вы на самом деле добавил

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

как я и писал, Вы должны.
Добро пожаловать в шаблон ServiceLocator в шаблоне DI;)
Чтобы узнать о рисках и побочных эффектах, обратитесь к врачу-резиденту или фармацевту - или изучите источники .NET Core по адресу github.com/aspnet, и сделать некоторые испытания.


возможно, более поддерживаемый метод будет добавлять этот вспомогательный класс

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


    }


}

а потом звонит HttpContext.Настройка при запуске- > настроить

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

просто добавить к другим ответам...

In ASP.NET ядро 2.1, есть the AddHttpContextAccessor метод расширения, что будет регистрировать IHttpContxtAccessor с правильной жизни.

наиболее законным способом, который я придумал, было введение IHttpContextAccessor в вашу статическую реализацию следующим образом:

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

     public static HttpContext HttpContext => _accessor.HttpContext;
}

затем назначение IHttpContextAccessor в Startup Configure должно выполнить эту работу.

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

Я думаю, вам также нужно зарегистрировать сервис singleton:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();