はじめに
ASP.NET Core のルーティングについて調べたときのメモです。
環境
$ dotnet --version
3.1.401
ルーティングを使えるようにする
ミドルウェアパイプラインに UseRouting と UseEndpoints を追加する。
(デフォルトで追加されるので、あまり気にする必要ない)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
// コントローラーで定義したアクションをエンドポイントに追加する
endpoints.MapControllers();
});
}
- 備考
- UseRoutingではSetEndpointを使用してエンドポイントをHTTPコンテキストに設定する
- UseEndpointsではGetEndpointを使用してエンドポイントの処理を実行する
https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/routing?view=aspnetcore-3.1#aspnet-core-endpoint-definition
ルーティングの定義方法
ASP.NET Coreでルートを定義する方法は二つある。
Attribute routing vs conventional routing
- 属性ルーティング - REST APIを構築する場合に使う
- 従来のルーティング - ブラウザ用のhtmlページを提供する場合に使う (こっちは自分には必要無いので今回は調べない)
ルートの結合
コントローラに設定したルートとアクションに設定したルートは結合される。
https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1#combining-attribute-routes
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("products")]
public class ProductsApiController : ControllerBase
{
[Route] // e.g. https://localhost:5001/products/
[Route("{id}")] // e.g. https://localhost:5001/products/100
public ActionResult<string> GetProduct(int? id)
{
return ControllerContext.HttpContext.Request.Path.ToString();
}
}
ただし、アクションのルートがスラッシュ(/)またはチルダとスラッシュ(~/)から始まる場合は結合されない。
using Microsoft.AspNetCore.Mvc;
[Route("Home")]
public class HomeController : Controller
{
[Route("Index")] // e.g https://localhost:5001/Home/Index
[Route("/Index")] // e.g https://localhost:5001/Index
[Route("/")] // e.g https://localhost:5001/
public ActionResult<string> Index()
{
return ControllerContext.HttpContext.Request.Path.ToString();
}
[Route("About")] // e.g https://localhost:5001/Home/About
[Route("~/About")] // e.g https://localhost:5001/About
public ActionResult<string> About()
{
return ControllerContext.HttpContext.Request.Path.ToString();
}
}
- RouteAttributeについて
- HTTPメソッドは区別されない。マッチしたアクションが呼び出される。
- アクションが処理するHTTPメソッドを指定するにはGetAttributeなどを使う。
ルートパラメータ
一つのルートセグメントの中に複数のルートパラメータを設定することができる。
ただし、各ルートパラメータはリテラルで区切る必要がある。
{controller=Home}{action=Index} <- 区切られていないのでダメ
{controller=Home}abc{action=Index} <- リテラル'abc'で区切られているのでおk
- セグメント・・・ パス区切り(/)で区切られた範囲。
https://localhost:5001/weatherforecast/{a}b{c}
ならセグメントはweatherforecast
と{a}b{c}
の2つ。
セグメントの中にオプションパラメータ(?付きのパスパラメータ)を設定する場合は、区切り文字としてドット(.)を使う。(他の文字は使用できない)
https://localhost:5001/weatherforecast/{filename}.{ext?} <- おk
https://localhost:5001/weatherforecast/{filename}-{ext?} <- '.'じゃない('-'区切りになっている)のでダメ
ターミナルミドルウェア
ルートの照合を行うミドルウェアのこと。
ランタイムが提供するルーティング機能を使用せずに実装することは推奨されない。
ルートの照合処理の実装は相当の手間が掛かる。
Map, MapWhen と組み合わせることで、ルートの照合処理とミドルウェアの機能を分離した方が良い。
- ターミナルミドルウェアについての説明とMapメソッドを使用した実装例
- ターミナルミドルウェアとルーティングの比較
- MapHealthChecks