ASP.NET ASP.NET для добавочной миграции IHttpModule core

Модули — это типы, которые реализуют IHttpModule и используются в ASP платформа .NET Framework для перехвата в конвейер запросов при различных событиях. В приложении ASP.NET Core они должны быть перенесены в ПО промежуточного слоя. Однако есть случаи, когда это невозможно сделать. Для поддержки сценариев миграции, в которых необходимы модули и не могут быть перемещены в ПО промежуточного слоя, адаптеры System.Web поддерживают добавление их в ASP.NET Core.

Пример IHttpModule

Чтобы поддерживать модули, экземпляр HttpApplication должен быть доступен. Если пользователь HttpApplication не используется, он будет использоваться по умолчанию для добавления модулей в. События, объявленные в пользовательском приложении (включая Application_Start) будут зарегистрированы и выполняются соответствующим образом.

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()
    {
    }
}

Миграция Global.asax

Эту инфраструктуру можно использовать для переноса использования Global.asax при необходимости. Источник из Global.asax него — это пользователь HttpApplication , и файл можно включить в приложение ASP.NET Core. Так как он называется Global, для его регистрации можно использовать следующий код:

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

Если логика в ней доступна в ASP.NET Core, этот подход можно использовать для добавочной миграции на Global.asax ASP.NET Core.

События проверки подлинности и авторизации

Чтобы события проверки подлинности и авторизации выполнялись в нужное время, следует использовать следующий шаблон:

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

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

Если это не сделано, события по-прежнему будут выполняться. Тем не менее, это будет во время вызова .UseSystemWebAdapters().

Пул модулей HTTP

Так как модули и приложения в ASP платформа .NET Framework были назначены запросу, для каждого запроса требуется новый экземпляр. Тем не менее, поскольку они могут быть дорогостоящими для создания, они используются в ObjectPool<T>пуле. Чтобы настроить фактическое время существования HttpApplication экземпляров, можно использовать настраиваемый пул:

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

Дополнительные ресурсы