web-dev-qa-db-de.com

Wie bekomme ich HttpContext.Current in ASP.NET Core?

Wir schreiben/konvertieren derzeit unsere ASP.NET-WebForms-Anwendung mit ASP.NET Core. Versuchen Sie, ein Reengineering so weit wie möglich zu vermeiden.

Es gibt einen Abschnitt, in dem wir HttpContext in einer Klassenbibliothek verwenden, um den aktuellen Status zu überprüfen. Wie kann ich in .NET Core 1.0 auf HttpContext.Current zugreifen?

 var current = HttpContext.Current;
     if (current == null)
      {
       // do something here
       // string connection = Configuration.GetConnectionString("MyDb");
      }

Ich muss darauf zugreifen, um den aktuellen Anwendungshost zu erstellen.

$"{current.Request.Url.Scheme}://{current.Request.Url.Host}{(current.Request.Url.Port == 80 ? "" : ":" + current.Request.Url.Port)}";
165
HaBo

In der Regel ist für die Konvertierung einer Web Forms- oder MVC5-Anwendung in ASP.NET Core ein erheblicher Umgestaltungsaufwand erforderlich .

HttpContext.Current wurde in ASP.NET Core entfernt. Der Zugriff auf den aktuellen HTTP-Kontext über eine separate Klassenbibliothek ist die Art von chaotischer Architektur, die ASP.NET Core zu vermeiden versucht. Es gibt verschiedene Möglichkeiten, dies in ASP.NET Core neu zu gestalten.

HttpContext-Eigenschaft

Sie können auf den aktuellen HTTP-Kontext über die Eigenschaft HttpContext auf einem beliebigen Controller zugreifen. Am nächsten an Ihrem ursprünglichen Codebeispiel wäre es, HttpContext an die aufgerufene Methode zu übergeben:

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-Parameter in der Middleware

Wenn Sie benutzerdefinierte Middleware für die ASP.NET Core-Pipeline schreiben, wird die HttpContext der aktuellen Anforderung automatisch an Ihre Invoke -Methode übergeben:

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

HTTP-Kontext-Accessor

Schließlich können Sie den Hilfsdienst IHttpContextAccessor verwenden, um den HTTP-Kontext in jeder Klasse abzurufen, die vom ASP.NET Core-Abhängigkeitsinjektionssystem verwaltet wird. Dies ist nützlich, wenn Sie über einen gemeinsamen Dienst verfügen, der von Ihren Controllern verwendet wird.

Fordern Sie diese Schnittstelle in Ihrem Konstruktor an:

public MyMiddleware(IHttpContextAccessor httpContextAccessor)
{
    _httpContextAccessor = httpContextAccessor;
}

Sie können dann auf sichere Weise auf den aktuellen HTTP-Kontext zugreifen:

var context = _httpContextAccessor.HttpContext;
// Do something with the current HTTP context...

IHttpContextAccessor wird dem Service-Container nicht immer standardmäßig hinzugefügt. Registrieren Sie ihn daher zur Sicherheit in ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpContextAccessor();
    // if < .NET Core 2.2 use this
    //services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

    // Other code...
}
210
Nate Barbettini

Nekromanzierung.
JA KÖNNEN SIE, und so.
Ein Geheimtipp für große Migranten junks Codestücke:
Die folgende Methode ist ein böser Karbunkel eines Hacks, der aktiv an der Ausführung der Express-Arbeit von Satan (in den Augen der .NET Core Framework-Entwickler) beteiligt ist, aber es arbeitet :

In public class Startup

eine Eigenschaft hinzufügen

public IConfigurationRoot Configuration { get; }

Fügen Sie dann DI in ConfigureServices einen einzelnen IHttpContextAccessor hinzu.

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

Dann in Konfigurieren

    public void Configure(
              IApplicationBuilder app
             ,IHostingEnvironment env
             ,ILoggerFactory loggerFactory
    )
    {

füge den DI-Parameter IServiceProvider svp hinzu, so dass die Methode so aussieht:

    public void Configure(
           IApplicationBuilder app
          ,IHostingEnvironment env
          ,ILoggerFactory loggerFactory
          ,IServiceProvider svp)
    {

Erstellen Sie als Nächstes eine Ersatzklasse für 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 


}

Speichern Sie jetzt in Configure, wo Sie IServiceProvider svp hinzugefügt haben, diesen Dienstanbieter in der statischen Variablen "ServiceProvider" in der gerade erstellten Dummy-Klasse System.Web.HttpContext (System.Web.HttpContext.ServiceProvider).

und setzen Sie HostingEnvironment.IsHosted auf true

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

dies ist im Wesentlichen das, was System.Web getan hat, nur dass Sie es nie gesehen haben (ich denke, die Variable wurde als intern anstatt öffentlich deklariert).

// 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

    });

Wie in ASP.NET Web-Forms erhalten Sie eine NullReference, wenn Sie versuchen, auf einen HttpContext zuzugreifen, wenn es keinen gibt, wie es früher in Application_Start in global.asax war.

Ich betone noch einmal, das funktioniert nur, wenn du es tatsächlich hinzufügst

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

wie ich geschrieben habe solltest du.
Willkommen zum ServiceLocator-Muster innerhalb des DI-Musters;)
Fragen Sie Ihren Arzt oder Apotheker nach Risiken und Nebenwirkungen - oder lesen Sie die Quellen von .NET Core unter github.com/aspnet , und führen Sie einige Tests durch.


Möglicherweise würde eine wartbarere Methode das Hinzufügen dieser Hilfsklasse sein

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


    }


}

Rufen Sie dann HttpContext.Configure unter Startup-> Configure auf

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>()
    );
41
Stefan Steiger

Hierfür gibt es eine Lösung, wenn Sie wirklich einen statischen Zugriff auf den aktuellen Kontext benötigen. In Startup.Configure (….)

app.Use(async (httpContext, next) =>
{
    CallContext.LogicalSetData("CurrentContextKey", httpContext);
    try
    {
        await next();
    }
    finally
    {
        CallContext.FreeNamedDataSlot("CurrentContextKey");
    }
});

Und wenn Sie es brauchen, können Sie es bekommen mit:

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

Ich hoffe das hilft. Denken Sie daran, dass Sie dieses Problem umgehen müssen, wenn Sie keine andere Wahl haben. Am besten ist es, die Abhängigkeitsinjektion zu verwenden.

9
HLS