Necromancing.
TAK MOŻESZ
Sekretna wskazówka dla migrujących dużych dżunlików kawałków (westchnienie, poślizg Freuda) kodu.
Poniższa metoda jest zła carbuncle hack który jest aktywnie zaangażowany w przeprowadzenie wyraźnej dzieło szatana (w oczach programistów .NET Framework rdzenia), ale działa:
W public class Startup
dodać obiekt
public IConfigurationRoot Configuration { get; }
a następnie dodać pojedyncza IHttpContextAccessor do DI w 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>();
Następnie w Configure
public void Configure(
IApplicationBuilder app
,IHostingEnvironment env
,ILoggerFactory loggerFactory
)
{
dodać DI Parametr IServiceProvider svp
, więc metoda wygląda następująco:
public void Configure(
IApplicationBuilder app
,IHostingEnvironment env
,ILoggerFactory loggerFactory
,IServiceProvider svp)
{
Następnie należy utworzyć klasę zastępczą dla system.Web:
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
}
Teraz w programie Configure, gdzie dodano IServiceProvider svp
, zapisz tego dostawcę usług do zmiennej statycznej "ServiceProvider" w właśnie utworzonej klasie dummy System.Web.HttpContext (System.Web.HttpContext.ServiceProvider)
i ustaw HostingEnvironment. IsHosted do prawdziwej
System.Web.Hosting.HostingEnvironment.m_IsHosted = true;
to zasadniczo co system.Web zrobił, tylko że nigdy nie widział go (chyba zmienna została zadeklarowana jako wewnętrzny zamiast publicznie).
// 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
});
Podobnie jak w ASP.NET Web-Forms, dostaniesz NullReference kiedy próbujesz uzyskać dostęp do HttpContext gdy nie ma nikogo, tak jak kiedyś w Application_Start
w global.asax.
Podkreślam ponownie, to działa tylko wtedy, gdy rzeczywiście dodaje
services.AddSingleton<Microsoft.AspNetCore.Http.IHttpContextAccessor, Microsoft.AspNetCore.Http.HttpContextAccessor>();
jak pisałem powinieneś.
Witamy na wzorzec ServiceLocator w schemacie DI;)
W celu uzyskania informacji o zagrożeniach i działaniach niepożądanych należy zwrócić się do lekarza lub farmaceuty lub przeanalizować źródła .NET Core pod numerem github.com/aspnet i wykonać kilka testów.
Może to metoda bardziej linkujących będzie dodanie tej klasy pomocnika
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;
}
}
}
}
a następnie wywołanie HttpContext.Configure w Startup-> Konfiguracja
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>()
);
Dobra uwaga! Warto również wspomnieć, że 'IHttpContextAccessor' będzie dostępny tylko w miejscach, w których kontener DI rozpoznaje instancję. – tugberk
@tugberk również, teoretycznie można również użyć 'CallContextServiceLocator' do rozwiązania usługi, nawet z instancji nie wstrzykniętej DI:' CallContextServiceLocator.Locator.ServiceProvider.GetService() '. W praktyce jest świetną rzeczą, jeśli możesz tego uniknąć :) –
Pinpoint
Proszę nie zamieszczać identycznych odpowiedzi na wiele pytań. Napisz jedną dobrą odpowiedź, a następnie głosuj/oznacz, aby zamknąć pozostałe pytania jako duplikaty. Jeśli pytanie nie jest duplikatem, * dostosuj swoje odpowiedzi na pytanie *. –