如何获取HttpContext。目前在ASP。网络核心?

我们目前正在重写/转换我们的ASP。NET WebForms应用程序使用ASP。净的核心。尽量避免重新设计。

有一节中,我们使用类库中的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)}";
398921 次浏览

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

HttpContext.Current在ASP. exe中被删除。净的核心。从一个单独的类库访问当前的HTTP上下文是ASP。NET Core尽量避免。有几种方法可以在ASP中重新构建它。净的核心。

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. xml编写定制中间件。NET核心管道,当前请求的HttpContext会自动传递给你的Invoke方法:

public Task Invoke(HttpContext context)
{
// Do something with the current HTTP context...
}

HTTP上下文访问器

最后,你可以使用IHttpContextAccessor帮助服务来获取ASP管理的任何类中的HTTP上下文。NET核心依赖注入系统。当您的控制器使用一个公共服务时,这很有用。

在构造函数中请求这个接口:

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(…)< / p >
app.Use(async (httpContext, next) =>
{
CallContext.LogicalSetData("CurrentContextKey", httpContext);
try
{
await next();
}
finally
{
CallContext.FreeNamedDataSlot("CurrentContextKey");
}
});

当你需要它的时候,你可以用:

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

我希望这对你有所帮助。请记住,这种变通方法是在你别无选择的情况下。最佳实践是使用非依赖注入。

< p > Necromancing。
是的,你可以,这就是方法。
对于那些迁移大型舢板代码块的秘密提示:
下面的方法是一个邪恶的红宝石,它积极地从事着撒旦的工作(在。net核心框架开发人员的眼中),但这是可行的:

public class Startup

添加属性

public IConfigurationRoot Configuration { get; }

然后在ConfigureServices中的DI中添加一个单例IHttpContextAccessor。

    // 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创建一个替换类。网络:

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中的静态变量“ServiceProvider”中

并设置HostingEnvironment。IsHosted为true

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

这就是系统的本质。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中。当你试图访问一个没有HttpContext的时候,你会得到一个NullReference,比如在global.asax中的Application_Start中。

我再强调一下,这只有在你添加的时候才有效

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

就像我写的你应该。
欢迎来到DI模式中的ServiceLocator模式;)
关于风险和副作用,请咨询您的住院医生或药剂师-或在github.com/aspnet研究。net Core的来源,并做一些测试。< / p >


也许更容易维护的方法是添加这个helper类

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




}




}

然后调用HttpContext。在Startup中配置->配置

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