访问 ASP.NET Core 中的当前 HttpContext

本文关键字:HttpContext ASP NET Core 访问 | 更新日期: 2023-09-27 18:01:22

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

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

访问 ASP.NET Core 中的当前 HttpContext

HttpContext.Current

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

然后将单例 IHttpContextAccessor 添加到 ConfigureServices 中的 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 创建一个替换类:

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 

}

现在,在配置中,您在其中添加了IServiceProvider svp,将此服务提供程序保存到刚刚创建的虚拟类System.Web.HttpContext(System.Web.HttpContext.ServiceProvider(中的静态变量"ServiceProvider"中。

并将 HostingEnvironment.IsHosted 设置为 true

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

这基本上是System.Web所做的,只是你从未见过它(我猜变量被声明为内部而不是公共(。

// 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 窗体中一样,当您尝试访问 HttpContext 时,如果没有 HttpContext,您将获得一个 NullReference,例如它曾经在 global.asax 中的Application_Start中。

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

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

就像我写的你应该。
欢迎使用 DI 模式 ;)
中的服务定位器模式有关风险和副作用,请咨询住院医生或药剂师 - 或在 github.com/aspnet 研究 .NET Core 的来源,并进行一些测试。

<小时 />

也许更易于维护的方法是添加此帮助程序类

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中,有AddHttpContextAccessor扩展方法,该方法将注册具有正确生存期的IHttpContextAccessor

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

根据这篇文章:在 ASP.NET 核心框架组件之外访问HttpContext。

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

若要从类访问会话对象而不在类构造函数中显式使用依赖项注入,请执行以下步骤:

  1. 在启动时添加单一实例.cs (配置服务(:

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

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

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

启动.cs

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

你的班级.cs

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

享受:)