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

C# 访问ASP.NET核心中的当前HttpContext,c#,asp.net-core,C#,Asp.net Core,我需要在静态方法或实用程序服务中访问当前的HttpContext 使用经典的ASP.NET MVC和System.Web,我只需使用HttpContext.Current静态访问上下文。但是如何在ASP.NET Core中做到这一点呢?HttpContext。当前的在ASP.NET Core中不再存在,但有一个新的,您可以将其注入依赖项中,并用于检索当前的HttpContext: public class MyComponent : IMyComponent { private read

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


使用经典的ASP.NET MVC和
System.Web
,我只需使用
HttpContext.Current
静态访问上下文。但是如何在ASP.NET Core中做到这一点呢?

HttpContext。当前的
在ASP.NET Core中不再存在,但有一个新的,您可以将其注入依赖项中,并用于检索当前的
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核心框架开发人员眼中)的快速工作,但它有效

公共类启动中

添加属性

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


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

与ASP.NET Web表单中一样,当您尝试访问一个HttpContext时,如果没有HttpContext,则会得到一个空引用,例如它以前在global.asax中的
Application\u Start

我再次强调,只有当你真的添加了

services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();
然后在启动->配置中调用HttpContext.Configure

    public void Configure(
              IApplicationBuilder app
             ,IHostingEnvironment env
             ,ILoggerFactory loggerFactory
    )
    {
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>()
    );
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂、IServiceProvider svp)
{
loggerFactory.AddConsole(Configuration.GetSection(“Logging”);
loggerFactory.AddDebug();
System.Web.HttpContext.Configure(app.ApplicationServices)。
GetRequiredService()
);

我想到的最合法的方法是在静态实现中注入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>());
HttpHelper.Configure(app.ApplicationServices.GetRequiredService());
我想您还需要注册服务singleton:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton();

只需添加到其他答案中

在ASP.NET Core 2.1中,将使用正确的生存期注册
IHttpContextAccessor

公共类启动
{
public void配置服务(IServiceCollection服务)
{
AddHttpContextAccessor();
//其他代码。。。
}
}

根据本文:

然后:

您可以这样使用它:

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

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

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

  • 访问会话对象:

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

    Startup.cs

    public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
        }
    
    public class YourClass {
          
           public string yourProperty {
                 get{
                     IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
                     return _httpContextAccessor.HttpContext.Session.GetString("_YourSessionVar");         
                    }
            }
      }
    

    享受:)

    这一点很好!值得一提的是,
    IHttpContextAccessor
    仅在DI容器解析实例的地方可用。@tugberk好吧,理论上,您也可以使用
    CallContextServiceLocator
    解析服务,即使是从非注入DI的实例:
    CallContextServiceLocator.Locator.ServiceProvider.GetService()
    。实际上,如果可以避免,这是一件好事:)不要使用CallContextServiceLocator@davidfowl除非你有一个有效的技术理由(当然除了“静态是邪恶的”之外),我打赌人们会在没有其他选择的情况下使用它。当然,人们很少有有效的技术理由。这更像是使用静态更容易,而且谁关心可测试性:)这是一个纯粹的问题,带有helper方法的版本在每种情况下都能正常工作。考虑多线程、异步和IoC容器中的服务不同的一生?我知道我们都必须指出这是多么邪恶…但是如果你把一个巨大的项目移植到核心,在那里HttpContext.Current被用在一些难以达到的静态类中…这可能会非常有用。我说过了。这是纯粹的邪恶…我要解释的是适当的我喜欢DI和IoC…但我正在处理一个带有邪恶静态变量的邪恶静态类的遗留应用程序,我们需要使用Kestrel推送并尝试注入HttpContext,这对我们来说是不可撤销的,不会破坏一切。是的,这是迁移的正确答案。;)很高兴看到一个更正式的替代方案对于撒旦红玉!@Ken Lyon:;)khellang:Singleton是正确的生命周期。作用域将是错误的。或者至少在撰写本文时是错误的。但是如果AddHttpContextAccessor正确地执行它,而不需要我们对特定框架版本的引用,那就更好了。你能分享一个例子吗?@Toolkit添加了一些示例MPE代码。不确定它在上面的文本中提供了什么价值。工作起来很有魅力-谢谢!
    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();
            }
       }
    
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
    IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
    
    string mySessionVar = _httpContextAccessor.HttpContext.Session.GetString("_MySessionVar");
    
    public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    
        }
    
    public class YourClass {
          
           public string yourProperty {
                 get{
                     IHttpContextAccessor _httpContextAccessor = new HttpContextAccessor();
                     return _httpContextAccessor.HttpContext.Session.GetString("_YourSessionVar");         
                    }
            }
      }