カスタム ASP.NET Core ミドルウェアを記述する

作成者: Rick AndersonSteve Smith

ミドルウェアとは、要求と応答を処理するために、アプリのパイプラインに組み込まれたソフトウェアです。 ASP.NET Core からは、組み込みミドルウェア コンポーネントが豊富に提供されますが、カスタム ミドルウェアを記述したほうが良い場合もあります。

注意

このトピックでは "規約に基づく" ミドルウェアを作成する方法について説明します。 厳密な型指定と要求ごとのアクティベーションを使用したアプローチについては、「ASP.NET Core でのファクトリ ベースのミドルウェアのアクティブ化」を参照してください。

ミドルウェア クラス

ミドルウェアは一般に、クラスにカプセル化され、拡張メソッドを使用して公開されます。 クエリ文字列から現在の要求のカルチャを設定する次のようなミドルウェアを考慮します。

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            var cultureQuery = context.Request.Query["culture"];
            if (!string.IsNullOrWhiteSpace(cultureQuery))
            {
                var culture = new CultureInfo(cultureQuery);

                CultureInfo.CurrentCulture = culture;
                CultureInfo.CurrentUICulture = culture;
            }

            // Call the next delegate/middleware in the pipeline
            await next();
        });

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                $"Hello {CultureInfo.CurrentCulture.DisplayName}");
        });

    }
}

上のサンプル コードを使って、ミドルウェア コンポーネントの作成方法を示します。 ASP.NET Core に組み込まれているローカライズのサポートについては、「ASP.NET Core のグローバリゼーションおよびローカリゼーション」を参照してください。

カルチャを渡すことによって、ミドルウェアをテストします。 たとえば、https://localhost:5001/?culture=no を要求します。

次のコードは、ミドルウェアのデリゲートをクラスに移動します。

using Microsoft.AspNetCore.Http;
using System.Globalization;
using System.Threading.Tasks;

namespace Culture
{
    public class RequestCultureMiddleware
    {
        private readonly RequestDelegate _next;

        public RequestCultureMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var cultureQuery = context.Request.Query["culture"];
            if (!string.IsNullOrWhiteSpace(cultureQuery))
            {
                var culture = new CultureInfo(cultureQuery);

                CultureInfo.CurrentCulture = culture;
                CultureInfo.CurrentUICulture = culture;

            }

            // Call the next delegate/middleware in the pipeline
            await _next(context);
        }
    }
}

ミドルウェアのクラスには、次のものが含まれる必要があります。

  • RequestDelegate 型のパラメーターを持つパブリック コンストラクター。
  • Invoke または InvokeAsync という名前のパブリック メソッド。 このメソッドでは次のことが必要です。
    • Task を返します。
    • HttpContext 型の最初のパラメーターを受け取ります。

コンストラクターおよび Invoke/InvokeAsync に対する追加のパラメーターは、依存関係の挿入 (DI) によって設定されます。

ミドルウェアの依存関係

ミドルウェアは、コンストラクターで依存関係を公開することによって、明示的な依存関係の原則に従う必要があります。 ミドルウェアは、"アプリケーションの有効期間" ごとに 1 回構築されます。 要求内でミドルウェアとサービスを共有する必要がある場合は、「要求ごとのミドルウェアの依存関係」セクションをご覧ください。

ミドルウェア コンポーネントは、コンストラクター パラメーターにより、依存関係の挿入 (DI) から依存関係を解決できます。 UseMiddleware<T> は、追加パラメーターを直接受け入れることもできます。

要求ごとのミドルウェアの依存関係

ミドルウェアは要求ごとではなくアプリの起動時に構築されるため、ミドルウェアのコンストラクターによって使われる "スコープ" 有効期間のサービスは、各要求の間に、依存関係によって挿入される他の種類と共有されません。 ミドルウェアとその他の種類の間で "スコープ" サービスを共有する必要がある場合は、これらのサービスを Invoke メソッドのシグネチャに追加します。 Invoke メソッドは、DI によって設定される追加のパラメーターを受け取ることができます。

public class CustomMiddleware
{
    private readonly RequestDelegate _next;

    public CustomMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    // IMyScopedService is injected into Invoke
    public async Task Invoke(HttpContext httpContext, IMyScopedService svc)
    {
        svc.MyProperty = 1000;
        await _next(httpContext);
    }
}

有効期間と登録のオプションには、"スコープ付き" 有効期間サービスを含むミドルウェアの完全なサンプルが含まれています。

ミドルウェア拡張メソッド

次の拡張メソッドは、IApplicationBuilder を介してミドルウェアを公開します。

using Microsoft.AspNetCore.Builder;

namespace Culture
{
    public static class RequestCultureMiddlewareExtensions
    {
        public static IApplicationBuilder UseRequestCulture(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<RequestCultureMiddleware>();
        }
    }
}

次のコードは、Startup.Configure からミドルウェアを呼び出します。

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.UseRequestCulture();

        app.Run(async (context) =>
        {
            await context.Response.WriteAsync(
                $"Hello {CultureInfo.CurrentCulture.DisplayName}");
        });
    }
}

その他の技術情報