ASP.NET から ASP.NET Core への IHttpModule の段階的な移行

モジュール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);
});

その他のリソース