BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

ASP.NET Core 5 のルーティングの基本

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 は UseRoutingUseEndpoints で実現しますが、規則ルーティングは、UseEndpoints の中で規則を定義しそれによってルーティングをするやつです。個人的には UI が絡むのはシンプルな規約ベースでやれイメージがあります。
パット見た感じだと v2.1 以前の IRouter ベースのルーティングとさほど変わらないようにみえますが、ルーティングが UseRoutingUseEndpoints に分裂したことで 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 メソッドでの実装は、大前提として UseRoutingUseEndpoints を使うのはもちろんですが、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 公式ドキュメント

その他