如何在 ASP.NET Core 中获取 HttpContext.Current?
How to get HttpContext.Current in ASP.NET Core?
我们目前 rewriting/converting 我们的 ASP.NET WebForms 应用程序使用 ASP.NET 核心。尽量避免重新设计。
有一节我们在 class 库中使用 HttpContext
来检查当前状态。如何在 .NET Core 1.0 中访问 HttpContext.Current
?
var current = HttpContext.Current;
if (current == null)
{
// do something here
// string connection = Configuration.GetConnectionString("MyDb");
}
我需要访问它才能构建当前应用程序主机。
$"{current.Request.Url.Scheme}://{current.Request.Url.Host}{(current.Request.Url.Port == 80 ? "" : ":" + current.Request.Url.Port)}";
作为一般规则,将 Web 窗体或 MVC5 应用程序转换为 ASP.NET 核心 将需要 大量重构。
HttpContext.Current
已在 ASP.NET 核心中删除。从单独的 class 库访问当前 HTTP 上下文是 ASP.NET Core 试图避免的那种混乱的架构。在 ASP.NET Core.
中有几种方法可以重新构建它
HttpContext 属性
您可以通过任何控制器上的 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
}
中间件中的 HttpContext 参数
如果您正在为 ASP.NET 核心管道编写 custom middleware,则当前请求的 HttpContext
会自动传递到您的 Invoke
方法中:
public Task Invoke(HttpContext context)
{
// Do something with the current HTTP context...
}
HTTP 上下文访问器
最后,您可以使用 IHttpContextAccessor
帮助程序服务获取任何 class 中由 ASP.NET 核心依赖注入系统管理的 HTTP 上下文。当您有控制器使用的公共服务时,这很有用。
在您的构造函数中请求此接口:
public MyMiddleware(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
然后您可以安全地访问当前的 HTTP 上下文:
var context = _httpContextAccessor.HttpContext;
// Do something with the current HTTP context...
默认情况下,IHttpContextAccessor
并不总是添加到服务容器中,因此为了安全起见,请在 ConfigureServices
中注册它:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
// if < .NET Core 2.2 use this
//services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Other code...
}
如果您确实需要对当前上下文的静态访问,则有一个解决方案。
在 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;
希望对您有所帮助。请记住,此解决方法适用于您别无选择的情况。最佳实践是使用去依赖注入。
死灵法术。
是的,你可以,这就是方法。
给迁移大型 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>()
);
我们目前 rewriting/converting 我们的 ASP.NET WebForms 应用程序使用 ASP.NET 核心。尽量避免重新设计。
有一节我们在 class 库中使用 HttpContext
来检查当前状态。如何在 .NET Core 1.0 中访问 HttpContext.Current
?
var current = HttpContext.Current;
if (current == null)
{
// do something here
// string connection = Configuration.GetConnectionString("MyDb");
}
我需要访问它才能构建当前应用程序主机。
$"{current.Request.Url.Scheme}://{current.Request.Url.Host}{(current.Request.Url.Port == 80 ? "" : ":" + current.Request.Url.Port)}";
作为一般规则,将 Web 窗体或 MVC5 应用程序转换为 ASP.NET 核心 将需要 大量重构。
HttpContext.Current
已在 ASP.NET 核心中删除。从单独的 class 库访问当前 HTTP 上下文是 ASP.NET Core 试图避免的那种混乱的架构。在 ASP.NET Core.
HttpContext 属性
您可以通过任何控制器上的 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
}
中间件中的 HttpContext 参数
如果您正在为 ASP.NET 核心管道编写 custom middleware,则当前请求的 HttpContext
会自动传递到您的 Invoke
方法中:
public Task Invoke(HttpContext context)
{
// Do something with the current HTTP context...
}
HTTP 上下文访问器
最后,您可以使用 IHttpContextAccessor
帮助程序服务获取任何 class 中由 ASP.NET 核心依赖注入系统管理的 HTTP 上下文。当您有控制器使用的公共服务时,这很有用。
在您的构造函数中请求此接口:
public MyMiddleware(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
然后您可以安全地访问当前的 HTTP 上下文:
var context = _httpContextAccessor.HttpContext;
// Do something with the current HTTP context...
默认情况下,IHttpContextAccessor
并不总是添加到服务容器中,因此为了安全起见,请在 ConfigureServices
中注册它:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
// if < .NET Core 2.2 use this
//services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Other code...
}
如果您确实需要对当前上下文的静态访问,则有一个解决方案。 在 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;
希望对您有所帮助。请记住,此解决方法适用于您别无选择的情况。最佳实践是使用去依赖注入。
死灵法术。
是的,你可以,这就是方法。
给迁移大型 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.Configurepublic 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>()
);