Help us understand the problem. What is going on with this article?

ASP.NET MVCのMapRouteとMapMvcAttributeRoutesを併用するとどうなるか

More than 1 year has passed since last update.

結論

  • RouteConfigの設定の順序によっては併用にならない。
  • Route属性の指定があればそちらでルーティングされ、MapRouteの方は使用されない。
  • Route属性の指定がなければMapRouteのルールが指定される。

前提知識

ASP.NET MVCでWebアプリのプロジェクトを作った時、デフォルトのルーティングルールはApp_Start/RouteConfig.csに書かれています。内容は以下の通り。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }

しかしこれは柔軟性が低いです。まずidはすべてのハンドラに必要ではありません。しかしこのままではすべてのハンドラでid付きでアクセスできてしまいます。そのような違いをMapRouteをモリモリ追加していくことで表現できるんですが複雑で読みづらくなります。デフォルトのまま運用しているところも多いのでは。

もちろんこれだけでなく、属性ベースのルーティングが採用できます。以下の通り。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes();
        }
    }

MapMvcAttributeRoutesを指定すると、Route属性やRoutePrefix属性が指定でき、パスを任意のパラメータとして指定できるなどとても便利です。

というわけで属性だけでいいじゃんと思うんですが、これを併記したらどうなるかを調べました。なんとなく両方のパスでアクセスできるんじゃないかと考えたんですがどうなるでしょうか。

パターン1

MapRouteの後にMapMvcAttributeRoutesをコール。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
            routes.MapMvcAttributeRoutes();
        }
    }
  • MapRouteは有効
  • Route属性が付いている場合はどちらで設定したパスでもアクセス不可
  • RoutePrefix属性は無視

というわけで併用できません。

ちなみにRazorの@Html.ActionLink()はアクセス不可でも動いてくれます。MapRouteの方で。だからなんだという感じですが。

パターン2

MapRouteより先にMapMvcAttributeRoutesをコール。

    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapMvcAttributeRoutes();
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }
    }
  • MapMvcAttributeRoutesは有効
  • Route属性がない場合のみMapRouteが有効
    • Route属性がある場合はMapRouteのルールではアクセス不可
    • RoutePrefix属性のみが付いている場合はRoutePrefix属性は無視される

併用できました。Route属性の有無でどちらが適用されるか変わります。片方しか適用されないのは理想的ですね。ただしRoute属性なし,RoutePrefix属性のみだとRoutePrefix属性が無視されるので、うっかりRoute属性を省略するとPrefix通りにアクセスできません。
@Html.ActionLink()もちゃんと動いてくれます。

上記の通りできるとはいえ、併用すると書く場所が発散しちゃうのでできるだけMapRoute側をシンプルに保つなどの工夫が必要です。

おまけ

調べるきっかけになった記事。
https://exceptionnotfound.net/attribute-routing-vs-convention-routing/

kik4
Webエンジニア
https://kik4.work
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした