Как получить HttpContext.Ток внутри ASP.NET ядро? [дубликат]
этот вопрос уже есть ответ здесь:
в настоящее время мы переписываем / преобразуем наши ASP.NET использование приложения WebForms ASP.NET ядро. Стараясь избежать реинжиниринга как можно больше.
есть раздел, где мы используем HttpContext в библиотеке классов для проверки текущего состояния. Как я могу получить доступ HttpContext.Current в .NET Core 1.0?
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)}";
3 ответов:
как правило, преобразование веб-форм или приложения MVC5 в ASP.NET ядро потребуется значительное количество рефакторинга.
HttpContext.Currentбыл удален в ASP.NET ядро. Доступ к текущему контексту HTTP из отдельной библиотеки классов-это тип беспорядочной архитектуры, которая ASP.NET ядро пытается избежать. Есть несколько способов, чтобы повторно спроектировать это ASP.NET ядро.свойство HttpContext
вы можете получить доступ к текущему HTTP контекст через
HttpContextсвойство на любом контроллере. Самое близкое к вашему исходному образцу кода было бы передать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 в middleware
если ты пишешь custom middleware для ASP.NET основной конвейер, текущий запрос
HttpContextпроходит черезInvokeспособ автоматически:public Task Invoke(HttpContext context) { // Do something with the current HTTP context... }http context accessor
наконец, вы можете используйте
IHttpContextAccessorвспомогательная служба для получения контекста HTTP в любом классе, которым управляет ASP.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.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); // Other code... }
некромантии.
Да, вы можете, и вот как.
Секретный совет для тех, кто мигрирует большойджонкикуски кода:
Следующий метод-это злой карбункул взлома, который активно занимается проведением экспрессной работы Сатаны (в глазах разработчиков .NET Core framework),но он работает:на
public class Startupдобавить свойство
public IConfigurationRoot Configuration { get; }а затем добавить синглтон IHttpContextAccessor для DI в ConfigureServices.
// 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>();затем в Configure
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 }теперь в Configure, где вы добавили
IServiceProvider svp, сохраните этого поставщика услуг в статической переменной "ServiceProvider" в только что созданной фиктивной системе классов.Сеть.HttpContext (Система.Сеть.HttpContext.Поставщику услуги)и установите HostingEnvironment.Размещение в true
System.Web.Hosting.HostingEnvironment.m_IsHosted = true;это по сути системы.Веб сделал, только что вы никогда не видели его (я думаю, переменная была объявлена как внутренняя, а не публичная).
// 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 веб-формы, вы получите NullReference, когда вы пытаетесь получить доступ к HttpContext, когда его нет, например, как это было в
Application_Startв глобальном.асакс.я подчеркиваю опять же, это работает только если вы на самом деле добавил
services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();как я и писал, Вы должны.
Добро пожаловать в шаблон ServiceLocator в шаблоне DI;)
Чтобы узнать о рисках и побочных эффектах, обратитесь к врачу-резиденту или фармацевту - или изучите источники .NET Core по адресу github.com/aspnet, и сделать некоторые испытания.
возможно, более поддерживаемый метод будет добавлять этот вспомогательный класс
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.Настройка при запуске- > настроить
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>() );
есть решение для этого, если вам действительно нужен статический доступ к текущему контексту. В Стартапе.Формировать.…()
app.Use(async (httpContext, next) => { CallContext.LogicalSetData("CurrentContextKey", httpContext); try { await next(); } finally { CallContext.FreeNamedDataSlot("CurrentContextKey"); } });и когда вам это нужно, вы можете сделать это с :
HttpContext context = CallContext.LogicalGetData("CurrentContextKey") as HttpContext;Я надеюсь, что помогает. Имейте в виду этот способ, когда у вас нет выбора. Лучше всего использовать инъекцию зависимости de.
Comments