Freigeben über


Inkrementelle Migration des IHttpModule von ASP.NET zu ASP.NET Core

Module sind Typen, die IHttpModule implementieren und in ASP.NET Framework verwendet werden, um an verschiedenen Ereignissen in die Anforderungspipeline einzuklinken. In einer ASP.NET Core-Anwendung sollten diese idealerweise zu Middleware migriert werden. Es gibt jedoch Fälle, in denen dies nicht möglich ist. Um Migrationsszenarien zu unterstützen, in denen Module erforderlich sind und nicht in Middleware verschoben werden können, unterstützen System.Web-Adapter das Hinzufügen zu ASP.NET Core.

Beispiel für IHttpModule

Um Module zu unterstützen, muss eine Instanz von HttpApplication verfügbar sein. Wenn keine benutzerdefinierte HttpApplication verwendet wird, wird standardmäßig ein Modul hinzugefügt. Ereignisse, die in einer benutzerdefinierten Anwendung (einschließlich Application_Start) deklariert sind, werden registriert und entsprechend ausgeführt.

using System.Web;
using Microsoft.AspNetCore.OutputCaching;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSystemWebAdapters()
    .AddHttpApplication<MyApp>(options =>
    {
        // Size of pool for HttpApplication instances. Should be what the expected concurrent requests will be
        options.PoolSize = 10;

        // Register a module (optionally) by name
        options.RegisterModule<MyModule>("MyModule");
    });

// Only available in .NET 7+
builder.Services.AddOutputCache(options =>
{
    options.AddHttpApplicationBasePolicy(_ => new[] { "browser" });
});

builder.Services.AddAuthentication();
builder.Services.AddAuthorization();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthenticationEvents();

app.UseAuthorization();
app.UseAuthorizationEvents();

app.UseSystemWebAdapters();
app.UseOutputCache();

app.MapGet("/", () => "Hello World!")
    .CacheOutput();

app.Run();

class MyApp : HttpApplication
{
    protected void Application_Start()
    {
    }

    public override string? GetVaryByCustomString(System.Web.HttpContext context, string custom)
    {
        // Any custom vary-by string needed

        return base.GetVaryByCustomString(context, custom);
    }
}

class MyModule : IHttpModule
{
    public void Init(HttpApplication application)
    {
        application.BeginRequest += (s, e) =>
        {
            // Handle events at the beginning of a request
        };

        application.AuthorizeRequest += (s, e) =>
        {
            // Handle events that need to be authorized
        };
    }

    public void Dispose()
    {
    }
}

Migration von Global.asax

Diese Infrastruktur kann verwendet werden, um die Nutzung von Global.asax bei Bedarf zu migrieren. Die Quelle aus Global.asax ist eine benutzerdefinierte HttpApplication. Die Datei kann in eine ASP.NET Core-Anwendung integriert werden. Da sie Global benannt ist, kann der folgende Code verwendet werden, um sie zu registrieren:

builder.Services.AddSystemWebAdapters()
    .AddHttpApplication<Global>();

Solange die darin enthaltene Logik in ASP.NET Core verfügbar ist, kann dieser Ansatz verwendet werden, um die Abhängigkeit von Global.asax inkrementell zu ASP.NET Core zu migrieren.

Authentifizierungs-/Autorisierungsereignisse

Damit die Authentifizierungs- und Autorisierungsereignisse zur gewünschten Zeit ausgeführt werden können, sollte das folgende Muster verwendet werden:

app.UseAuthentication();
app.UseAuthenticationEvents();

app.UseAuthorization();
app.UseAuthorizationEvents();

Wenn dies nicht erfolgt, werden die Ereignisse weiterhin ausgeführt. Es wird jedoch während des Aufrufs von .UseSystemWebAdapters() ausgeführt.

HTTP-Modulpooling

Da Module und Anwendungen in ASP.NET Framework einer Anforderung zugewiesen wurden, wird für jede Anforderung eine neue Instanz benötigt. Da die Erstellung jedoch laufzeitintensiv ist, werden sie mit ObjectPool<T> gepoolt. Um die tatsächliche Lebensdauer der HttpApplication-Instanzen anzupassen, kann ein benutzerdefinierter Pool verwendet werden:

builder.Services.TryAddSingleton<ObjectPool<HttpApplication>>(sp =>
{
    // Recommended to use the in-built policy as that will ensure everything is initialized correctly and is not intended to be replaced
    var policy = sp.GetRequiredService<IPooledObjectPolicy<HttpApplication>>();

    // Can use any provider needed
    var provider = new DefaultObjectPoolProvider();

    // Use the provider to create a custom pool that will then be used for the application.
    return provider.Create(policy);
});

Zusätzliche Ressourcen