ASP.NET Core でのコントローラー アクションへのルーティングRouting to controller actions in ASP.NET Core

作成者: Ryan NowakRick AndersonBy Ryan Nowak and Rick Anderson

ASP.NET Core MVC は、ルーティング ミドルウェアを使って、受信した要求の URL を照合し、アクションにマップします。ASP.NET Core MVC uses the Routing middleware to match the URLs of incoming requests and map them to actions. ルートは、スタートアップ コードまたは属性で定義されています。Routes are defined in startup code or attributes. ルートでは、URL パスとアクションの照合方法が記述されています。Routes describe how URL paths should be matched to actions. また、ルートは、応答で送信される (リンク用) の URL の生成にも使われます。Routes are also used to generate URLs (for links) sent out in responses.

アクションは、規則的にルーティングされるか、または属性でルーティングされます。Actions are either conventionally routed or attribute routed. コントローラーまたはアクションにルートを配置すると、そのルートは属性ルーティングされるようになります。Placing a route on the controller or the action makes it attribute routed. 詳しくは、「混合ルーティング」をご覧ください。See Mixed routing for more information.

このドキュメントでは、MVC とルーティングの間の相互作用、および標準的な MVC アプリでのルーティング機能の利用方法を説明します。This document will explain the interactions between MVC and routing, and how typical MVC apps make use of routing features. 高度なルーティングについて詳しくは、「ASP.NET Core のルーティング」をご覧ください。See Routing for details on advanced routing.

ルーティング ミドルウェアの設定Setting up Routing Middleware

Configure メソッドには、次のようなコードが含まれることがあります。In your Configure method you may see code similar to:

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

UseMvc の呼び出しの内部で、MapRoute は単一のルートの作成に使われます。これは、default ルートと呼ばれます。Inside the call to UseMvc, MapRoute is used to create a single route, which we'll refer to as the default route. ほとんどの MVC アプリは、default ルートのようなルートをテンプレートで使います。Most MVC apps will use a route with a template similar to the default route.

ルート テンプレート "{controller=Home}/{action=Index}/{id?}" は、/Products/Details/5 のような URL パスと一致し、パスをトークン化することによってルート値 { controller = Products, action = Details, id = 5 } を抽出します。The route template "{controller=Home}/{action=Index}/{id?}" can match a URL path like /Products/Details/5 and will extract the route values { controller = Products, action = Details, id = 5 } by tokenizing the path. MVC は、ProductsController という名前のコントローラーを探して、アクション Details の実行を試みます。MVC will attempt to locate a controller named ProductsController and run the action Details:

public class ProductsController : Controller
{
   public IActionResult Details(int id) { ... }
}

この例では、このアクションを呼び出すときに、モデル バインドが id = 5 という値を使って、id パラメーターを 5 に設定することに注意してください。Note that in this example, model binding would use the value of id = 5 to set the id parameter to 5 when invoking this action. 詳しくは、「モデル バインド」をご覧ください。See the Model Binding for more details.

default ルートの使用:Using the default route:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

ルート テンプレート:The route template:

  • {controller=Home} は、Home を既定の controller として定義します{controller=Home} defines Home as the default controller

  • {action=Index} は、Index を既定の action として定義します{action=Index} defines Index as the default action

  • {id?} は、id を省略可能として定義します{id?} defines id as optional

既定および省略可能のルート パラメーターは、URL パスに存在していなくても一致します。Default and optional route parameters don't need to be present in the URL path for a match. ルート テンプレートの構文について詳しくは、「ルート テンプレート参照」をご覧ください。See Route Template Reference for a detailed description of route template syntax.

"{controller=Home}/{action=Index}/{id?}" は URL パス / と一致でき、ルート値 { controller = Home, action = Index } を生成します。"{controller=Home}/{action=Index}/{id?}" can match the URL path / and will produce the route values { controller = Home, action = Index }. controlleraction の値は既定値を使い、id は URL パスに対応するセグメントが存在しないため値を生成しません。The values for controller and action make use of the default values, id doesn't produce a value since there's no corresponding segment in the URL path. MVC はこれらのルート値を使って、HomeController および Index アクションを選びます。MVC would use these route values to select the HomeController and Index action:

public class HomeController : Controller
{
  public IActionResult Index() { ... }
}

このコントローラー定義とルート テンプレートを使うと、HomeController.Index アクションは次のいずれかの URL パスに対して実行されます。Using this controller definition and route template, the HomeController.Index action would be executed for any of the following URL paths:

  • /Home/Index/17

  • /Home/Index

  • /Home

  • /

便利なメソッド UseMvcWithDefaultRoute:The convenience method UseMvcWithDefaultRoute:

app.UseMvcWithDefaultRoute();

これは、次の代わりに使うことができます。Can be used to replace:

app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

UseMvc および UseMvcWithDefaultRoute は、RouterMiddleware のインスタンスをミドルウェア パイプラインに追加します。UseMvc and UseMvcWithDefaultRoute add an instance of RouterMiddleware to the middleware pipeline. MVC は、ミドルウェアと直接相互作用せず、ルーティングを使って要求を処理します。MVC doesn't interact directly with middleware, and uses routing to handle requests. MVC は、MvcRouteHandler のインスタンスによってルートに接続されます。MVC is connected to the routes through an instance of MvcRouteHandler. UseMvc の内部のコードは次のようになります。The code inside of UseMvc is similar to the following:

var routes = new RouteBuilder(app);

// Add connection to MVC, will be hooked up by calls to MapRoute.
routes.DefaultHandler = new MvcRouteHandler(...);

// Execute callback to register routes.
// routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

// Create route collection and add the middleware.
app.UseRouter(routes.Build());

UseMvc は、ルートを直接定義することはなく、attribute ルートのルート コレクションにプレースホルダーを追加します。UseMvc doesn't directly define any routes, it adds a placeholder to the route collection for the attribute route. オーバーロード UseMvc(Action<IRouteBuilder>) は、独自ルートの追加を可能にし、属性ルーティングをサポートします。The overload UseMvc(Action<IRouteBuilder>) lets you add your own routes and also supports attribute routing. UseMvc とそのすべてのバリエーションは、属性ルートのプレースホルダーを追加します。属性ルーティングは、UseMvc の構成方法に関係なく常に利用できます。UseMvc and all of its variations adds a placeholder for the attribute route - attribute routing is always available regardless of how you configure UseMvc. UseMvcWithDefaultRoute は既定のルートを定義し、属性ルーティングをサポートします。UseMvcWithDefaultRoute defines a default route and supports attribute routing. 属性ルーティング」セクションでは、属性ルーティングについてさらに詳しく説明します。The Attribute Routing section includes more details on attribute routing.

規則ルーティングConventional routing

次は default ルートです。The default route:

routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");

これは、"規則ルーティング" の例です。is an example of a conventional routing. このスタイルを "規則ルーティング" と呼ぶのは、それが URL パスの "規則" を作成するためです。We call this style conventional routing because it establishes a convention for URL paths:

  • 最初のパス セグメントは、コントローラー名にマップしますthe first path segment maps to the controller name

  • 2 つ目は、アクション名にマップします。the second maps to the action name.

  • 3 番目のセグメントは、モデル エンティティへのマップに使われる省略可能な id に使われますthe third segment is used for an optional id used to map to a model entity

この default ルートを使うと、URL パス /Products/ListProductsController.List アクションにマップし、/Blog/Article/17BlogController.Article にマップします。Using this default route, the URL path /Products/List maps to the ProductsController.List action, and /Blog/Article/17 maps to BlogController.Article. このマッピングは、コントローラーとアクションの名前にのみ基づき、名前空間、ソース ファイルの場所、またはメソッドのパラメーターには基づきません。This mapping is based on the controller and action names only and isn't based on namespaces, source file locations, or method parameters.

ヒント

既定のルートで規則ルーティングを使うと、定義するアクションごとに新しい URL パターンを考える必要がなく、アプリケーションをすばやく構築できます。Using conventional routing with the default route allows you to build the application quickly without having to come up with a new URL pattern for each action you define. CRUD スタイルのアクションを使うアプリケーションでは、コントローラー間で URL に一貫性を持たせると、コードが容易になり、UI の予測可能性が向上します。For an application with CRUD style actions, having consistency for the URLs across your controllers can help simplify your code and make your UI more predictable.

警告

id はルート テンプレートで省略可能と定義されており、これは URL の一部として ID を提供されなくてもアクションを実行できることを意味します。The id is defined as optional by the route template, meaning that your actions can execute without the ID provided as part of the URL. 通常、id が URL から省略されると、ID はモデル バインドによって 0 に設定され、結果として、id == 0 と一致するエンティティはデータベースで検索されません。Usually what will happen if id is omitted from the URL is that it will be set to 0 by model binding, and as a result no entity will be found in the database matching id == 0. 属性ルーティングを使うと、ID が必須のアクションと必須ではないアクションをきめ細かく制御できます。Attribute routing can give you fine-grained control to make the ID required for some actions and not for others. 慣例に従って、ドキュメントでは id などの省略可能なパラメーターが正しい使用法で使われる可能性がある場合はパラメーターを記載してあります。By convention the documentation will include optional parameters like id when they're likely to appear in correct usage.

複数のルートMultiple routes

MapRoute の呼び出しをさらに追加することで、UseMvc の内部に複数のルートを追加できます。You can add multiple routes inside UseMvc by adding more calls to MapRoute. これにより、次のように、複数の規則を定義すること、または特定のアクションに専用の規則ルートを追加することができます。Doing so allows you to define multiple conventions, or to add conventional routes that are dedicated to a specific action, such as:

app.UseMvc(routes =>
{
   routes.MapRoute("blog", "blog/{*article}",
            defaults: new { controller = "Blog", action = "Article" });
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

blog ルートは "専用の規則ルート" です。これは、このルートは規則ルーティング システムを使いますが、特定のアクション専用であることを意味します。The blog route here is a dedicated conventional route, meaning that it uses the conventional routing system, but is dedicated to a specific action. controlleraction はパラメーターとしてルート テンプレートに表示されないので、既定値を持つことだけができ、したがってこのルートは常に BlogController.Article アクションにマップされます。Since controller and action don't appear in the route template as parameters, they can only have the default values, and thus this route will always map to the action BlogController.Article.

ルート コレクション内のルートには順序があり、追加された順序で処理されます。Routes in the route collection are ordered, and will be processed in the order they're added. そのため、この例では、blog ルートが default ルートより先に試されます。So in this example, the blog route will be tried before the default route.

注意

"専用の規則ルート" は、多くの場合、{*article} のようなキャッチオール ルート パラメーターを使って、URL パスの残りの部分をキャプチャします。Dedicated conventional routes often use catch-all route parameters like {*article} to capture the remaining portion of the URL path. このようにすると、ルートの "一致範囲が広くなりすぎて"、他のルートと一致させるつもりであった URL まで一致する可能性があります。This can make a route 'too greedy' meaning that it matches URLs that you intended to be matched by other routes. この問題を解決するには、"一致範囲の広い" ルートはルート テーブルの後の方に配置します。Put the 'greedy' routes later in the route table to solve this.

フォールバックFallback

要求処理の一環として、MVC はルートの値を使ってアプリケーション内のコントローラーとアクションを検索できることを確認します。As part of request processing, MVC will verify that the route values can be used to find a controller and action in your application. ルートの値がアクションと一致しない場合、そのルートは一致と見なされず、次のルートが試されます。If the route values don't match an action then the route isn't considered a match, and the next route will be tried. これは "フォールバック" と呼ばれ、規則ルートがオーバーラップしている場合の簡略化を意図したものです。This is called fallback, and it's intended to simplify cases where conventional routes overlap.

アクションの明確化Disambiguating actions

2 つのアクションがルーティングで一致する場合、MVC はあいまいさを解消して "最善の" 候補を選ぶか、または例外をスローする必要があります。When two actions match through routing, MVC must disambiguate to choose the 'best' candidate or else throw an exception. 次に例を示します。For example:

public class ProductsController : Controller
{
   public IActionResult Edit(int id) { ... }

   [HttpPost]
   public IActionResult Edit(int id, Product product) { ... }
}

このコントローラーでは、URL パス /Products/Edit/17 およびルート データ { controller = Products, action = Edit, id = 17 } と一致する 2 つのアクションが定義されています。This controller defines two actions that would match the URL path /Products/Edit/17 and route data { controller = Products, action = Edit, id = 17 }. これは、Edit(int) で製品を編集するためのフォームを表示し、Edit(int, Product) で送信されたフォームを処理する MVC コントローラーの一般的なパターンです。This is a typical pattern for MVC controllers where Edit(int) shows a form to edit a product, and Edit(int, Product) processes the posted form. これを MVC で可能にするには、要求が HTTP POST の場合は Edit(int, Product) を選び、それ以外の HTTP 動詞の場合は Edit(int) を選ぶ必要があります。To make this possible MVC would need to choose Edit(int, Product) when the request is an HTTP POST and Edit(int) when the HTTP verb is anything else.

HttpPostAttribute ([HttpPost]) は、HTTP 動詞が POST の場合にのみそのアクションの選択を許可する IActionConstraint の実装です。The HttpPostAttribute ( [HttpPost] ) is an implementation of IActionConstraint that will only allow the action to be selected when the HTTP verb is POST. IActionConstraint が存在すると、Edit(int, Product) の方が Edit(int) より "良い" 一致になるので、Edit(int, Product) が最初に試されます。The presence of an IActionConstraint makes the Edit(int, Product) a 'better' match than Edit(int), so Edit(int, Product) will be tried first.

カスタム IActionConstraint を作成する必要があるのは特殊なシナリオだけですが、HttpPostAttribute のような属性の役割を理解しておくことが重要です。似た属性が他の HTTP 動詞に対しても定義されています。You will only need to write custom IActionConstraint implementations in specialized scenarios, but it's important to understand the role of attributes like HttpPostAttribute - similar attributes are defined for other HTTP verbs. 規則ルーティングでは、アクションが show form -> submit form ワークフローの一部になっている場合、複数のアクションが同じアクション名を使うのはよくあることです。In conventional routing it's common for actions to use the same action name when they're part of a show form -> submit form workflow. IActionConstraint について」セクションを読むと、このパターンの便利さがいっそうよくわかります。The convenience of this pattern will become more apparent after reviewing the Understanding IActionConstraint section.

複数のルートが一致し、MVC が "最善の " ルートを発見できない場合、MVC は AmbiguousActionException をスローします。If multiple routes match, and MVC can't find a 'best' route, it will throw an AmbiguousActionException.

ルート名Route names

次の例の文字列 "blog""default" は、ルート名です。The strings "blog" and "default" in the following examples are route names:

app.UseMvc(routes =>
{
   routes.MapRoute("blog", "blog/{*article}",
               defaults: new { controller = "Blog", action = "Article" });
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

ルート名は、URL の生成に名前付きのルートを使うことができるよう、ルートに論理名を提供します。The route names give the route a logical name so that the named route can be used for URL generation. これは、ルートの順序指定によって URL の生成が複雑になる場合に、URL の作成を大幅に合理化します。This greatly simplifies URL creation when the ordering of routes could make URL generation complicated. ルート名は、アプリケーション全体で一意である必要があります。Route names must be unique application-wide.

ルート名が URL の照合や要求の処理に影響を与えることはありません。ルート名は URL の生成のみに使われます。Route names have no impact on URL matching or handling of requests; they're used only for URL generation. MVC 固有のヘルパーでの URL の生成など、URL の生成について詳しくは、「ルーティング」をご覧ください。Routing has more detailed information on URL generation including URL generation in MVC-specific helpers.

属性ルーティングAttribute routing

属性ルーティングでは、属性のセットを使ってアクションをルート テンプレートに直接マップします。Attribute routing uses a set of attributes to map actions directly to route templates. 次の例では、app.UseMvc();Configure メソッド内で使われており、ルートは渡されていません。In the following example, app.UseMvc(); is used in the Configure method and no route is passed. HomeController は、既定のルート {controller=Home}/{action=Index}/{id?} が一致するのと同じように、URL のセットと一致します。The HomeController will match a set of URLs similar to what the default route {controller=Home}/{action=Index}/{id?} would match:

public class HomeController : Controller
{
   [Route("")]
   [Route("Home")]
   [Route("Home/Index")]
   public IActionResult Index()
   {
      return View();
   }
   [Route("Home/About")]
   public IActionResult About()
   {
      return View();
   }
   [Route("Home/Contact")]
   public IActionResult Contact()
   {
      return View();
   }
}

HomeController.Index() アクションは、URL パス //Home、または /Home/Index のいずれかに対して実行されます。The HomeController.Index() action will be executed for any of the URL paths /, /Home, or /Home/Index.

注意

この例では、属性ルーティングと規則ルーティングでのプログラミングの大きな違いが強調して示されています。This example highlights a key programming difference between attribute routing and conventional routing. 属性ルーティングの方が、ルートを指定するために多くの入力を必要とします。既定の規則ルートの方が簡潔にルートを処理します。Attribute routing requires more input to specify a route; the conventional default route handles routes more succinctly. ただし、属性ルーティングでは、各アクションに適用するルート テンプレートを正確に制御できます (そして制御する必要があります)。However, attribute routing allows (and requires) precise control of which route templates apply to each action.

属性ルーティングでは、コントローラー名とアクション名はアクションの選択において役割を持ちませんWith attribute routing the controller name and action names play no role in which action is selected. この例では、前の例と同じ URL を照合します。This example will match the same URLs as the previous example.

public class MyDemoController : Controller
{
   [Route("")]
   [Route("Home")]
   [Route("Home/Index")]
   public IActionResult MyIndex()
   {
      return View("Index");
   }
   [Route("Home/About")]
   public IActionResult MyAbout()
   {
      return View("About");
   }
   [Route("Home/Contact")]
   public IActionResult MyContact()
   {
      return View("Contact");
   }
}

注意

上のルート テンプレートでは、actionareacontroller のルート パラメーターは定義されていません。The route templates above don't define route parameters for action, area, and controller. 実際、これらのルート パラメーターは属性ルートでは許可されていません。In fact, these route parameters are not allowed in attribute routes. ルート テンプレートはアクションと既に関連付けられているため、URL からアクション名を解析しても意味はありません。Since the route template is already associated with an action, it wouldn't make sense to parse the action name from the URL.

Http[Verb] 属性を使用する属性ルーティングAttribute routing with Http[Verb] attributes

属性ルーティングでは、HttpPostAttribute などの Http[Verb] 属性も使うことができます。Attribute routing can also make use of the Http[Verb] attributes such as HttpPostAttribute. これらの属性はすべて、ルート テンプレートを受け入れることができます。All of these attributes can accept a route template. 次の例では、同じルート テンプレートと一致する 2 つのアクションが示されています。This example shows two actions that match the same route template:

[HttpGet("/products")]
public IActionResult ListProducts()
{
   // ...
}

[HttpPost("/products")]
public IActionResult CreateProduct(...)
{
   // ...
}

/products のような URL パスの場合、HTTP 動詞が GET のときは ProductsApi.ListProducts アクションが実行され、HTTP 動詞が POST のときは ProductsApi.CreateProduct が実行されます。For a URL path like /products the ProductsApi.ListProducts action will be executed when the HTTP verb is GET and ProductsApi.CreateProduct will be executed when the HTTP verb is POST. 属性ルーティングでは、最初に、ルート属性で定義されているルート テンプレートのセットに対して URL が照合されます。Attribute routing first matches the URL against the set of route templates defined by route attributes. ルート テンプレートが一致すると、IActionConstraint 制約が適用されて、実行できるアクションが決定されます。Once a route template matches, IActionConstraint constraints are applied to determine which actions can be executed.

ヒント

REST API を作成するとき、アクション メソッドで [Route(...)] を使う必要があることはあまりありません。When building a REST API, it's rare that you will want to use [Route(...)] on an action method. より固有の Http*Verb*Attributes を使って、API がサポートするものを正確に指定するのがよい方法です。It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. REST API のクライアントは、パスおよび HTTP 動詞と特定の論理操作のマップを理解していることを期待されます。Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

属性ルートは特定のアクションに適用されるため、ルート テンプレート定義の一部として簡単にパラメーターを必須にできます。Since an attribute route applies to a specific action, it's easy to make parameters required as part of the route template definition. 次の例では、id は URL パスの一部として必須です。In this example, id is required as part of the URL path.

public class ProductsApiController : Controller
{
   [HttpGet("/products/{id}", Name = "Products_List")]
   public IActionResult GetProduct(int id) { ... }
}

ProductsApi.GetProduct(int) アクションは、/products/3 のような URL パスに対しては実行されますが、/products のような URL パスに対しては実行されません。The ProductsApi.GetProduct(int) action will be executed for a URL path like /products/3 but not for a URL path like /products. ルート テンプレートと関連するオプションについて詳しくは、「ルーティング」をご覧ください。See Routing for a full description of route templates and related options.

ルート名Route Name

次のコードでは、Products_List の "ルート名" を定義しています。The following code defines a route name of Products_List:

public class ProductsApiController : Controller
{
   [HttpGet("/products/{id}", Name = "Products_List")]
   public IActionResult GetProduct(int id) { ... }
}

ルート名を使うと、特定のルートに基づいて URL を生成できます。Route names can be used to generate a URL based on a specific route. ルート名は、ルーティングの URL 照合動作には影響を与えず、URL 生成に対してのみ使われます。Route names have no impact on the URL matching behavior of routing and are only used for URL generation. ルート名は、アプリケーション全体で一意である必要があります。Route names must be unique application-wide.

注意

これに対し、規則 "既定ルート" では、id パラメーターは省略可能 ({id?}) として定義されています。Contrast this with the conventional default route, which defines the id parameter as optional ({id?}). API を厳密に指定するこの機能には、/products/products/5 を異なるアクションに対してディスパッチできるといった利点があります。This ability to precisely specify APIs has advantages, such as allowing /products and /products/5 to be dispatched to different actions.

ルートの結合Combining routes

属性ルーティングの反復を少なくするため、コントローラーのルート属性は個々のアクションでのルート属性と結合されます。To make attribute routing less repetitive, route attributes on the controller are combined with route attributes on the individual actions. コントローラーで定義されているルート テンプレートが、アクションのルート テンプレートの前に付加されます。Any route templates defined on the controller are prepended to route templates on the actions. ルート属性をコントローラーに配置すると、コントローラーのすべてのアクションが属性ルーティングを使います。Placing a route attribute on the controller makes all actions in the controller use attribute routing.

[Route("products")]
public class ProductsApiController : Controller
{
   [HttpGet]
   public IActionResult ListProducts() { ... }

   [HttpGet("{id}")]
   public ActionResult GetProduct(int id) { ... }
}

次の例では、URL パス /productsProductsApi.ListProducts と一致でき、URL パス /products/5ProductsApi.GetProduct(int) と一致できます。In this example the URL path /products can match ProductsApi.ListProducts, and the URL path /products/5 can match ProductsApi.GetProduct(int). どちらのアクションも、HttpGetAttribute で修飾されているため、HTTP GET だけと一致します。Both of these actions only match HTTP GET because they're decorated with the HttpGetAttribute.

/ または ~/ で始まるアクションに適用されるルート テンプレートは、コントローラーに適用されるルート テンプレートと結合されません。Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller. 次の例は、"既定ルート" と同様の URL パスのセットと一致します。This example matches a set of URL paths similar to the default route.

[Route("Home")]
public class HomeController : Controller
{
    [Route("")]      // Combines to define the route template "Home"
    [Route("Index")] // Combines to define the route template "Home/Index"
    [Route("/")]     // Doesn't combine, defines the route template ""
    public IActionResult Index()
    {
        ViewData["Message"] = "Home index";
        var url = Url.Action("Index", "Home");
        ViewData["Message"] = "Home index" + "var url = Url.Action; =  " + url;
        return View();
    }

    [Route("About")] // Combines to define the route template "Home/About"
    public IActionResult About()
    {
        return View();
    }   
}

属性ルートの順序の指定Ordering attribute routes

定義されている順序で実行される規則ルートとは異なり、属性ルーティングはツリーを作成して、すべてのルートと同時に一致します。In contrast to conventional routes which execute in a defined order, attribute routing builds a tree and matches all routes simultaneously. これは、ルート エントリが理想的な順序で配置されているかのように動作します。一般的なルートより前に、最も固有のルートが実行する機会があります。This behaves as-if the route entries were placed in an ideal ordering; the most specific routes have a chance to execute before the more general routes.

たとえば、blog/search/{topic} のようなルートは、blog/{*article} のようなルートより固有です。For example, a route like blog/search/{topic} is more specific than a route like blog/{*article}. 論理的には、blog/search/{topic} ルートが唯一の意味のある順序なので、既定では、これが最初に "実行" されます。Logically speaking the blog/search/{topic} route 'runs' first, by default, because that's the only sensible ordering. 規則ルーティングを使うときは、開発者が目的の順序でルートを配置する必要があります。Using conventional routing, the developer is responsible for placing routes in the desired order.

属性ルートでは、フレームワークが提供するすべてのルート属性の Order プロパティを使って、順序を構成できます。Attribute routes can configure an order, using the Order property of all of the framework provided route attributes. ルートは、Order プロパティの昇順に従って処理されます。Routes are processed according to an ascending sort of the Order property. 既定の順序は 0 です。The default order is 0. Order = -1 を使ってルートを設定すると、順序が設定されていないルートの前に実行されます。Setting a route using Order = -1 will run before routes that don't set an order. Order = 1 を使ってルートを設定すると、既定のルート順序の後で実行されます。Setting a route using Order = 1 will run after default route ordering.

ヒント

Order には依存しないでください。Avoid depending on Order. URL 空間で正しくルーティングするために明示的な順序値が必要な場合、クライアントの混乱を招く可能性があります。If your URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. 一般に、属性ルーティングは URL 照合で正しいルートを選びます。In general attribute routing will select the correct route with URL matching. URL の生成に使われる既定の順序がうまくいかない場合は、通常、オーバーライドとしてルート名を使う方が、Order プロパティを適用するより簡単です。If the default order used for URL generation isn't working, using route name as an override is usually simpler than applying the Order property.

Razor Pages ルーティングと MVC コントローラー ルーティングは、実装を共有します。Razor Pages routing and MVC controller routing share an implementation. Razor Pages でのルート順序に関する情報は、Razor Pages のルートとアプリの規則: ルート順序に関する記事を参照してください。Information on route order in the Razor Pages topics is available at Razor Pages route and app conventions: Route order.

ルート テンプレートでのトークンの置換 ([controller], [action], [area])Token replacement in route templates ([controller], [action], [area])

利便性のため、属性ルートではトークンを角かっこ ([]) で囲むことによる "トークンの置換" がサポートされています。For convenience, attribute routes support token replacement by enclosing a token in square-braces ([, ]). トークン [action][area]、および [controller] は、ルートが定義されているアクションのアクション名、区分名、コントローラー名の値に置き換えられます。The tokens [action], [area], and [controller] are replaced with the values of the action name, area name, and controller name from the action where the route is defined. 次の例では、アクションはコメントで説明されているように URL パスと一致します。In the following example, the actions match URL paths as described in the comments:

[Route("[controller]/[action]")]
public class ProductsController : Controller
{
    [HttpGet] // Matches '/Products/List'
    public IActionResult List() {
        // ...
    }

    [HttpGet("{id}")] // Matches '/Products/Edit/{id}'
    public IActionResult Edit(int id) {
        // ...
    }
}

属性ルート作成の最後のステップで、トークンの置換が発生します。Token replacement occurs as the last step of building the attribute routes. 上の例は、次のコードと同じように動作します。The above example will behave the same as the following code:


public class ProductsController : Controller
{
    [HttpGet("[controller]/[action]")] // Matches '/Products/List'
    public IActionResult List() {
        // ...
    }

    [HttpGet("[controller]/[action]/{id}")] // Matches '/Products/Edit/{id}'
    public IActionResult Edit(int id) {
        // ...
    }
}

属性ルートを継承と組み合わせることもできます。Attribute routes can also be combined with inheritance. これをトークンの置換と組み合わせると特に強力です。This is particularly powerful combined with token replacement.

[Route("api/[controller]")]
public abstract class MyBaseController : Controller { ... }

public class ProductsController : MyBaseController
{
   [HttpGet] // Matches '/api/Products'
   public IActionResult List() { ... }

   [HttpPut("{id}")] // Matches '/api/Products/{id}'
   public IActionResult Edit(int id) { ... }
}

トークンの置換は、属性ルートで定義されているルート名にも適用されます。Token replacement also applies to route names defined by attribute routes. [Route("[controller]/[action]", Name="[controller]_[action]")] では、アクションごとに一意のルート名が生成されます。[Route("[controller]/[action]", Name="[controller]_[action]")] generates a unique route name for each action.

リテラル トークン置換区切り文字 [ または ] と一致させるためには、その文字を繰り返すことでエスケープします ([[ または ]])。To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

パラメーター トランスフォーマーを使用してトークンの置換をカスタマイズするUse a parameter transformer to customize token replacement

トークンの置換は、パラメーター トランスフォーマーを使用してカスタマイズできます。Token replacement can be customized using a parameter transformer. パラメーター トランスフォーマーは IOutboundParameterTransformer を実装し、パラメーターの値を変換します。A parameter transformer implements IOutboundParameterTransformer and transforms the value of parameters. たとえば、SlugifyParameterTransformer パラメーター トランスフォーマーでは、SubscriptionManagement のルート値が subscription-management に変更されます。For example, a custom SlugifyParameterTransformer parameter transformer changes the SubscriptionManagement route value to subscription-management.

RouteTokenTransformerConvention は、次のようなアプリケーション モデルの規則です。The RouteTokenTransformerConvention is an application model convention that:

  • パラメーター トランスフォーマーをアプリケーションのすべての属性ルートに適用します。Applies a parameter transformer to all attribute routes in an application.
  • 置き換えられる属性ルートのトークン値をカスタマイズします。Customizes the attribute route token values as they are replaced.
public class SubscriptionManagementController : Controller
{
    [HttpGet("[controller]/[action]")] // Matches '/subscription-management/list-all'
    public IActionResult ListAll() { ... }
}

RouteTokenTransformerConvention は、ConfigureServices でオプションとして登録されます。The RouteTokenTransformerConvention is registered as an option in ConfigureServices.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Conventions.Add(new RouteTokenTransformerConvention(
                                     new SlugifyParameterTransformer()));
    });
}

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        // Slugify value
        return Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower();
    }
}

複数のルートMultiple Routes

属性ルーティングでは、同じアクションに到達する複数のルートの定義がサポートされています。Attribute routing supports defining multiple routes that reach the same action. これの最も一般的な使用方法は、次の例で示すように、"既定の規則ルート" の動作を模倣することです。The most common usage of this is to mimic the behavior of the default conventional route as shown in the following example:

[Route("[controller]")]
public class ProductsController : Controller
{
   [Route("")]     // Matches 'Products'
   [Route("Index")] // Matches 'Products/Index'
   public IActionResult Index()
}

コントローラーに複数のルート属性を配置すると、それぞれが、アクション メソッドの各ルート属性と結合します。Putting multiple route attributes on the controller means that each one will combine with each of the route attributes on the action methods.

[Route("Store")]
[Route("[controller]")]
public class ProductsController : Controller
{
   [HttpPost("Buy")]     // Matches 'Products/Buy' and 'Store/Buy'
   [HttpPost("Checkout")] // Matches 'Products/Checkout' and 'Store/Checkout'
   public IActionResult Buy()
}

アクションに (IActionConstraint を実装する) 複数のルート属性を配置すると、各アクション制約がそれを定義した属性のルート テンプレートと結合します。When multiple route attributes (that implement IActionConstraint) are placed on an action, then each action constraint combines with the route template from the attribute that defined it.

[Route("api/[controller]")]
public class ProductsController : Controller
{
   [HttpPut("Buy")]      // Matches PUT 'api/Products/Buy'
   [HttpPost("Checkout")] // Matches POST 'api/Products/Checkout'
   public IActionResult Buy()
}

ヒント

アクションで複数のルートを使うと強力に見えますが、アプリケーションの URL 空間は簡潔で明確に定義された状態に保つことをお勧めします。While using multiple routes on actions can seem powerful, it's better to keep your application's URL space simple and well-defined. アクションで複数のルートを使うのは、必要な場合 (既存のクライアントをサポートする、など) だけにしてください。Use multiple routes on actions only where needed, for example to support existing clients.

属性ルートの省略可能なパラメーター、既定値、制約を指定するSpecifying attribute route optional parameters, default values, and constraints

属性ルートでは、省略可能なパラメーター、既定値、および制約の指定に関して、規則ルートと同じインライン構文がサポートされています。Attribute routes support the same inline syntax as conventional routes to specify optional parameters, default values, and constraints.

[HttpPost("product/{id:int}")]
public IActionResult ShowProduct(int id)
{
   // ...
}

ルート テンプレートの構文について詳しくは、「ルート テンプレート参照」をご覧ください。See Route Template Reference for a detailed description of route template syntax.

IRouteTemplateProvider を使用するカスタム ルート属性Custom route attributes using IRouteTemplateProvider

フレームワークで提供されるすべてのルート属性 ([Route(...)][HttpGet(...)] など) は、IRouteTemplateProvider インターフェイスを実装しています。All of the route attributes provided in the framework ( [Route(...)], [HttpGet(...)] , etc.) implement the IRouteTemplateProvider interface. アプリが起動し、IRouteTemplateProvider を実装している属性を使ってルートの初期セットを作成すると、MVC はコントローラー クラスとアクション メソッドで属性を検索します。MVC looks for attributes on controller classes and action methods when the app starts and uses the ones that implement IRouteTemplateProvider to build the initial set of routes.

IRouteTemplateProvider を実装して、独自のルート属性を定義できます。You can implement IRouteTemplateProvider to define your own route attributes. IRouteTemplateProvider では、カスタム ルート テンプレート、順序、名前を使って 1 つのルートを定義できます。Each IRouteTemplateProvider allows you to define a single route with a custom route template, order, and name:

public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider
{
   public string Template => "api/[controller]";

   public int? Order { get; set; }

   public string Name { get; set; }
}

上の例の属性は、[MyApiController] が適用されると、自動的に Template"api/[controller]" に設定します。The attribute from the above example automatically sets the Template to "api/[controller]" when [MyApiController] is applied.

アプリケーション モデルを使用した属性ルートのカスタマイズUsing Application Model to customize attribute routes

"アプリケーション モデル" は、アクションをルーティングおよび実行するために MVC によって使われるすべてのメタデータで起動時に作成されるオブジェクト モデルです。The application model is an object model created at startup with all of the metadata used by MVC to route and execute your actions. "アプリケーション モデル" には、(IRouteTemplateProvider によって) ルート属性から収集されるすべてのデータが含まれます。The application model includes all of the data gathered from route attributes (through IRouteTemplateProvider). 起動時にアプリケーション モデルを変更してルーティングの動作方法をカスタマイズする "規則" を作成できます。You can write conventions to modify the application model at startup time to customize how routing behaves. このセクションでは、アプリケーション モデルを使ってルーティングをカスタマイズする簡単な例を示します。This section shows a simple example of customizing routing using application model.

using Microsoft.AspNetCore.Mvc.ApplicationModels;
using System.Linq;
using System.Text;
public class NamespaceRoutingConvention : IControllerModelConvention
{
    private readonly string _baseNamespace;

    public NamespaceRoutingConvention(string baseNamespace)
    {
        _baseNamespace = baseNamespace;
    }

    public void Apply(ControllerModel controller)
    {
        var hasRouteAttributes = controller.Selectors.Any(selector =>
                                                selector.AttributeRouteModel != null);
        if (hasRouteAttributes)
        {
            // This controller manually defined some routes, so treat this 
            // as an override and not apply the convention here.
            return;
        }

        // Use the namespace and controller name to infer a route for the controller.
        //
        // Example:
        //
        //  controller.ControllerTypeInfo ->    "My.Application.Admin.UsersController"
        //  baseNamespace ->                    "My.Application"
        //
        //  template =>                         "Admin/[controller]"
        //
        // This makes your routes roughly line up with the folder structure of your project.
        //
        var namespc = controller.ControllerType.Namespace;
        if (namespc == null)
            return;
        var template = new StringBuilder();
        template.Append(namespc, _baseNamespace.Length + 1,
                        namespc.Length - _baseNamespace.Length - 1);
        template.Replace('.', '/');
        template.Append("/[controller]");

        foreach (var selector in controller.Selectors)
        {
            selector.AttributeRouteModel = new AttributeRouteModel()
            {
                Template = template.ToString()
            };
        }
    }
}

混合ルーティング:属性ルーティングと規則ルーティングMixed routing: Attribute routing vs conventional routing

MVC アプリケーションでは、規則ルーティングと属性ルーティングを併用できます。MVC applications can mix the use of conventional routing and attribute routing. 一般に、ブラウザーに HTML ページを提供するコントローラーには規則ルートを使い、REST API を提供するコントローラーには属性ルーティングを使います。It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.

アクションは、規則的にルーティングされるか、または属性でルーティングされます。Actions are either conventionally routed or attribute routed. コントローラーまたはアクションにルートを配置すると、そのルートは属性ルーティングされるようになります。Placing a route on the controller or the action makes it attribute routed. 属性ルートが定義されているアクションには規則ルートでは到達できず、規則ルートが定義されているアクションには属性ルートでは到達できません。Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. コントローラーの任意のルート属性により、コントローラー属性のすべてのアクションがルーティングされます。Any route attribute on the controller makes all actions in the controller attribute routed.

注意

2 種類のルーティング システムを区別しているのは、URL がルート テンプレートと一致した後に適用されるプロセスです。What distinguishes the two types of routing systems is the process applied after a URL matches a route template. 規則ルーティングでは、一致のルート値を使って、規則ルーティングされるすべてのアクションの参照テーブルから、アクションとコントローラーが選ばれます。In conventional routing, the route values from the match are used to choose the action and controller from a lookup table of all conventional routed actions. 属性ルーティングでは、各テンプレートはアクションと既に関連付けられており、それ以上参照する必要はありません。In attribute routing, each template is already associated with an action, and no further lookup is needed.

複雑なセグメントComplex segments

複雑なセグメント (たとえば、[Route("/dog{token}cat")]) は、右から左にリテラルを最短の方法で照合することによって処理されます。Complex segments (for example, [Route("/dog{token}cat")]), are processed by matching up literals from right to left in a non-greedy way. 説明については、ソース コードをご覧ください。See the source code for a description. 詳しくは、こちらの懸案事項をご覧ください。For more information, see this issue.

URL の生成URL Generation

MVC アプリケーションでは、ルーティングの URL 生成機能を使って、アクションへの URL リンクを生成できます。MVC applications can use routing's URL generation features to generate URL links to actions. URL を生成すると URL をハードコーディングする必要がなくなり、コードの堅牢性と保守性が向上します。Generating URLs eliminates hardcoding URLs, making your code more robust and maintainable. このセクションでは、MVC によって提供される URL 生成機能について説明します。URL 生成のしくみに関する基本だけを取り上げます。This section focuses on the URL generation features provided by MVC and will only cover basics of how URL generation works. URL の生成について詳しくは、「ルーティング」をご覧ください。See Routing for a detailed description of URL generation.

IUrlHelper インターフェイスは、MVC と URL 生成のルーティングの間にあるインフラストラクチャの基盤部分です。The IUrlHelper interface is the underlying piece of infrastructure between MVC and routing for URL generation. 使用可能な IUrlHelper のインスタンスは、コントローラー、ビュー、およびビュー コンポーネントの Url プロパティを使って探します。You'll find an instance of IUrlHelper available through the Url property in controllers, views, and view components.

この例の IUrlHelper インターフェイスは、別のアクションへの URL を生成するために Controller.Url プロパティを介して使われています。In this example, the IUrlHelper interface is used through the Controller.Url property to generate a URL to another action.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    public IActionResult Source()
    {
        // Generates /UrlGeneration/Destination
        var url = Url.Action("Destination");
        return Content($"Go check out {url}, it's really great.");
    }

    public IActionResult Destination()
    {
        return View();
    }
}

アプリケーションが既定の規則ルートを使っている場合、url 変数の値は URL パス文字列 /UrlGeneration/Destination になります。If the application is using the default conventional route, the value of the url variable will be the URL path string /UrlGeneration/Destination. この URL パスは、ルーティングにより、現在の要求からのルート値 (アンビエント値) と、Url.Action に渡された値を結合し、これらの値でルート テンプレートを置換することによって作成されます。This URL path is created by routing by combining the route values from the current request (ambient values), with the values passed to Url.Action and substituting those values into the route template:

ambient values: { controller = "UrlGeneration", action = "Source" }
values passed to Url.Action: { controller = "UrlGeneration", action = "Destination" }
route template: {controller}/{action}/{id?}

result: /UrlGeneration/Destination

ルート テンプレートの各ルート パラメーターの値は、一致する名前と値およびアンビエント値によって置換されます。Each route parameter in the route template has its value substituted by matching names with the values and ambient values. 値を持たないルート パラメーターは、既定値がある場合はそれを使うことができ、省略可能な場合はスキップできます (この例の id の場合と同様)。A route parameter that doesn't have a value can use a default value if it has one, or be skipped if it's optional (as in the case of id in this example). 必須のルート パラメーターに対応する値がない場合、URL の生成は失敗します。URL generation will fail if any required route parameter doesn't have a corresponding value. ルートの URL 生成が失敗した場合、すべてのルートが試されるまで、または一致が見つかるまで、次のルートが試されます。If URL generation fails for a route, the next route is tried until all routes have been tried or a match is found.

上の Url.Action の例では規則ルーティングを想定しています。URL 生成は属性ルーティングでも同じように動作しますが、概念は異なります。The example of Url.Action above assumes conventional routing, but URL generation works similarly with attribute routing, though the concepts are different. 規則ルーティングでは、ルート値を使ってテンプレートが展開され、通常、controlleraction のルートがそのテンプレートに表示されます。これは、ルーティングによって一致した URL が "規則" に従うために動作します。With conventional routing, the route values are used to expand a template, and the route values for controller and action usually appear in that template - this works because the URLs matched by routing adhere to a convention. 属性ルーティングでは、controlleraction のルート値はテンプレートに表示できません。代わりに、使うテンプレートの検索に使われます。In attribute routing, the route values for controller and action are not allowed to appear in the template - they're instead used to look up which template to use.

この例では、属性ルーティングを使います。This example uses attribute routing:

// In Startup class
public void Configure(IApplicationBuilder app)
{
    app.UseMvc();
}
using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.Action("Destination"); // Generates /custom/url/to/destination
        return Content($"Go check out {url}, it's really great.");
    }

    [HttpGet("custom/url/to/destination")]
    public IActionResult Destination() {
        return View();
    }
}

MVC はすべての属性ルーティングされるアクションの参照テーブルを作成し、controlleraction の値で照合して、URL 生成に使うルート テンプレートを選びます。MVC builds a lookup table of all attribute routed actions and will match the controller and action values to select the route template to use for URL generation. 上の例では、custom/url/to/destination が生成されます。In the sample above, custom/url/to/destination is generated.

アクション名による URL の生成Generating URLs by action name

Url.Action (IUrlHelper.Url.Action (IUrlHelper . Action) およびすべての関連するオーバーロードは、コントローラー名とアクション名を指定することによってリンク先を指定するアイデアに基づきます。Action) and all related overloads all are based on that idea that you want to specify what you're linking to by specifying a controller name and action name.

注意

Url.Action を使うと、controller および action の現在のルート値が自動的に指定されます。controller および action の値は、"アンビエント値" "" 両方の一部です。When using Url.Action, the current route values for controller and action are specified for you - the value of controller and action are part of both ambient values and values. Url.Action メソッドは、常に actioncontroller の現在の値は使い、現在のアクションにルーティングする URL パスを生成します。The method Url.Action, always uses the current values of action and controller and will generate a URL path that routes to the current action.

ルーティングは、ユーザーが URL 生成時に指定しなかった情報を、アンビエント値を使って埋めようとします。Routing attempts to use the values in ambient values to fill in information that you didn't provide when generating a URL. {a}/{b}/{c}/{d} やアンビエント値 { a = Alice, b = Bob, c = Carol, d = David } のようなルートを使うと、すべてのルート パラメーターが値を持っているため、ルーティングには URL を生成するための十分な情報があり、追加の値は必要ありません。Using a route like {a}/{b}/{c}/{d} and ambient values { a = Alice, b = Bob, c = Carol, d = David }, routing has enough information to generate a URL without any additional values - since all route parameters have a value. { d = Donovan } を追加した場合は、値 { d = David } は無視されて、生成される URL パスは Alice/Bob/Carol/Donovan になります。If you added the value { d = Donovan }, the value { d = David } would be ignored, and the generated URL path would be Alice/Bob/Carol/Donovan.

警告

URL パスは階層的です。URL paths are hierarchical. 上の例で、値 { c = Cheryl } を追加した場合は、両方の値 { c = Carol, d = David } が無視されます。In the example above, if you added the value { c = Cheryl }, both of the values { c = Carol, d = David } would be ignored. この場合、d には値がなくなり、URL の生成は失敗します。In this case we no longer have a value for d and URL generation will fail. c および d の目的の値を指定する必要があります。You would need to specify the desired value of c and d. 既定のルート ({controller}/{action}/{id?}) でもこの問題が発生すると思われるかもしれませんが、Url.Action が常に controlleraction の値を明示的に指定するので、実際には、このような動作が発生することはほとんどありません。You might expect to hit this problem with the default route ({controller}/{action}/{id?}) - but you will rarely encounter this behavior in practice as Url.Action will always explicitly specify a controller and action value.

Url.Action の長いオーバーロードも、追加の "ルート値" オブジェクトを受け取って、controller および action 以外のルート パラメーターの値を提供します。Longer overloads of Url.Action also take an additional route values object to provide values for route parameters other than controller and action. これを最もよく目にするのは、Url.Action("Buy", "Products", new { id = 17 }) のように id で使われる場合です。You will most commonly see this used with id like Url.Action("Buy", "Products", new { id = 17 }). 慣例では、"ルート値" オブジェクトは通常は匿名型のオブジェクトですが、IDictionary<> または "単純な従来の .NET オブジェクト" を使うこともできます。By convention the route values object is usually an object of anonymous type, but it can also be an IDictionary<> or a plain old .NET object. ルート パラメーターと一致しないすべての追加ルート値は、クエリ文字列に格納されます。Any additional route values that don't match route parameters are put in the query string.

using Microsoft.AspNetCore.Mvc;

public class TestController : Controller
{
    public IActionResult Index()
    {
        // Generates /Products/Buy/17?color=red
        var url = Url.Action("Buy", "Products", new { id = 17, color = "red" });
        return Content(url);
    }
}

ヒント

絶対 URL を作成するには、protocol を受け取るオーバーロードを使います。Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)To create an absolute URL, use an overload that accepts a protocol: Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)

ルートによる URL の生成Generating URLs by route

上記のコードでは、コントローラーとアクション名を渡すことによる URL の生成を示しました。The code above demonstrated generating a URL by passing in the controller and action name. IUrlHelper では、Url.RouteUrl ファミリ メソッドも提供されています。IUrlHelper also provides the Url.RouteUrl family of methods. これらのメソッドは、Url.Action と似ていますが、action および controller の現在の値をルート値にコピーしません。These methods are similar to Url.Action, but they don't copy the current values of action and controller to the route values. 最も一般的な使用方法は、ルート名を指定して特定のルートを使って URL を生成する場合です。通常、コントローラーまたはアクション名は指定 "しません"。The most common usage is to specify a route name to use a specific route to generate the URL, generally without specifying a controller or action name.

using Microsoft.AspNetCore.Mvc;

public class UrlGenerationController : Controller
{
    [HttpGet("")]
    public IActionResult Source()
    {
        var url = Url.RouteUrl("Destination_Route"); // Generates /custom/url/to/destination
        return Content($"See {url}, it's really great.");
    }

    [HttpGet("custom/url/to/destination", Name = "Destination_Route")]
    public IActionResult Destination() {
        return View();
    }
}

HTML での URL の生成Generating URLs in HTML

IHtmlHelper で提供されている HtmlHelper メソッドの Html.BeginForm および Html.ActionLink は、それぞれ <form> 要素と <a> 要素を生成します。IHtmlHelper provides the HtmlHelper methods Html.BeginForm and Html.ActionLink to generate <form> and <a> elements respectively. これらのメソッドは Url.Action メソッドを使って URL を生成するので、同じような引数を受け取ります。These methods use the Url.Action method to generate a URL and they accept similar arguments. HtmlHelperUrl.RouteUrl コンパニオンは、同様の機能を持つ Html.BeginRouteFormHtml.RouteLink です。The Url.RouteUrl companions for HtmlHelper are Html.BeginRouteForm and Html.RouteLink which have similar functionality.

TagHelper は、form TagHelper と <a> TagHelper を使って URL を生成します。TagHelpers generate URLs through the form TagHelper and the <a> TagHelper. これらはどちらも、実装に IUrlHelper を使います。Both of these use IUrlHelper for their implementation. 詳しくは、「フォームの操作」をご覧ください。See Working with Forms for more information.

ビューの内部では、Url プロパティを使って任意のアドホック URL 生成に IUrlHelper を使うことができます (上の記事では説明されていません)。Inside views, the IUrlHelper is available through the Url property for any ad-hoc URL generation not covered by the above.

アクションの結果での URL の生成Generating URLS in Action Results

上の例ではコントローラーでの IUrlHelper の使用が示されていますが、コントローラーでの最も一般的な使用方法はアクションの結果の一部として URL を生成することです。The examples above have shown using IUrlHelper in a controller, while the most common usage in a controller is to generate a URL as part of an action result.

基底クラス ControllerBase および Controller では、別のアクションを参照するアクション結果用の便利なメソッドが提供されています。The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. 一般的な使用法の 1 つは、ユーザー入力を受け付けた後でリダイレクトする場合です。One typical usage is to redirect after accepting user input.

public IActionResult Edit(int id, Customer customer)
{
    if (ModelState.IsValid)
    {
        // Update DB with new details.
        return RedirectToAction("Index");
    }
    return View(customer);
}

アクション結果ファクトリ メソッドは、IUrlHelper のメソッドに似たパターンに従います。The action results factory methods follow a similar pattern to the methods on IUrlHelper.

専用規則ルートの特殊なケースSpecial case for dedicated conventional routes

規則ルーティングでは、"専用規則ルート" と呼ばれる特殊なルート定義を使うことができます。Conventional routing can use a special kind of route definition called a dedicated conventional route. 次の例の blog という名前のルートが専用規則ルートです。In the example below, the route named blog is a dedicated conventional route.

app.UseMvc(routes =>
{
    routes.MapRoute("blog", "blog/{*article}",
        defaults: new { controller = "Blog", action = "Article" });
    routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

これらのルート定義を使うと、Url.Action("Index", "Home")default ルートで URL パス / を生成します。なぜでしょうか。Using these route definitions, Url.Action("Index", "Home") will generate the URL path / with the default route, but why? ルート値 { controller = Home, action = Index }blog を使って URL を生成するのに十分であり、結果は /blog?action=Index&controller=Home になるように思われます。You might guess the route values { controller = Home, action = Index } would be enough to generate a URL using blog, and the result would be /blog?action=Index&controller=Home.

専用規則ルートは、URL の生成でルートの "一致範囲が広くなりすぎる" のを防ぐために対応するルート パラメーターを持たない既定値の特別な動作に依存します。Dedicated conventional routes rely on a special behavior of default values that don't have a corresponding route parameter that prevents the route from being "too greedy" with URL generation. この場合、既定値は { controller = Blog, action = Article } であり、controlleraction はどちらもルート パラメーターとして表示されません。In this case the default values are { controller = Blog, action = Article }, and neither controller nor action appears as a route parameter. ルーティングが URL 生成を実行するとき、指定された値は既定値と一致する必要があります。When routing performs URL generation, the values provided must match the default values. { controller = Home, action = Index }{ controller = Blog, action = Article } と一致しないため、blog を使った URL の生成は失敗します。URL generation using blog will fail because the values { controller = Home, action = Index } don't match { controller = Blog, action = Article }. そして、ルーティングはフォールバックして default を試み、これは成功します。Routing then falls back to try default, which succeeds.

AreasAreas

区分は MVC の機能であり、関連する機能を独立したルーティング名前空間 (コントローラー アクションの場合) およびフォルダー構造 (ビューの場合) としてグループ化するために使われます。Areas are an MVC feature used to organize related functionality into a group as a separate routing-namespace (for controller actions) and folder structure (for views). 区分を使うと、アプリケーションは同じ名前の複数のコントローラーを持つことができます (ただし、"区分" が異なる場合)。Using areas allows an application to have multiple controllers with the same name - as long as they have different areas. 区分を使い、別のルート パラメーター areacontroller および action に追加することで、ルーティングのための階層を作成します。Using areas creates a hierarchy for the purpose of routing by adding another route parameter, area to controller and action. このセクションでは、ルーティングと区分がどのように相互作用するのかについて説明します。ビューでの区分の使い方について詳しくは、「区分」をご覧ください。This section will discuss how routing interacts with areas - see Areas for details about how areas are used with views.

次の例では、既定の規則ルートと、Blog という名前の区分に対する "区分ルート" を使うように、MVC を構成しています。The following example configures MVC to use the default conventional route and an area route for an area named Blog:

app.UseMvc(routes =>
{
    routes.MapAreaRoute("blog_route", "Blog",
        "Manage/{controller}/{action}/{id?}");
    routes.MapRoute("default_route", "{controller}/{action}/{id?}");
});

/Manage/Users/AddUser のような URL パスを照合すると、最初のルートではルート値 { area = Blog, controller = Users, action = AddUser } が生成されます。When matching a URL path like /Manage/Users/AddUser, the first route will produce the route values { area = Blog, controller = Users, action = AddUser }. area ルート値は、area の既定値によって生成されます。実際には、MapAreaRoute によって作成されるルートは以下と同等です。The area route value is produced by a default value for area, in fact the route created by MapAreaRoute is equivalent to the following:

app.UseMvc(routes =>
{
    routes.MapRoute("blog_route", "Manage/{controller}/{action}/{id?}",
        defaults: new { area = "Blog" }, constraints: new { area = "Blog" });
    routes.MapRoute("default_route", "{controller}/{action}/{id?}");
});

MapAreaRoute は、指定された区分名 (この場合はBlog) を使い、既定値と、area に対する制約の両方からルートを作成します。MapAreaRoute creates a route using both a default value and constraint for area using the provided area name, in this case Blog. 既定値はルートが常に { area = Blog, ... } を生成することを保証し、制約では URL を生成するために値 { area = Blog, ... } が必要です。The default value ensures that the route always produces { area = Blog, ... }, the constraint requires the value { area = Blog, ... } for URL generation.

ヒント

規則ルーティングは順序に依存します。Conventional routing is order-dependent. 一般に、区分のあるルートは区分を持たないルートより具体的なので、区分のあるルートはルート テーブルの前の方に配置する必要があります。In general, routes with areas should be placed earlier in the route table as they're more specific than routes without an area.

上の例を使うと、ルート値は次のアクションと一致します。Using the above example, the route values would match the following action:

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        public IActionResult AddUser()
        {
            return View();
        }        
    }
}

AreaAttribute はコントローラーが区分の一部であることを示すものであり、このコントローラーは Blog 区分に含まれます。The AreaAttribute is what denotes a controller as part of an area, we say that this controller is in the Blog area. [Area] 属性を持たないコントローラーはどの区域のメンバーでもなく、area ルート値がルーティングによって提供されたときは一致しませんControllers without an [Area] attribute are not members of any area, and will not match when the area route value is provided by routing. 次の例では、リストの最初のコントローラーだけがルート値 { area = Blog, controller = Users, action = AddUser } と一致できます。In the following example, only the first controller listed can match the route values { area = Blog, controller = Users, action = AddUser }.

using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace1
{
    [Area("Blog")]
    public class UsersController : Controller
    {
        public IActionResult AddUser()
        {
            return View();
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace2
{
    // Matches { area = Zebra, controller = Users, action = AddUser }
    [Area("Zebra")]
    public class UsersController : Controller
    {
        public IActionResult AddUser()
        {
            return View();
        }        
    }
}
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace3
{
    // Matches { area = string.Empty, controller = Users, action = AddUser }
    // Matches { area = null, controller = Users, action = AddUser }
    // Matches { controller = Users, action = AddUser }
    public class UsersController : Controller
    {
        public IActionResult AddUser()
        {
            return View();

        }
    }
}

注意

ここでは完全を期すために各コントローラーの名前空間を示してあります。そうしないと、コントローラーの名前が競合し、コンパイラ エラーが発生します。The namespace of each controller is shown here for completeness - otherwise the controllers would have a naming conflict and generate a compiler error. クラスの名前空間は、MVC のルーティングに対して影響を与えません。Class namespaces have no effect on MVC's routing.

最初の 2 つのコントローラーは区分のメンバーであり、それぞれの区分名が area ルート値によって提供された場合にのみ一致します。The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. 3 番目のコントローラーはどの区分のメンバーでもなく、ルーティングによって area の値が提供されない場合にのみ一致します。The third controller isn't a member of any area, and can only match when no value for area is provided by routing.

注意

"値なし" との一致では、area の値がないことは、area の値が null または空の文字列であることと同じです。In terms of matching no value, the absence of the area value is the same as if the value for area were null or the empty string.

区分の内部でアクションを実行するとき、area のルート値は、URL の生成に使うルーティングの "アンビエント値" として利用できます。When executing an action inside an area, the route value for area will be available as an ambient value for routing to use for URL generation. つまり、既定では、次の例で示すように、区分は URL の生成に対する "付箋" として機能します。This means that by default areas act sticky for URL generation as demonstrated by the following sample.

app.UseMvc(routes =>
{
    routes.MapAreaRoute("duck_route", "Duck",
        "Manage/{controller}/{action}/{id?}");
    routes.MapRoute("default", "Manage/{controller=Home}/{action=Index}/{id?}");
});
using Microsoft.AspNetCore.Mvc;

namespace MyApp.Namespace4
{
    [Area("Duck")]
    public class UsersController : Controller
    {
        public IActionResult GenerateURLInArea()
        {
            // Uses the 'ambient' value of area
            var url = Url.Action("Index", "Home"); 
            // returns /Manage
            return Content(url);
        }

        public IActionResult GenerateURLOutsideOfArea()
        {
            // Uses the empty value for area
            var url = Url.Action("Index", "Home", new { area = "" }); 
            // returns /Manage/Home/Index
            return Content(url);
        }
    }
}

IActionConstraint についてUnderstanding IActionConstraint

注意

このセクションでは、フレームワークの内部構造と MVC が実行するアクションを選ぶ方法について詳しく説明します。This section is a deep-dive on framework internals and how MVC chooses an action to execute. 一般的なアプリケーションでは、カスタム IActionConstraint は必要ありません。A typical application won't need a custom IActionConstraint

インターフェイスにあまり詳しくない場合でも、既に IActionConstraint を使ったことがあるはずです。You have likely already used IActionConstraint even if you're not familiar with the interface. [HttpGet] 属性およびそれに似た [Http-VERB] 属性は、アクション メソッドの実行を制限するために IActionConstraint を実装しています。The [HttpGet] Attribute and similar [Http-VERB] attributes implement IActionConstraint in order to limit the execution of an action method.

public class ProductsController : Controller
{
    [HttpGet]
    public IActionResult Edit() { }

    public IActionResult Edit(...) { }
}

既定の規則ルートでは、URL パス /Products/Edit は値 { controller = Products, action = Edit } を生成し、ここで示す両方のアクションと一致するものとします。Assuming the default conventional route, the URL path /Products/Edit would produce the values { controller = Products, action = Edit }, which would match both of the actions shown here. IActionConstraint ではこれを、両方のアクションが候補と見なされる、といいます。どちらもルート データと一致するからです。In IActionConstraint terminology we would say that both of these actions are considered candidates - as they both match the route data.

HttpGetAttribute は実行すると、Edit()GET に対して一致し、他の HTTP 動詞には一致しないことを示します。When the HttpGetAttribute executes, it will say that Edit() is a match for GET and isn't a match for any other HTTP verb. Edit(...) アクションには制約が定義されていないので、すべての HTTP 動詞と一致します。The Edit(...) action doesn't have any constraints defined, and so will match any HTTP verb. したがって、POSTEdit(...) のみと一致します。So assuming a POST - only Edit(...) matches. 一方、GET の場合は両方のアクションが一致します。しかし、IActionConstraint を指定されているアクションの方が常に、指定されていないアクション "より適切" であると見なされます。But, for a GET both actions can still match - however, an action with an IActionConstraint is always considered better than an action without. したがって、Edit() には [HttpGet] があるので、より具体的と見なされ、両方のアクションが一致する場合はこちらが選ばれます。So because Edit() has [HttpGet] it's considered more specific, and will be selected if both actions can match.

概念的には、IActionConstraint は "オーバーロード" の形式ですが、同じ名前のメソッドをオーバーロードするのではなく、同じ URL に一致するアクション間でオーバーロードします。Conceptually, IActionConstraint is a form of overloading, but instead of overloading methods with the same name, it's overloading between actions that match the same URL. 属性ルーティングも IActionConstraint を使い、異なるコントローラーのアクションがどちらも候補と見なされる結果になることがあります。Attribute routing also uses IActionConstraint and can result in actions from different controllers both being considered candidates.

IActionConstraint の実装Implementing IActionConstraint

IActionConstraint を実装する最も簡単な方法は、System.Attribute の派生クラスを作成し、アクションとコントローラーに配置する方法です。The simplest way to implement an IActionConstraint is to create a class derived from System.Attribute and place it on your actions and controllers. MVC は、属性として適用された IActionConstraint を自動的に検出します。MVC will automatically discover any IActionConstraint that are applied as attributes. アプリケーション モデルを使って制約を適用することができ、適用方法をメタプログラムできるので、おそらくこれが最も柔軟なアプローチです。You can use the application model to apply constraints, and this is probably the most flexible approach as it allows you to metaprogram how they're applied.

次の例の制約は、ルート データの "国コード" に基づいてアクションを選びます。In the following example a constraint chooses an action based on a country code from the route data. GitHub の完全なサンプルはこちらをご覧ください。The full sample on GitHub.

public class CountrySpecificAttribute : Attribute, IActionConstraint
{
    private readonly string _countryCode;

    public CountrySpecificAttribute(string countryCode)
    {
        _countryCode = countryCode;
    }

    public int Order
    {
        get
        {
            return 0;
        }
    }

    public bool Accept(ActionConstraintContext context)
    {
        return string.Equals(
            context.RouteContext.RouteData.Values["country"].ToString(),
            _countryCode,
            StringComparison.OrdinalIgnoreCase);
    }
}

ユーザーは、Accept メソッドを実装し、実行する制約の "順序" を選ぶ必要があります。You are responsible for implementing the Accept method and choosing an 'Order' for the constraint to execute. この例では、country ルート値が一致すると、Accept メソッドは true を返してアクションが一致することを示します。In this case, the Accept method returns true to denote the action is a match when the country route value matches. この動作は、非属性アクションにフォールバックできる RouteValueAttribute とは異なります。This is different from a RouteValueAttribute in that it allows fallback to a non-attributed action. サンプルでは、en-US アクションを定義すると、fr-FR のような国コードは [CountrySpecific(...)] が適用されていない、より一般的なコントローラーにフォールバックすることが示されています。The sample shows that if you define an en-US action then a country code like fr-FR will fall back to a more generic controller that doesn't have [CountrySpecific(...)] applied.

Order プロパティは、制約が含まれる "ステージ" を決定します。The Order property decides which stage the constraint is part of. アクションの制約は、Order に基づいてグループで実行されます。Action constraints run in groups based on the Order. たとえば、フレームワークで提供されるすべての HTTP メソッド属性は、同じステージで実行されるように、同じ Order 値を使います。For example, all of the framework provided HTTP method attributes use the same Order value so that they run in the same stage. 目的のポリシーを実装するため、必要なだけいくつでもステージを使うことができます。You can have as many stages as you need to implement your desired policies.

ヒント

Order の値を決めるときは、HTTP メソッドより前に制約を適用する必要があるかどうかを考えます。To decide on a value for Order think about whether or not your constraint should be applied before HTTP methods. 小さい値が先に実行されます。Lower numbers run first.