演習 - カスタム ミドルウェアを作成する
開発者は、カスタム ミドルウェア コンポーネントを作成して、ASP.NET Core アプリに機能を追加できます。 カスタム ミドルウェアはミドルウェア パイプライン内のどこにでも挿入でき、次の例に示すように組み込みミドルウェア コンポーネントと共に使用できます。
あなたの会社のネットワーク運用チームは、運用環境でのパフォーマンスの問題のトラブルシューティングを行っています。 チーム リーダーから、アプリのリアルタイム監視をより適切にサポートするために、いくつかの機能を実装する作業を任されました。 アプリは、要求の詳細をコンソールに記録する必要があります。 要求ごとに、要求メソッド、パス、応答状態コードをログに記録する必要があります。
この演習では、要求の詳細をコンソールに記録するカスタム ミドルウェア コンポーネントを作成します。
カスタム ミドルウェアを追加する
要求の詳細をコンソールに記録するカスタム ミドルウェアを含むように、既存の ASP.NET Core アプリを変更してみましょう。
Program.cs ファイルをまだ開いていない場合は、これを開きます。
app.Run()
の直前に、次のコードを挿入します。app.Use(async (context, next) => { Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}"); await next(); });
上のコードでは以下の操作が行われます。
-
app.Use()
は、カスタム ミドルウェア コンポーネントをパイプラインに追加します。 コンポーネントは、パラメーターとしてHttpContext
オブジェクトとRequestDelegate
オブジェクトを受け取ります。 - 委任は、要求メソッド、パス、応答状態コードをコンソールに書き込みます。
-
await next()
は、パイプライン内の次のミドルウェア コンポーネントを呼び出します。
-
変更内容をテストする
Ctrl+Shift+F5 キーを押してアプリをリビルドして再起動します。
ブラウザー ウィンドウが開いたら、ルート URL に "Welcome to Contoso!" と表示されることに注意してください
/history
を URL に追加し、Enter キーを押します。 ブラウザーは [/about
] ページにリダイレクトされます。Visual Studio Code で、Ctrl + Shift + P キーを押してコマンド パレットを開きます。 [デバッグ コンソール: デバッグ コンソール ビューにフォーカスする] を検索して選択し、下部パネルの [デバッグ コンソール] タブに切り替えます。 以下の行に注意してください。
GET / 200 GET /about 200
コンソール出力は、各要求の要求メソッド、パス、応答状態コードを示します。 最初の行はルート URL の要求を示し、2 行目は
/about
ページの要求を示します。注
ブラウザーが
/favicon.ico
を要求することもあります。 これは、Web サイトのファビコンに対する標準的な要求であり、無視できます。次の演習のために、このアプリを実行したままにします。
ミドルウェアの順序を変更する
アプリは動作しているように見えますが、問題があります。
/history
ページを要求しましたが、コンソール出力に表示されません。 この動作は、要求の詳細をログに記録するカスタム ミドルウェア コンポーネントが URL リライター ミドルウェアの後に追加されたためです。 URL リライター ミドルウェアは、要求を /history
から /about
にリダイレクトして応答を送信します。カスタム ミドルウェア コンポーネントには要求が表示されません。 これを修正しましょう。
追加した
app.Use()
行をapp.UseRewriter()
行の直前に移動します。完全な Program.cs ファイルはこのようになります。
using Microsoft.AspNetCore.Rewrite; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Use(async (context, next) => { Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}"); await next(); }); app.UseRewriter(new RewriteOptions().AddRedirect("history", "about")); app.MapGet("/", () => "Hello World!"); app.MapGet("/about", () => "Contoso was founded in 2000."); app.Run();
URL リライター ミドルウェアの前にカスタム ミドルウェア コンポーネントが追加されました。 URL リライター ミドルウェアが要求を処理し、リダイレクトする前に、カスタム ミドルウェア コンポーネントが要求の詳細をログに記録します。
アプリをもう一度再起動し、前と同様にテストします。 今回は、デバッグ コンソールの出力に、
/history
ページの要求が含まれている必要があります。GET / 200 GET /history 200 GET /about 200
コンソール出力には、
/history
ページにリダイレクトする直前に/about
ページの要求が表示されるようになりました。
状態コードを修正する
アプリはほぼ準備ができていますが、もう 1 つ問題があります。 アプリが要求をリダイレクトした場合でも、コンソール出力の状態コードは常に 200 です。
/history
要求の状態コードは 302 リダイレクトになる必要があります。 この動作の理由は、ミドルウェア コンポーネントが処理される順序に関する別の問題にあります。
カスタム ミドルウェア コンポーネントは、詳細をコンソールに記録し、await next()
を呼び出して次のミドルウェア コンポーネントに渡します。 問題は、ターミナル ミドルウェア コンポーネントが応答を開始した後に、StatusCode
オブジェクトの Response
プロパティが設定されていることです。 コードを変更してこれを修正しましょう。
追加したデリゲートで、
Console.WriteLine()
行をawait next()
行の後に移動します。更新したコードは次のようになります。
app.Use(async (context, next) => { await next(); Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}"); });
これで、カスタム ミドルウェア コンポーネントは、ターミナル ミドルウェア コンポーネントが応答状態コードを設定した後、要求の詳細をログに記録します。
再起動して、
/history
要求をもう一度テストします。 デバッグ コンソールの出力に正しい状態コードが表示されるようになりました。GET / 200 GET /history 302 GET /about 200