【C# ASP.NET Core】IApplicationBuilderのUse()とRun()の違いを徹底解説
はじめに
ASP.NET Coreでは、StartupクラスのConfigureメソッド内で、IApplicationBuilderインターフェースのインスタンスを使ってミドルウェアを構成します。本記事では、その中でも特によく使われる2つの拡張メソッド「Use()」と「Run()」の違いについて、具体例を交えながらわかりやすく解説します。
Run()メソッドとは
Run()はIApplicationBuilderの拡張メソッドで、アプリケーションのリクエストパイプラインに終端ミドルウェア(ターミナルミドルウェア)を追加します。名前の示す通り、ここでパイプラインの処理が完了するため、それ以降に登録されたミドルウェアは一切実行されません。
Runメソッドは、RequestDelegate型のデリゲートを引数として受け取ります。
Runメソッドのシグネチャ
public static void Run(this IApplicationBuilder app, RequestDelegate handler)
RequestDelegateのシグネチャ
public delegate Task RequestDelegate(HttpContext context);
Run()の基本的な使用例
public class Startup
{
public Startup()
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
// ここでIApplicationBuilderを使ってミドルウェアを構成します
app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
// わかりやすさのため他のコードは省略しています
}
}
非同期処理によるパフォーマンス向上
ミドルウェアを同期メソッドとして実装すると、処理が完了するまでスレッドがブロックされ続けます。asyncとawaitを使って非同期化することで、スレッドの占有時間を最小限に抑え、アプリケーション全体のパフォーマンスとスケーラビリティを大きく改善できます。
public class Startup
{
public Startup()
{
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Run(MyMiddleware);
}
private async Task MyMiddleware(HttpContext context)
{
await context.Response.WriteAsync("Hello World! ");
}
}
Run()を複数回呼び出した場合の挙動
Run()はパイプラインを終了させる性質を持つため、複数のRun()を続けて記述しても、最初のRun()のみが実行され、2つ目以降には決して処理が到達しません。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Run(async (context) =>
{
await context.Response.WriteAsync("1st Middleware");
});
// 以下のコードは決して実行されません
app.Run(async (context) =>
{
await context.Response.WriteAsync(" 2nd Middleware");
});
}
Use()メソッドとは
複数のミドルウェアを順番につなげて実行したい場合は、Use()拡張メソッドを使用します。Use()はRun()とほぼ同じ働きをしますが、nextパラメータを受け取れる点が大きな違いです。nextを呼び出すことで、処理を次のミドルウェアへ委譲でき、ミドルウェア同士を自由に連結(チェーン)できます。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("1st Middleware!");
await next();
});
app.Run(async (context) =>
{
await context.Response.WriteAsync("2nd Middleware");
});
}
まとめ:Use()とRun()の違い
- Run():パイプラインを終端させる。
nextデリゲートを持たないため、それ以降のミドルウェアは実行されない。 - Use():
nextデリゲートを受け取り、次のミドルウェアへ処理を引き渡せるため、複数のミドルウェアを柔軟に連結できる。
実務では、ログ記録や認証チェックなどの前処理・後処理を行うミドルウェアにはUse()を使い、最終的なレスポンス生成などパイプラインの末端に置く処理にはRun()を使うのが基本の設計パターンです。
-
C# ASP.NET Web APIにおけるFromBody属性とFromUri属性の違いとは?
ASP.NET Web APIがコントローラーのメソッドを呼び出す際には、パラメータに値を設定する必要があります。この一連の処理は「パラメータバインディング」と呼ばれます。通常、モデル(アクションパラメータ)はフォーマッターによってバインドされるのがデフォルトの動作ですが、URIから値を取得してバインドしたい場合は[FromUri]属性を付与します。FromUriAttributeはModelBinderAttributeを継承したクラスであり、Web APIに対して「IUriValueProviderFactoryで定義されたValueProvidersを使ってURIから特定のパラメータを取
-
C#のListとDictionaryの違いとは?使い分けのポイントを解説
C#におけるListとDictionaryの基本的な違いC#にはさまざまなコレクションクラスが用意されていますが、その中でも特によく使われるのが「List」と「Dictionary」です。両者はいずれもSystem.Collections.Generic名前空間に属するジェネリック型のコレクションですが、データの格納方法やアクセス方法が大きく異なります。Dictionary(ディクショナリ)とはDictionaryは、キーと値のペアを管理するコレクションです。Dictionary<TKey, TValue>の形式で宣言され、System.Collections.Generic名前空