如何获得ASP.NET核心中的HttpContext.Current?

我们目前正在使用ASP.NET Core重写/转换我们的ASP.NET WebForms应用程序。 尽量避免重新devise。

有一个部分我们在类库中使用HttpContext来检查当前状态。 如何在.NET Core 1.0中访问HttpContext.Current

  var current = HttpContext.Current; if (current == null) { // do something here // string connection = Configuration.GetConnectionString("MyDb"); } 

我需要访问这个为了构build当前的应用程序主机。

 $"{current.Request.Url.Scheme}://{current.Request.Url.Host}{(current.Request.Url.Port == 80 ? "" : ":" + current.Request.Url.Port)}"; 

作为一般规则,将Web窗体或MVC5应用程序转换为ASP.NET Core 将需要大量的重构。

获取HttpContext.Current是不可能的,因为在ASP.NET Core中删除了Current 。 从单独的类库访问当前HTTP上下文是ASP.NET Core试图避免的混乱体系结构的types。

在ASP.NET Core中,可以使用HttpContext从控制器访问当前HTTP上下文。 最接近你原来的代码示例是将HttpContext传递给你正在调用的方法:

 public class HomeController : Controller { public IActionResult Index() { MyMethod(HttpContext); // Other code } } public void MyMethod(Microsoft.AspNetCore.Http.HttpContext context) { var host = $"{context.Request.Scheme}://{context.Request.Host}"; // Other code } 

也可以使用ASP.NET Coredependency injection系统中的IHttpContextAccessor获取上下文。 如果您有一个从服务容器请求接口的控制器或中间件function:

 public MyMiddleware(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } 

然后您可以安全地访问当前的HTTP上下文:

 var context = _httpContextAccessor.HttpContext; 

由于默认情况下IHttpContextAccessor未被添加到服务容器,因此您必须注册它:

 public void ConfigureServices(IServiceCollection services) { services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // Other code... } 

Necromancing。
是的,你可以,这是如何。
为那些迁徙的人提供一个秘密小费 帆船 代码块:
下面的方法是积极从事开发撒旦(在.NET核心框架开发人员眼中)的快速工作的黑客的邪恶carb but但它的工作原理是

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

然后在configuration中

  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创build一个replace类:

 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 Configure中,将此服务提供者保存到刚创build的虚拟类System.Web.HttpContext(System.Web.HttpContext.ServiceProvider)中的静态variables“ServiceProvider”

并将HostingEnvironment.IsHosted设置为true

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

这基本上是System.Web做的,只是你从来没有看到它(我猜这个variables被声明为内部而不是公共的)。

 // 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中一样,当你尝试访问一个没有的HttpContext的时候,你会得到一个NullReference,比如它曾经在Global.asax的Application_Start中。

我再次强调,这只有在你实际添加的情况下才有效

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

像我写你应该。
欢迎使用DI模式中的ServiceLocator模式;)
有关风险和副作用,请咨询您的驻地医生或药剂师 – 或者在github.com/aspnet上学习.NET Core的源代码 ,并进行一些testing。


也许更可维护的方法是添加这个辅助类

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

如果你真的需要静态访问当前的上下文,有一个解决scheme。 在Startup.Configure(…。)

 app.Use(async (httpContext, next) => { CallContext.LogicalSetData("CurrentContextKey", httpContext); try { await next(); } finally { CallContext.FreeNamedDataSlot("CurrentContextKey"); } }); 

而当你需要它时,你可以得到它:

 HttpContext context = CallContext.LogicalGetData("CurrentContextKey") as HttpContext; 

我希望有帮助。 请记住,这个解决方法是当你没有select。 最好的做法是使用dedependency injection。