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

ASP.NET MVC5でもルートテンプレート内でトークンを使いたい!

More than 1 year has passed since last update.

ルートテンプレートでのトークンの使用

ASP.NET Core ではルーティングを定義するときにトークンを使用できます。
ルート テンプレートでのトークンの置換 ([controller], [action], [area])
しかし残念ながら ASP.NET MVC5 には実装されていないため逆輸入します。

IDirectRouteProvider の作成

DefaultDirectRouteProvider を継承してトークンを変換する処理を実装します。

DefaultTokenDirectRouteProvider.cs
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Routing;

public class DefaultTokenDirectRouteProvider : DefaultDirectRouteProvider
{
    public override IReadOnlyList<RouteEntry> GetDirectRoutes(ControllerDescriptor controllerDescriptor, IReadOnlyList<ActionDescriptor> actionDescriptors, IInlineConstraintResolver constraintResolver)
    {
        return base.GetDirectRoutes(controllerDescriptor, actionDescriptors, constraintResolver)
            .Select(x =>
            {
                x.Route.Url = x.Route.Url
                    .Replace("[controller]", x.Route.Defaults["controller"].ToString())
                    .Replace("[action]", x.Route.Defaults["action"].ToString());
                return new RouteEntry(x.Name, x.Route);
            })
            .ToList();
    }
}

RouteConfig への登録

あとは MapMvcAttributeRoutes メソッドに先ほど作成した DefaultTokenDirectRouteProvider を渡してあげるだけです。

RouteConfig.cs
using System.Web.Mvc;
using System.Web.Routing;

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.Clear();
        routes.MapMvcAttributeRoutes(new DefaultTokenDirectRouteProvider());
    }
}

使い方

以下の今までの書き方が...

Sample1Controller.cs
using System.Web.Mvc;

[RoutePrefix("Sample1")]
public class Sample1Controller : Controller
{
    [HttpGet]
    [Route("Index")]
    public ActionResult Index()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }
}

スマートになります。
[area] トークン、トークンのカスタマイズは対応していません。

Sample2Controller.cs
using System.Web.Mvc;

[RoutePrefix("[controller]")]
public class Sample2Controller : Controller
{
    [HttpGet]
    [Route("[action]")]
    public ActionResult Index()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }
}
xmid
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