如何获得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。