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. 고급 라우팅에 대한 자세한 내용은 라우팅을 참조하세요.See Routing for details on advanced routing.

라우팅 미들웨어 설정Setting up Routing Middleware

구성된 메서드에서 다음과 비슷한 코드를 볼 수 있습니다.In your Configure method you may see code similar to:

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

UseMvc 호출 내부에서, MapRoutedefault 경로라고 부르는 단일 경로를 만드는 데 사용됩니다.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의 값으로 기본값이 사용되며, URL 경로에 해당 세그먼트 없기 때문에 id가 값을 생성하지 않습니다.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는 이러한 경로 값을 사용하여 HomeControllerIndex 작업을 선택합니다.MVC would use these route values to select the HomeController and Index action:

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

이 컨트롤러 정의와 경로 템플릿을 사용하면 다음 URL 경로에 대해 HomeController.Index 작업이 실행됩니다.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?}");
});

UseMvcUseMvcWithDefaultRouteRouterMiddleware 인스턴스를 미들웨어 파이프라인에 추가합니다.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

  • 두 번째는 작업 이름에 매핑됩니다.the second maps to the action name.

  • 세 번째 세그먼트는 모델 엔터티에 매핑하는 데 사용되는 선택적 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. 일반적으로 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

두 작업이 라우팅을 통해 일치하는 경우 MVC는 작업을 명확히 구분하여 '최적의' 후보를 선택해야 하며, 그렇지 못하면 예외가 throw됩니다.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 }과 일치하는 두 작업을 정의합니다.This controller defines two actions that would match the URL path /Products/Edit/17 and route data { controller = Products, action = Edit, id = 17 }. 이것은 MVC 컨트롤러의 일반적인 패턴으로, Edit(int) 는 제품을 편집할 양식을 보여주고 Edit(int, Product)는 게시된 양식을 처리합니다.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. 이것을 가능하게 만들려면 요청이 HTTP POST이면 MVC가 Edit(int, Product)를 선택해야 하고, HTTP 동사가 그 외의 다른 것이면 MVC가 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을 throw합니다.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");
   }
}

참고

위의 경로 템플릿은 action, areacontroller에 대한 경로 매개 변수를 정의하지 않습니다.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[동사] 특성을 포함한 라우팅 특성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. 이 예에서는 동일한 경로 템플릿과 일치하는 두 가지 작업을 보여줍니다.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 a / 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.

경로 템플릿에서 토큰 바꾸기([컨트롤러] [작업] [지역])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] will be replaced with the values of the action name, area name, and controller name from the action where the route is defined. 이 예의 작업은 주석에 설명된 대로 URL 경로를 매칭할 수 있습니다.In this example the actions can 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]")] will generate a unique route name for each action.

리터럴 토큰 교체 구분 기호 [ 또는 ]와 매칭하려면 문자([[ 또는 ]])를 반복하여 이스케이프합니다.To match the literal token replacement delimiter [ or ], escape it by repeating the character ([[ or ]]).

여러 경로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. 앱이 시작되면 MVC는 컨트롤러 클래스 및 작업 메서드에서 특성을 찾아 IRouteTemplateProvider를 구현하는 특성을 사용하여 초기 경로 집합을 빌드합니다.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를 사용하여 사용자 지정 경로 템플릿, 순서 및 이름으로 단일 경로를 정의할 수 있습니다.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.

참고

두 라우팅 시스템의 차이는 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.

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. 컨트롤러, 보기 및 보기 구성 요소의 Url 속성을 통해 제공되는 IUrlHelper 인스턴스를 찾을 수 있습니다.You'll find an instance of IUrlHelper available through the Url property in controllers, views, and view components.

이 예에서 IUrlHelper 인터페이스는 Controller.Url 속성을 통해 다른 작업에 대한 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을 사용하면 controlleraction의 현재 경로 값이 자동으로 지정됩니다. controlleraction의 값은 앰비언트 값 의 일부입니다.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 } 값이 무시되고 Alice/Bob/Carol/Donovan URL 경로가 생성됩니다.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. 원하는 cd 값을 지정해야 합니다.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 오버로드가 길면 controlleraction이 아닌 경로 매개 변수의 값을 제공하기 위해 추가 경로 값 개체가 사용됩니다.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과 비슷하지만, actioncontroller의 현재 값을 경로 값에 복사하지 않습니다.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는 각각 <form><a> 요소를 생성하는 HtmlHelper 메서드 Html.BeginFormHtml.ActionLink를 제공합니다.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. HtmlHelper에 대한 Url.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.

보기 내에서, IUrlHelper는 위에서 다루지 않은 임시 URL 생성에 대한 Url 속성을 통해 사용할 수 있습니다.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.

ControllerBaseController 기본 클래스는 다른 작업을 참조하는 작업 결과에 대한 편의 메서드를 제공합니다.The ControllerBase and Controller base classes provide convenience methods for action results that reference another action. 한 가지 일반적인 사용법은 사용자 입력을 수락한 후 리디렉션하는 것입니다.One typical usage is to redirect after accepting user input.

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

작업 결과 팩터리 메서드는 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.

영역Areas

영역은 관련 기능을 별도의 라우팅-네임스페이스(컨트롤러 작업용) 및 폴더 구조(보기용)로 그룹화하는 데 사용되는 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. 영역을 사용하면 다른 경로 매개 변수 areacontrolleraction에 추가하여 라우팅을 위한 계층 구조가 생성됩니다.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는 입력된 영역 이름을 사용하는 area의 기본값 및 제약 조건을 모두 사용하는 경로로, 이 예에서는 Blog입니다.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.

처음 두 컨트롤러는 영역의 구성원이며, area 경로 값에서 해당 영역 이름을 제공하는 경우에만 매칭됩니다.The first two controllers are members of areas, and only match when their respective area name is provided by the area route value. 세 번째 컨트롤러는 어떤 영역의 구성원도 아니며, 라우팅에서 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 생성을 위한 sticky 역할을 합니다.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. 따라서 POST를 가정하면 Edit(...)만 일치합니다.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. 이 예에서 Accept 메서드는 country 경로 값이 일치하면 작업이 일치한다는 것을 나타내기 위해 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.