カスタム ASP.NET Core ミドルウェアを記述する
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
作成者: Fiyaz Hasan、Rick Anderson、Steve Smith
ミドルウェアとは、要求と応答を処理するために、アプリのパイプラインに組み込まれたソフトウェアです。 ASP.NET Core からは、組み込みミドルウェア コンポーネントが豊富に提供されますが、カスタム ミドルウェアを記述したほうが良い場合もあります。
このトピックでは "規約に基づく" ミドルウェアを作成する方法について説明します。 厳密な型指定と要求ごとのアクティベーションを使用したアプローチについては、「ASP.NET Core でのファクトリ ベースのミドルウェアのアクティブ化」を参照してください。
ミドルウェア クラス
ミドルウェアは一般に、クラスにカプセル化され、拡張メソッドを使用して公開されます。 クエリ文字列から現在の要求のカルチャを設定する次のようなインライン ミドルウェアを考慮します。
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
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(context);
});
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});
app.Run();
上記で強調表示されているインライン ミドルウェアは、Microsoft.AspNetCore.Builder.UseExtensions.Use を呼び出してミドルウェア コンポーネントを作成する方法を示すために使用されています。 上記の Use
拡張メソッドは、インラインで定義されたミドルウェア デリゲートを、アプリケーションの要求パイプラインに追加します。
Use
拡張機能には、次の 2 つのオーバーロードがあります。
- 1 つは、HttpContext と
Func<Task>
を受け取ります。Func<Task>
はパラメーターなしで呼び出します。 - もう 1 つは、
HttpContext
および RequestDelegate を受け取ります。RequestDelegate
はHttpContext
を渡すことで呼び出します。
後者では、他のオーバーロードを使用するときに必要な 2 つの内部要求ごとの割り当てが保存されるので、後者を優先的に使用してください。
カルチャを渡すことによって、ミドルウェアをテストします。 たとえば、https://localhost:5001/?culture=es-es
を要求します。
ASP.NET Core の組み込みのローカリゼーション サポートについては、「ASP.NET Core のグローバリゼーションおよびローカリゼーション」をご覧ください。
次のコードは、ミドルウェアのデリゲートをクラスに移動します。
using System.Globalization;
namespace Middleware.Example;
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) によって設定されます。
通常、拡張メソッドは IApplicationBuilder を通じてミドルウェアを公開するために作成されます。
using System.Globalization;
namespace Middleware.Example;
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);
}
}
public static class RequestCultureMiddlewareExtensions
{
public static IApplicationBuilder UseRequestCulture(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestCultureMiddleware>();
}
}
次のコードは、Program.cs
からミドルウェアを呼び出します。
using Middleware.Example;
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseRequestCulture();
app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"CurrentCulture.DisplayName: {CultureInfo.CurrentCulture.DisplayName}");
});
app.Run();
ミドルウェアの依存関係
ミドルウェアは、コンストラクターで依存関係を公開することによって、明示的な依存関係の原則に従う必要があります。 ミドルウェアは、"アプリケーションの有効期間" ごとに 1 回構築されます。
ミドルウェア コンポーネントは、コンストラクター パラメーターにより、依存関係の挿入 (DI) から依存関係を解決できます。 UseMiddleware は、追加パラメーターを直接受け入れることもできます。
要求ごとのミドルウェアの依存関係
ミドルウェアはアプリの起動時に構築されるため、アプリケーションの有効期間があります。 ミドルウェアのコンストラクターによって使われる "スコープ有効期間" のサービスは、各要求の間に、依存関係によって挿入される他の種類と共有されません。 ミドルウェアとその他の種類の間で "スコープ" サービスを共有するには、これらのサービスを InvokeAsync
メソッドのシグネチャに追加します。 InvokeAsync
メソッドは、DI によって設定される追加のパラメーターを受け取ることができます。
namespace Middleware.Example;
public class MyCustomMiddleware
{
private readonly RequestDelegate _next;
public MyCustomMiddleware(RequestDelegate next)
{
_next = next;
}
// IMessageWriter is injected into InvokeAsync
public async Task InvokeAsync(HttpContext httpContext, IMessageWriter svc)
{
svc.Write(DateTime.Now.Ticks.ToString());
await _next(httpContext);
}
}
public static class MyCustomMiddlewareExtensions
{
public static IApplicationBuilder UseMyCustomMiddleware(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<MyCustomMiddleware>();
}
}
有効期間と登録のオプションには、"スコープ付き" 有効期間サービスを含むミドルウェアの完全なサンプルが含まれています。
次のコードは、前述のミドルウェアをテストするために使用されます。
using Middleware.Example;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IMessageWriter, LoggingMessageWriter>();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseMyCustomMiddleware();
app.MapGet("/", () => "Hello World!");
app.Run();
IMessageWriter
インターフェイスと実装:
namespace Middleware.Example;
public interface IMessageWriter
{
void Write(string message);
}
public class LoggingMessageWriter : IMessageWriter
{
private readonly ILogger<LoggingMessageWriter> _logger;
public LoggingMessageWriter(ILogger<LoggingMessageWriter> logger) =>
_logger = logger;
public void Write(string message) =>
_logger.LogInformation(message);
}
その他のリソース
- この記事で使用されているサンプル コード
- GitHub の UseExtensions ソース
- 有効期間と登録のオプションには、スコープ、一時、シングルトン 有効期間サービスを含むミドルウェアの完全なサンプルが含まれています。
- 詳細: ASP.NET コアミドルウェア パイプラインの構築方法
- ASP.NET Core のミドルウェア
- ASP.NET Core のミドルウェアのテスト
- HTTP ハンドラーとモジュールを ASP.NET Core ミドルウェアに移行する
- ASP.NET Core でのアプリケーションのスタートアップ
- ASP.NET Core での要求機能
- ASP.NET Core でのファクトリ ベースのミドルウェアのアクティブ化
- ASP.NET Core でのサードパーティ コンテナーによるミドルウェアのアクティブ化
作成者: Rick Anderson、Steve Smith
ミドルウェアとは、要求と応答を処理するために、アプリのパイプラインに組み込まれたソフトウェアです。 ASP.NET Core からは、組み込みミドルウェア コンポーネントが豊富に提供されますが、カスタム ミドルウェアを記述したほうが良い場合もあります。
Note
このトピックでは "規約に基づく" ミドルウェアを作成する方法について説明します。 厳密な型指定と要求ごとのアクティベーションを使用したアプローチについては、「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 は、追加パラメーターを直接受け入れることもできます。
要求ごとのミドルウェアの依存関係
ミドルウェアは要求ごとではなくアプリの起動時に構築されるため、ミドルウェアのコンストラクターによって使われる "スコープ" 有効期間のサービスは、各要求の間に、依存関係によって挿入される他の種類と共有されません。 ミドルウェアとその他の種類の間で "スコープ" サービスを共有する必要がある場合は、これらのサービスを InvokeAsync
メソッドのシグネチャに追加します。 InvokeAsync
メソッドは、DI によって設定される追加のパラメーターを受け取ることができます。
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
// IMyScopedService is injected into InvokeAsync
public async Task InvokeAsync(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}");
});
}
}
その他の技術情報
- 有効期間と登録のオプションには、スコープ、一時、シングルトン 有効期間サービスを含むミドルウェアの完全なサンプルが含まれています。
- ASP.NET Core のミドルウェア
- ASP.NET Core のミドルウェアのテスト
- HTTP ハンドラーとモジュールを ASP.NET Core ミドルウェアに移行する
- ASP.NET Core でのアプリケーションのスタートアップ
- ASP.NET Core での要求機能
- ASP.NET Core でのファクトリ ベースのミドルウェアのアクティブ化
- ASP.NET Core でのサードパーティ コンテナーによるミドルウェアのアクティブ化
ASP.NET Core