访问 ASP.NET 核心中的当前 HttpContext

Access the current HttpContext in ASP.NET Core

我需要在静态方法或实用程序服务中访问当前 HttpContext

使用经典的 ASP.NET MVC 和 System.Web,我将只使用 HttpContext.Current 来静态访问上下文。但是我如何在 ASP.NET Core 中执行此操作?

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

死灵法术。
是的,你可以
那些迁移大量 junks 代码块(叹气,弗洛伊德式失误)代码的秘密提示。
以下方法是一个黑客的邪恶的痈肿,积极从事撒旦的快速工作(在 .NET Core 框架开发人员的眼中),但它有效:

public class Startup

添加一个属性

public IConfigurationRoot Configuration { get; }

然后在ConfigureServices中添加一个单例IHttpContextAccessor到DI。

    // 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 创建一个替换 class:

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,将此服务提供商保存到刚刚创建的虚拟 class System.Web.HttpContext 中的静态变量 "ServiceProvider" 中( System.Web.HttpContext.ServiceProvider)

并将 HostingEnvironment.IsHosted 设置为真

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

这基本上就是 System.Web 所做的,只是您从未见过它(我猜该变量被声明为内部变量而不是 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

    });

就像在 ASP.NET Web 表单中一样,当您尝试访问存在 none 的 HttpContext 时,您将获得一个 NullReference,例如它曾经在 [=23] =] 在 global.asax.

我再次强调,这只有在您实际添加

时才有效
services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();

就像我写给你的那样。
欢迎使用 DI 模式中的 ServiceLocator 模式 ;)
对于风险和副作用,请咨询您的住院医生或药剂师 - 或者在 github.com/aspnet 上研究 .NET Core 的来源,并进行一些测试。


也许更易于维护的方法是添加此助手 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;
            }
        }


    }


}

然后在Startup->Configure

中调用HttpContext.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>()
    );

我想到的最合法的方法是在静态实现中注入 IHttpContextAccessor,如下所示:

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

     public static HttpContext HttpContext => _accessor.HttpContext;
}

然后在启动配置中分配 IHttpContextAccessor 应该可以完成工作。

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

我猜你还需要注册服务单例:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

只是添加到其他答案...

在 ASP.NET Core 2.1 中,有 the AddHttpContextAccessor extension method,它将用正确的生命周期注册 IHttpContextAccessor

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

        // Other code...
    }
}

根据这篇文章: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;
        }
    }
}

然后:

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

然后:

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

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

你可以这样使用它:

using System.Web;

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

正在启动中

services.AddHttpContextAccessor();

在控制器中

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

要从 class 访问会话对象而不在 class 构造函数中显式使用依赖注入,请按照以下步骤操作:

  1. 在 Startup.cs (ConfigureServices) 上添加单例实例:

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
  2. 在您的目标中 class 声明一个 HttpContextAccessor 实例:

    IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
    
  3. 访问会话对象:

    string mySessionVar = _httpContextAccessor.HttpContext.Session.GetString("_MySessionVar");
    

示例

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    }

YourClass.cs

public class YourClass {
      
       public string yourProperty {
             get{
                 IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
                 return _httpContextAccessor.HttpContext.Session.GetString("_YourSessionVar");         
                }
        }
  }

尽情享受吧:)