ASP.NET Core のルーティングについての簡単な自分用メモです。ようは Endpoint Routing についてです。
タイトルでは ASP.NET Core 5 と書きましたが Endpoint Routing は v2.2 で追加されて以前の Routing 機能よりパフォーマンスの向上もしているので使わない理由がありません。そして v3.0 以降ちょいちょいアップデートされている機能です。ここで話す基本的なことは v3系以降であれば一緒です。
まとめ
ということでいきなりまとめです。
Routing には大きく2種類あり、Web API を開発する場合は 属性ベース のルーティングがベストプラクティスです。
- 規則ルーティング (Conventional routing) を使うケース: ASP.NET Core MVC や Razer Pages
- 属性ルーティング (Attribute routing) を使うケース: Web API
規則ルーティング (Conventional routing) のルーティング
いきなり話が脱線しますが、私的には"規約"ルーティングの方がしっくりきます。ドキュメントが"規則"って翻訳されてるんですけどどうでしょうね。
で本題ですが、規則ルーティングは ASP.NET Core の Startup.cs の Configure
メソッドで書きます。
app.UseRouting(); //中略 app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); });
そもそもとして Endpoint Routing は UseRouting
と UseEndpoints
で実現しますが、規則ルーティングは、UseEndpoints
の中で規則を定義しそれによってルーティングをするやつです。個人的には UI が絡むのはシンプルな規約ベースでやれイメージがあります。
パット見た感じだと v2.1 以前の IRouter
ベースのルーティングとさほど変わらないようにみえますが、ルーティングが UseRouting
と UseEndpoints
に分裂したことで request pipeline Middleware の構成がしやすくなったりしています。
イメージしやすくするために上記のコードを書きましたが、このデフォルトの設定は拡張メソッドが用意されてるので以下のように書けます。
app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); });
とめっちゃざっくりな説明ですが、規則ルーティングを使うときは、以下のドキュメントを人通り見ておけばやりたいことは実現できるでしょう。
属性ルーティング (Attribute routing)
Web API を開発する場合の利用でベストプラクティスと書かれている属性ルーティング、これ自体は目新しいものではありませんがおさらいです。
ASP.NET Core の Startup.cs の Configure
メソッドでは以下のようにだけ書いておき、あとは Controller の class に属性 (Attribute) を付けて Routing を定義します。
Startup.cs の Configure
メソッドでの実装は、大前提として UseRouting
と UseEndpoints
を使うのはもちろんですが、UseEndpoints
の中で MapControllers
を呼ぶだけです。
app.UseRouting();
//中略
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
あとは Controller 側で属性を付けてあげます。
[Route("api/[controller]")] [ApiController] public class HelloController : ControllerBase { [HttpGet] // GET /api/hello public IActionResult ListProducts() { return ControllerContext.MyDisplayRouteInfo(); } [HttpGet("{id}")] // GET /api/hello/xyz public IActionResult GetProduct(string id) { return ControllerContext.MyDisplayRouteInfo(id); } [HttpGet("world/{id:int}")] // GET /api/hello/world/3 public IActionResult GetIntProduct(int id) { return ControllerContext.MyDisplayRouteInfo(id); } [HttpGet("{roomId}/member/{memberId}")] // GET /room1/member/13 public IActionResult GetIntProduct(int id) { return ControllerContext.MyDisplayRouteInfo(id); } }
ざっくり理解出来たら、あとは以下を読めばやりたいことが実現できます。
ASP.NET Core でのコントローラー アクションへのルーティング - REST APIs の属性ルーティング
終わりに
v2.1 以前の互換性を保つためのコードを書く方法もありますが、エンドポイントルーティングの導入でパフォーマンスもよくなるし死にゆく古いコードを互換を保って使って技術的負債を抱える理由もないと思うので、互換性の恩恵を得ずに新しくするべき点ですね。
あとは、もうちょと細かいことを書こうと思ってたんですがこれだけで自分的に十分と感じたのでここまでとします。
ASP.NET Core でのコントローラー アクションへのルーティング のページが素の機械翻訳のせいかひどかったので翻訳の修正をやりだしてブログが雑になったってやつです。その翻訳修正も前半の一部だけの PR を出しただけになりますがwマージされたら続きの翻訳やろうっと♪
参考
ASP.NET Core 公式ドキュメント
その他
- ASP.NET Core MVC 2.1系からの動作の互換性 blog.shibayan.jp