Маршрутизация в ASP.NET CoreRouting in ASP.NET Core

Авторы: Райан Новак (Ryan Nowak), Стив Смит (Steve Smith) и Рик Андерсон (Rick Anderson)By Ryan Nowak, Steve Smith, and Rick Anderson

Маршрутизация отвечает за сопоставление URI запросов с конечными точками и отправку входящих запросов к этим конечным точкам.Routing is responsible for mapping request URIs to endpoints and dispatching incoming requests to those endpoints. Маршруты определяются в приложении и настраиваются при его запуске.Routes are defined in the app and configured when the app starts. Маршрут может также извлекать значения из содержащегося в запросе URL-адреса, которые затем используются для обработки запроса.A route can optionally extract values from the URL contained in the request, and these values can then be used for request processing. С помощью сведений о маршрутах из приложения маршрутизация также может формировать URL-адреса, которые сопоставляются с конечными точками.Using route information from the app, routing is also able to generate URLs that map to endpoints. Многим приложениям не нужно добавлять маршруты помимо тех, которые предоставлены шаблонами.Many apps don't need to add routes beyond what the templates provide. Шаблоны ASP.NET Core для контроллеров и страниц Razor настраивают конечные точки маршрута.The ASP.NET Core templates for controllers and Razor pages configure route endpoints. Если вам необходимо добавить пользовательские конечные точки маршрута, их можно настроить с конечными точками маршрута, созданными на основе шаблона.If you need to add custom route endpoints, the custom endpoints can be configured alongside template generated route endpoints.

Важно!

В этом документе рассматривается низкоуровневая маршрутизация ASP.NET Core.This document covers low-level ASP.NET Core routing. Сведения о маршрутизации ASP.NET Core MVC см. в разделе Маршрутизация к действиям контроллера в ASP.NET Core.For information on ASP.NET Core MVC routing, see Маршрутизация к действиям контроллера в ASP.NET Core. Сведения о соглашениях о маршрутизации в Razor Pages см. в разделе Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.For information on routing conventions in Razor Pages, see Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

Основы маршрутизацииRouting basics

Для большинства приложений следует выбрать базовую описательную схему маршрутизации таким образом, чтобы URL-адреса были удобочитаемыми и осмысленными.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. Традиционный маршрут по умолчанию {controller=Home}/{action=Index}/{id?}.The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Поддерживает основную и описательную схемы маршрутизации.Supports a basic and descriptive routing scheme.
  • Является отправной точкой для приложений на базе пользовательского интерфейса.Is a useful starting point for UI-based apps.

Как правило, в зонах приложения с высоким трафиком и в особых случаях (например, конечные точки блога, интернет-магазина) добавляются дополнительные краткие маршруты с использованием маршрутизации с помощью атрибутов или выделенные традиционные маршруты.Developers commonly add additional terse routes to high-traffic areas of an app in specialized situations (for example, blog and ecommerce endpoints) using attribute routing or dedicated conventional routes.

Веб-интерфейсы API должны использовать маршрутизацию с помощью атрибутов, чтобы моделировать функциональность приложения в качестве набора ресурсов, где операции представлены с помощью команд HTTP.Web APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs. Это означает, что многие операции (например, GET, POST) на одном логическом ресурсе будут использовать одинаковый URL-адрес.This means that many operations (for example, GET, POST) on the same logical resource will use the same URL. Маршрутизация с помощью атрибутов обеспечивает необходимый уровень контроля, позволяющий тщательно разработать схему общедоступных конечных точек API-интерфейса.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Приложения Razor Pages используют стандартную маршрутизацию по умолчанию для предоставления именованных ресурсов в папке Pages приложения.Razor Pages apps use default conventional routing to serve named resources in the Pages folder of an app. Доступны дополнительные соглашения, которые позволяют настроить поведение маршрутизации Razor Pages.Additional conventions are available that allow you to customize Razor Pages routing behavior. Дополнительные сведения см. в разделах Введение в Razor Pages в ASP.NET Core и Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.For more information, see Введение в Razor Pages в ASP.NET Core and Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.

Благодаря поддержке создания URL-адресов приложение можно разрабатывать без жесткого программирования URL-адресов для связывания компонентов приложения.URL generation support allows the app to be developed without hard-coding URLs to link the app together. Это обеспечивает начало работы с основной конфигурацией маршрутизации и изменение маршрутов после определения схемы ресурсов приложения.This support allows for starting with a basic routing configuration and modifying the routes after the app's resource layout is determined.

Маршрутизация использует конечные точки (Endpoint) для представления логических конечных точек в приложении.Routing uses endpoints (Endpoint) to represent logical endpoints in an app.

Конечная точка определяет делегат для обработки запросов и коллекцию произвольных метаданных.An endpoint defines a delegate to process requests and a collection of arbitrary metadata. Метаданные используются для реализации сквозной функциональности на основе политик и конфигурации каждой конечной точки.The metadata is used to implement cross-cutting concerns based on policies and configuration attached to each endpoint.

Система маршрутизации обладает следующими характеристиками:The routing system has the following characteristics:

  • Синтаксис шаблона маршрута используется для определения маршрутов с помощью параметров размеченного маршрута.Route template syntax is used to define routes with tokenized route parameters.

  • Допускается конфигурация конечной точки в стандартном стиле и с атрибутами.Conventional-style and attribute-style endpoint configuration is permitted.

  • IRouteConstraint используется для определения того, содержит ли параметр URL-адреса допустимое значение для ограничения заданной конечной точки.IRouteConstraint is used to determine whether a URL parameter contains a valid value for a given endpoint constraint.

  • Модели приложения, такие как MVC и Razor Pages, регистрируют все свои конечные точки, имеющие предсказуемую реализацию сценариев маршрутизации.App models, such as MVC/Razor Pages, register all of their endpoints, which have a predictable implementation of routing scenarios.

  • Реализация маршрутизации принимает решения о маршрутизации в нужном месте конвейера ПО промежуточного слоя.The routing implementation makes routing decisions wherever desired in the middleware pipeline.

  • ПО промежуточного слоя, которое появляется после ПО промежуточного слоя маршрутизации, может проверить результат принятия решений о конечной точке, принятое ПО промежуточного слоя маршрутизации для заданного URI запроса.Middleware that appears after a Routing Middleware can inspect the result of the Routing Middleware's endpoint decision for a given request URI.

  • Можно перечислить все конечные точки в приложении в любом месте конвейера ПО промежуточного слоя.It's possible to enumerate all of the endpoints in the app anywhere in the middleware pipeline.

  • Приложение может использовать маршрутизацию для формирования URL-адресов (например, для перенаправления или ссылок) на основе сведений о конечной точке, что позволяет избежать жесткого задания URL-адресов и упрощает поддержку.An app can use routing to generate URLs (for example, for redirection or links) based on endpoint information and thus avoid hard-coded URLs, which helps maintainability.

  • Формирование URL-адреса основано на адресах, которые поддерживают произвольную расширяемость:URL generation is based on addresses, which support arbitrary extensibility:

    • API генератора ссылок (LinkGenerator) может быть разрешено в любом месте с помощью внедрения зависимостей (DI) для формирования URL-адреса.The Link Generator API (LinkGenerator) can be resolved anywhere using dependency injection (DI) to generate URLs.
    • Если API генератора ссылок недоступно через внедрение зависимостей, IUrlHelper предлагает методы для создания URL-адреса.Where the Link Generator API isn't available via DI, IUrlHelper offers methods to build URLs.

Примечание

Связывание конечных точек ограничено действиями и страницами MVC и Razor Pages.Endpoint linking is limited to MVC/Razor Pages actions and pages. Расширение функций связывания конечных точек планируется в будущих выпусках.The expansions of endpoint-linking capabilities is planned for future releases.

Функция маршрутизации подключается к конвейеру ПО промежуточного слоя с помощью класса RouterMiddleware.Routing is connected to the middleware pipeline by the RouterMiddleware class. ASP.NET Core MVC добавляет функцию маршрутизации в конвейер ПО промежуточного слоя в процессе настройки и обрабатывает маршрутизацию в приложениях MVC и Razor Pages.ASP.NET Core MVC adds routing to the middleware pipeline as part of its configuration and handles routing in MVC and Razor Pages apps. Сведения об использовании маршрутизации в виде отдельного компонента см. в руководстве по использованию ПО промежуточного слоя маршрутизации.To learn how to use routing as a standalone component, see the Use Routing Middleware section.

Соответствие URL-адресовURL matching

Сопоставление URL-адресов — это процесс, с помощью которого функция маршрутизации отправляет входящий запрос в конечную точку.URL matching is the process by which routing dispatches an incoming request to an endpoint. Этот процесс основывается на данных в пути URL-адреса, но может быть расширен для учета любых данных в запросе.This process is based on data in the URL path but can be extended to consider any data in the request. Возможность отправки запросов в отдельные обработчики имеет первостепенное значение для масштабирования размера и сложности приложения.The ability to dispatch requests to separate handlers is key to scaling the size and complexity of an app.

При выполнении ПО промежуточного слоя маршрутизации оно задает конечную точку (Endpoint) и значения маршрута для компонента в HttpContext.When a Routing Middleware executes, it sets an endpoint (Endpoint) and route values to a feature on the HttpContext. Для текущего запроса:For the current request:

  • Вызов к HttpContext.GetEndpoint возвращает конечную точку.Calling HttpContext.GetEndpoint gets the endpoint.
  • HttpRequest.RouteValues получает коллекцию значений маршрута.HttpRequest.RouteValues gets the collection of route values.

ПО промежуточного слоя, которое выполняется после ПО промежуточного слоя маршрутизации, может видеть конечную точку и выполнять действия.Middleware running after the Routing Middleware can see the endpoint and take action. Например, ПО промежуточного слоя авторизации может запросить политику авторизации у коллекции метаданных конечной точки.For example, an Authorization Middleware can interrogate the endpoint's metadata collection for an authorization policy. После выполнения всех экземпляров ПО промежуточного слоя в конвейере обработки запросов вызывается делегат выбранной конечной точки.After all of the middleware in the request processing pipeline is executed, the selected endpoint's delegate is invoked.

Система маршрутизации в маршрутизации по конечным точкам принимает все решения об отправке.The routing system in endpoint routing is responsible for all dispatching decisions. Так как ПО промежуточного слоя применяет политики в зависимости от выбранной конечной точки, очень важно, чтобы любое решение, которое может повлиять на отправку или применение политик безопасности, принималось внутри системы маршрутизации.Since the middleware applies policies based on the selected endpoint, it's important that any decision that can affect dispatching or the application of security policies is made inside the routing system.

Когда делегат конечной точки выполняется, свойствам RouteContext.RouteData присваиваются значения с учетом уже выполненной на текущий момент обработки.When the endpoint delegate is executed, the properties of RouteContext.RouteData are set to appropriate values based on the request processing performed thus far.

RouteData.Values — это словарь значений маршрута, полученных из маршрута.RouteData.Values is a dictionary of route values produced from the route. Как правило, эти значения определяются путем разбивки URL-адреса на сегменты и могут использоваться для принятия входных данных пользователя или принятия дальнейших решений об отправке в приложении.These values are usually determined by tokenizing the URL and can be used to accept user input or to make further dispatching decisions inside the app.

RouteData.DataTokens — это контейнер свойств с дополнительными данными, связанными с соответствующим маршрутом.RouteData.DataTokens is a property bag of additional data related to the matched route. Свойства DataTokens обеспечивают связывание данных состояния с каждым маршрутом, что позволяет приложению принимать решения в зависимости от соответствующего маршрута.DataTokens are provided to support associating state data with each route so that the app can make decisions based on which route matched. Эти значения определяются разработчиком и никоим образом не влияют на поведение маршрутизации.These values are developer-defined and do not affect the behavior of routing in any way. Кроме того, значения, спрятанные в токенах RouteData.DataToken, могут быть любого типа в отличие от значений RouteData.Value, которые должны легко преобразовываться в строки и из строк.Additionally, values stashed in RouteData.DataTokens can be of any type, in contrast to RouteData.Values, which must be convertible to and from strings.

RouteData.Routers — это список маршрутов, которые участвовали в успешном сопоставлении с запросом.RouteData.Routers is a list of the routes that took part in successfully matching the request. Маршруты могут быть вложены друг в друга.Routes can be nested inside of one another. Свойство Routers отражает путь по логическому дереву маршрутов, который привел к совпадению.The Routers property reflects the path through the logical tree of routes that resulted in a match. Как правило, первый элемент в свойстве Routers — это коллекция маршрутов, используемая для формирования URL-адресов.Generally, the first item in Routers is the route collection and should be used for URL generation. Последний элемент в свойстве Routers — это соответствующий обработчик маршрутов.The last item in Routers is the route handler that matched.

Создание URL-адреса с помощью LinkGeneratorURL generation with LinkGenerator

Формирование URL-адреса — это процесс создания пути URL-адреса функцией маршрутизации на основе набора значений маршрута.URL generation is the process by which routing can create a URL path based on a set of route values. Он обеспечивает логическое разделение конечных точек и URL-адресов, по которым к ним осуществляется доступ.This allows for a logical separation between your endpoints and the URLs that access them.

Маршрутизация по конечным точкам включает в себя API генератора ссылок (LinkGenerator).Endpoint routing includes the Link Generator API (LinkGenerator). LinkGenerator — это отдельная служба, которую можно получить посредством внедрения зависимостей.LinkGenerator is a singleton service that can be retrieved from DI. API можно использовать вне контекста выполнения запроса.The API can be used outside of the context of an executing request. IUrlHelper MVC и сценарии, которые зависят от IUrlHelper, такие как вспомогательные функции тегов, вспомогательные методы HTML и результаты действий, используют генератор ссылок для предоставления возможностей создания ссылок.MVC's IUrlHelper and scenarios that rely on IUrlHelper, such as Tag Helpers, HTML Helpers, and Action Results, use the link generator to provide link generating capabilities.

Генератор ссылок использует концепции адреса и схем адресов.The link generator is backed by the concept of an address and address schemes. Схема адресов — это способ определения конечных точек, которые должны рассматриваться для создания ссылки.An address scheme is a way of determining the endpoints that should be considered for link generation. Например, сценарии с именем маршрута и значениями маршрута, с которыми многие пользователи знакомы по MVC и Razor Pages, реализуются как схема адресов.For example, the route name and route values scenarios many users are familiar with from MVC/Razor Pages are implemented as an address scheme.

Генератор ссылок может установить связь с действиями и страницами MVC и Razor Pages с помощью следующих методов расширения:The link generator can link to MVC/Razor Pages actions and pages via the following extension methods:

Перегрузка этих методов принимает аргументы, которые включают HttpContext.An overload of these methods accepts arguments that include the HttpContext. Эти методы являются функциональными эквивалентами Url.Action и Url.Page, но предлагают дополнительную гибкость и параметры.These methods are functionally equivalent to Url.Action and Url.Page but offer additional flexibility and options.

Методы GetPath* наиболее схожи с Url.Action и Url.Page в том, что создают URI, содержащий абсолютный путь.The GetPath* methods are most similar to Url.Action and Url.Page in that they generate a URI containing an absolute path. Методы GetUri* всегда создают абсолютный URI, содержащий схему и узел.The GetUri* methods always generate an absolute URI containing a scheme and host. Методы, которые принимают HttpContext, создают URI в контексте выполнения запроса.The methods that accept an HttpContext generate a URI in the context of the executing request. Используются значения окружения маршрута, базовый URL-адрес, схема и узел из выполняющегося запроса, если не указано иное.The ambient route values, URL base path, scheme, and host from the executing request are used unless overridden.

LinkGenerator вызывается с адресом.LinkGenerator is called with an address. Создание URI происходит в два этапа:Generating a URI occurs in two steps:

  1. Адрес привязан к списку конечных точек, соответствующих адресу.An address is bound to a list of endpoints that match the address.
  2. RoutePattern конечной точки вычисляется, пока не будет найден шаблон маршрута, который соответствует предоставленным значениям.Each endpoint's RoutePattern is evaluated until a route pattern that matches the supplied values is found. Полученный результат объединяется с другими частями URI, предоставленными генератору ссылок и возвращенными.The resulting output is combined with the other URI parts supplied to the link generator and returned.

Методы, предоставляемые LinkGenerator, поддерживают стандартные возможности создания ссылки для любого типа адреса.The methods provided by LinkGenerator support standard link generation capabilities for any type of address. Самый удобный способ использовать генератор ссылки — через методы расширения, которые выполняют операции для определенного типа адреса.The most convenient way to use the link generator is through extension methods that perform operations for a specific address type.

Метод расширенияExtension Method ОписаниеDescription
GetPathByAddress Создает URI с абсолютным путем на основе предоставленных значений.Generates a URI with an absolute path based on the provided values.
GetUriByAddress Создает абсолютный URI на основе предоставленных значений.Generates an absolute URI based on the provided values.

Предупреждение

Обратите внимание на следующие последствия вызова методов LinkGenerator:Pay attention to the following implications of calling LinkGenerator methods:

  • Используйте методы расширения GetUri* с осторожностью в конфигурации приложения, которая не проверяет заголовок входящих запросов Host.Use GetUri* extension methods with caution in an app configuration that doesn't validate the Host header of incoming requests. Если не проверить заголовок входящих запросов Host, входные данные в запросе без доверия могут отправляться обратно клиенту в URI в представлении или странице.If the Host header of incoming requests isn't validated, untrusted request input can be sent back to the client in URIs in a view/page. Рекомендуется, чтобы все рабочие приложения настраивали свой сервер на проверку заголовка Host относительно известных допустимых значений.We recommend that all production apps configure their server to validate the Host header against known valid values.

  • Используйте LinkGenerator с осторожностью в ПО промежуточного слоя в сочетании с Map или MapWhen.Use LinkGenerator with caution in middleware in combination with Map or MapWhen. Map* изменяет базовый путь выполняющегося запроса, что влияет на выходные данные создания ссылки.Map* changes the base path of the executing request, which affects the output of link generation. Все API LinkGenerator разрешают указание базового пути.All of the LinkGenerator APIs allow specifying a base path. Всегда указывайте пустой базовый путь для отмены влияния Map* на создание ссылок.Always specify an empty base path to undo Map*'s affect on link generation.

Маршрутизация конечных точекEndpoint routing

  • Конечная точка маршрута содержит шаблон, метаданные и делегат запроса, который обслуживает ответ конечной точки.A route endpoint has a template, metadata, and a request delegate that serves the endpoint's response. Метаданные используются для реализации сквозной функциональности на основе политик и конфигурации каждой конечной точки.The metadata is used to implement cross-cutting concerns based on policies and configuration attached to each endpoint. Например, ПО промежуточного слоя авторизации может запросить политику авторизации у коллекции метаданных конечной точки.For example, an authorization middleware can interrogate the endpoint's metadata collection for an authorization policy.
  • Маршрутизация конечной точки интегрируется с ПО промежуточного слоя с использованием двух приведенных ниже методов расширения.Endpoint routing integrates with middleware using two extension methods:
    • UseRouting добавляет соответствие маршрута в конвейер ПО промежуточного слоя.UseRouting adds route matching to the middleware pipeline. Он должен быть указан перед любым ПО промежуточного слоя, учитывающим маршрут, таким как авторизация, выполнение конечной точки и т. д.It must come before any route-aware middleware such as authorization, endpoint execution, etc.
    • UseEndpoints добавляет выполнение конечной точки в конвейер ПО промежуточного слоя.UseEndpoints adds endpoint execution to the middleware pipeline. Он запускает делегат запроса, который обслуживает ответ конечной точки.It runs the request delegate that serves the endpoint's response. В UseEndpoints также настраиваются конечные точки маршрута, которые могут быть сопоставлены и выполнены приложением.UseEndpoints is also where route endpoints are configured that can be matched and executed by the app. Например, MapRazorPages, MapControllers, MapGet и MapPost.For example, MapRazorPages, MapControllers, MapGet, and MapPost.
  • Приложения используют вспомогательные методы ASP.NET Core для настройки маршрутов.Apps use ASP.NET Core's helper methods to configure their routes. Платформы ASP.NET Core предоставляют такие вспомогательные методы, как MapRazorPages, MapControllers и MapHub<THub>.ASP.NET Core frameworks provide helper methods like MapRazorPages,, MapControllers and MapHub<THub>. Существуют также вспомогательные методы для настройки собственных конечных точек маршрута: MapGet, MapPost и MapVerb.There are also helper methods for configuring your own custom route endpoints: MapGet, MapPost, and MapVerb.
  • Маршрутизация конечных точек также поддерживает изменения в конечных точках после запуска приложения.Endpoint routing also supports endpoints changing after an application has started up. Для этого в приложении или платформе ASP.NET Core необходимо создать и зарегистрировать пользовательскую функцию EndpointDataSource.To support this in your app or ASP.NET Core framework, a custom EndpointDataSource must be created and registered. Это дополнительная функция, которая обычно не нужна.This is an advanced feature, and usually not needed. Конечные точки обычно настраиваются при запуске и являются фиксированными в течение всего срока жизни службы приложения.Endpoints are typically configured at startup and are static for the lifetime of the app. Загрузка конфигурации маршрута из файла или базы данных при запуске не является динамической.Loading route configuration from a file or database at startup is not dynamic.

В следующем коде приведен базовый пример маршрутизации конечной точки:The following code shows a basic example of endpoint routing:

public void Configure(IApplicationBuilder app)
{
    // Matches request to an endpoint.
    app.UseRouting();

    // Endpoint aware middleware. 
    // Middleware can use metadata from the matched endpoint.
    app.UseAuthorization();

    // Execute the matched endpoint.
    app.UseEndpoints(endpoints =>
    {
        // Configuration of app endpoints.
        endpoints.MapRazorPages();
        endpoints.MapGet("/", context => context.Response.WriteAsync("Hello world"));
        endpoints.MapHealthChecks("/healthz");
    });
}

Дополнительные сведения см. в разделе Соответствие URL-адресов.See URL matching in this document for more information on endpoint routing.

Отличия маршрутизации конечных точек от более ранних версий маршрутизацииEndpoint routing differences from earlier versions of routing

Существует несколько различий между маршрутизацией по конечным точкам и более ранними версиями маршрутизации, чем в ASP.NET Core 2.2:A few differences exist between endpoint routing and versions of routing earlier than in ASP.NET Core 2.2:

  • Система маршрутизации по конечным точкам не поддерживает расширяемость на основе IRouter, включая наследование от Route.The endpoint routing system doesn't support IRouter-based extensibility, including inheriting from Route.

  • Маршрутизация по конечным точкам не поддерживает WebApiCompatShim.Endpoint routing doesn't support WebApiCompatShim. Используйте совместимую версию 2.1 (.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)), чтобы продолжить использование оболочек совместимости.Use the 2.1 compatibility version (.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)) to continue using the compatibility shim.

  • Маршрутизация по конечным точкам иначе обрабатывает регистр созданных URI при использовании стандартных маршрутов.Endpoint Routing has different behavior for the casing of generated URIs when using conventional routes.

    Рассмотрим следующий шаблон маршрута по умолчанию:Consider the following default route template:

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

    Предположим, вы создаете ссылку на действие с помощью следующего маршрута:Suppose you generate a link to an action using the following route:

    var link = Url.Action("ReadPost", "blog", new { id = 17, });
    

    С помощью маршрутизации на основе IRouter этот код создает URI из /blog/ReadPost/17, который учитывает регистр предоставленного значения маршрута.With IRouter-based routing, this code generates a URI of /blog/ReadPost/17, which respects the casing of the provided route value. Маршрутизация по конечным точкам в ASP.NET Core 2.2 или более поздней версии создает /Blog/ReadPost/17 ("Blog" — с прописной буквы).Endpoint routing in ASP.NET Core 2.2 or later produces /Blog/ReadPost/17 ("Blog" is capitalized). Маршрутизация по конечным точкам предоставляет интерфейс IOutboundParameterTransformer, который можно использовать для настройки этого поведения на глобальном уровне или применения других соглашения для сопоставления URL-адресов.Endpoint routing provides the IOutboundParameterTransformer interface that can be used to customize this behavior globally or to apply different conventions for mapping URLs.

    Дополнительные сведения см. в разделе Справочник по преобразователям параметров.For more information, see the Parameter transformer reference section.

  • Создание ссылок, используемых MVC и Razor Pages со стандартными маршрутами, работает иначе при попытке сослаться на контроллер/действие или страницу, которые не существуют.Link Generation used by MVC/Razor Pages with conventional routes behaves differently when attempting to link to an controller/action or page that doesn't exist.

    Рассмотрим следующий шаблон маршрута по умолчанию:Consider the following default route template:

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

    Предположим, вы создаете ссылку на действие с помощью шаблона по умолчанию:Suppose you generate a link to an action using the default template with the following:

    var link = Url.Action("ReadPost", "Blog", new { id = 17, });
    

    С маршрутизацией на основе IRouter результатом всегда будет /Blog/ReadPost/17, даже если BlogController не существует или не имеет метода действия ReadPost.With IRouter-based routing, the result is always /Blog/ReadPost/17, even if the BlogController doesn't exist or doesn't have a ReadPost action method. Как и ожидалось, маршрутизация по конечным точкам в ASP.NET Core 2.2 или более поздней версии создает /Blog/ReadPost/17, если метод действия существует.As expected, endpoint routing in ASP.NET Core 2.2 or later produces /Blog/ReadPost/17 if the action method exists. Но маршрутизация по конечным точкам создает пустую строку, если действие не существует.However, endpoint routing produces an empty string if the action doesn't exist. По существу, маршрутизация по конечным точкам не предполагает, что конечная точка существует, если действие не существует.Conceptually, endpoint routing doesn't assume that the endpoint exists if the action doesn't exist.

  • Алгоритм отмены значения окружения при создании ссылок работает иначе при маршрутизации по конечным точкам.The link generation ambient value invalidation algorithm behaves differently when used with endpoint routing.

    Отмена значения окружения — это алгоритм, который решает, какие значения маршрута из текущего выполняемого запроса (значения окружения) могут использоваться в операции создания ссылки.Ambient value invalidation is the algorithm that decides which route values from the currently executing request (the ambient values) can be used in link generation operations. Стандартная маршрутизация всегда отменяет лишние значения маршрута при привязке к другому действию.Conventional routing always invalidated extra route values when linking to a different action. Маршрутизация с помощью атрибутов работала иначе до выпуска ASP.NET Core 2.2.Attribute routing didn't have this behavior prior to the release of ASP.NET Core 2.2. В более ранних версиях ASP.NET Core ссылки на другое действие, которые используют те же имена параметров маршрута, приводили к ошибкам создания ссылки.In earlier versions of ASP.NET Core, links to another action that use the same route parameter names resulted in link generation errors. В ASP.NET Core 2.2 или более поздней версии обе формы маршрутизации отменяют значения при привязке к другому действию.In ASP.NET Core 2.2 or later, both forms of routing invalidate values when linking to another action.

    Рассмотрим следующий пример в ASP.NET Core 2.1 или более ранней версии.Consider the following example in ASP.NET Core 2.1 or earlier. При привязке к другому действию (или странице) значения маршрута могут использоваться повторно нежелательным образом.When linking to another action (or another page), route values can be reused in undesirable ways.

    В /Pages/Store/Product.cshtml:In /Pages/Store/Product.cshtml:

    @page "{id}"
    @Url.Page("/Login")
    

    В /Pages/Login.cshtml:In /Pages/Login.cshtml:

    @page "{id?}"
    

    Если URI — /Store/Product/18 в ASP.NET Core 2.1 или более ранней версии, ссылка, созданная на странице Store/Info с помощью @Url.Page("/Login") — /Login/18.If the URI is /Store/Product/18 in ASP.NET Core 2.1 or earlier, the link generated on the Store/Info page by @Url.Page("/Login") is /Login/18. Значение id 18 используется повторно, хотя конечный объект ссылки является совсем другой частью приложения.The id value of 18 is reused, even though the link destination is different part of the app entirely. Значение маршрута id в контексте страницы /Login, вероятно, является значением идентификатора пользователя, а не кодом хранимого продукта.The id route value in the context of the /Login page is probably a user ID value, not a store product ID value.

    При маршрутизации по конечным точкам в ASP.NET Core 2.2 или более поздней версии результатом является /Login.In endpoint routing with ASP.NET Core 2.2 or later, the result is /Login. Значения окружения не используются повторно, если конечный объект ссылки является другим действием или страницей.Ambient values aren't reused when the linked destination is a different action or page.

  • Синтаксис параметра кругового маршрута: символы прямой косой черты не кодируются при использовании синтаксиса универсального параметра с двумя звездочками (**).Round-tripping route parameter syntax: Forward slashes aren't encoded when using a double-asterisk (**) catch-all parameter syntax.

    Во время создания ссылки система маршрутизации кодирует значение, записанное в универсальном параметре с двумя звездочками (**) (например, {**myparametername}), за исключением прямой косой черты.During link generation, the routing system encodes the value captured in a double-asterisk (**) catch-all parameter (for example, {**myparametername}) except the forward slashes. Универсальный параметр с двумя звездочками поддерживается в маршрутизации на основе IRouter в ASP.NET Core 2.2 или более поздней версии.The double-asterisk catch-all is supported with IRouter-based routing in ASP.NET Core 2.2 or later.

    Синтаксис универсального параметра с одной звездочкой в предыдущих версиях ASP.NET Core ({*myparametername}) поддерживается, и прямая косая черта кодируется.The single asterisk catch-all parameter syntax in prior versions of ASP.NET Core ({*myparametername}) remains supported, and forward slashes are encoded.

    МаршрутRoute Ссылка, созданная с помощьюLink generated with
    Url.Action(new { category = "admin/products" })
    /search/{*page} /search/admin%2Fproducts (прямая косая черта кодируется)/search/admin%2Fproducts (the forward slash is encoded)
    /search/{**page} /search/admin/products

Пример ПО промежуточного слояMiddleware example

В следующем примере ПО промежуточного слоя использует API LinkGenerator, чтобы создать ссылку на метод действия, который перечисляет хранимые продукты.In the following example, a middleware uses the LinkGenerator API to create link to an action method that lists store products. Использование генератора ссылок путем его внедрения в класс и вызова GenerateLink доступно для любого класса в приложении.Using the link generator by injecting it into a class and calling GenerateLink is available to any class in an app.

using Microsoft.AspNetCore.Routing;

public class ProductsLinkMiddleware
{
    private readonly LinkGenerator _linkGenerator;

    public ProductsLinkMiddleware(RequestDelegate next, LinkGenerator linkGenerator)
    {
        _linkGenerator = linkGenerator;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        var url = _linkGenerator.GetPathByAction("ListProducts", "Store");

        httpContext.Response.ContentType = "text/plain";

        await httpContext.Response.WriteAsync($"Go to {url} to see our products.");
    }
}

Создание маршрутовCreate routes

Большинство приложений создают маршруты, вызывая метод MapRoute или один из аналогичных методов расширения, определенных в интерфейсе IRouteBuilder.Most apps create routes by calling MapRoute or one of the similar extension methods defined on IRouteBuilder. Все методы расширения IRouteBuilder создают экземпляр Route и добавляют его в коллекцию маршрутов.Any of the IRouteBuilder extension methods create an instance of Route and add it to the route collection.

MapRoute не принимает параметр обработчика маршрутов.MapRoute doesn't accept a route handler parameter. MapRoute только добавляет маршруты, которые обрабатываются DefaultHandler.MapRoute only adds routes that are handled by the DefaultHandler. Дополнительные сведения о маршрутизации в MVC см. в разделе Маршрутизация к действиям контроллера в ASP.NET Core.To learn more about routing in MVC, see Маршрутизация к действиям контроллера в ASP.NET Core.

В следующем коде приводится пример вызова MapRoute, используемого в типичном определении маршрута ASP.NET Core MVC:The following code example is an example of a MapRoute call used by a typical ASP.NET Core MVC route definition:

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

Этот шаблон соответствует пути URL-адреса и извлекает значения маршрута.This template matches a URL path and extracts the route values. Например, путь /Products/Details/17 создает следующие значения маршрута: { controller = Products, action = Details, id = 17 }.For example, the path /Products/Details/17 generates the following route values: { controller = Products, action = Details, id = 17 }.

Значения маршрута определяются с помощью разделения пути URL-адреса на сегменты и сопоставления каждого сегмента с именем параметра маршрута в шаблоне маршрута.Route values are determined by splitting the URL path into segments and matching each segment with the route parameter name in the route template. Параметры маршрута являются именованными.Route parameters are named. Параметры определяются путем заключения имени параметра в фигурные скобки { ... }.The parameters defined by enclosing the parameter name in braces { ... }.

Приведенный выше шаблон может также соответствовать пути URL-адреса /. В этом случае он предоставляет значения { controller = Home, action = Index }.The preceding template could also match the URL path / and produce the values { controller = Home, action = Index }. Связано это с тем, что параметры маршрута {controller} и {action} имеют значения по умолчанию, а параметр маршрута id является необязательным.This occurs because the {controller} and {action} route parameters have default values and the id route parameter is optional. Значение по умолчанию для параметра маршрута определяется с помощью знака равенства (=), за которым следует значение после имени параметра.An equals sign (=) followed by a value after the route parameter name defines a default value for the parameter. Вопросительный знак (?) после имени параметра маршрута определяет параметр как необязательный.A question mark (?) after the route parameter name defines an optional parameter.

Параметры маршрута со значением по умолчанию всегда предоставляют значения маршрута при совпадении маршрута.Route parameters with a default value always produce a route value when the route matches. Необязательные параметры не предоставляют значение маршрута, если нет соответствующего сегмента пути URL-адреса.Optional parameters don't produce a route value if there was no corresponding URL path segment. Подробное описание сценариев и синтаксиса шаблона маршрута см. в разделе Справочник по шаблонам маршрутов.See the Route template reference section for a thorough description of route template scenarios and syntax.

В следующем примере в определении параметра маршрута {id:int} определяется ограничение маршрута для параметра маршрута id:In the following example, the route parameter definition {id:int} defines a route constraint for the id route parameter:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id:int}");

Этот шаблон соответствует такому пути URL-адреса, как /Products/Details/17, но не /Products/Details/Apples.This template matches a URL path like /Products/Details/17 but not /Products/Details/Apples. Ограничения маршрута реализуют интерфейс IRouteConstraint и проверяют значения маршрута.Route constraints implement IRouteConstraint and inspect route values to verify them. В этом примере значение маршрута id должно иметь возможность преобразования в целое число.In this example, the route value id must be convertible to an integer. Более подробное описание ограничений маршрутов, предоставляемых платформой, см. в разделе Справочник по ограничениям маршрутов.See route-constraint-reference for an explanation of route constraints provided by the framework.

Дополнительные перегрузки MapRoute принимают значения для параметров constraints, dataTokens и defaults.Additional overloads of MapRoute accept values for constraints, dataTokens, and defaults. Типичное применение этих параметров состоит в передаче анонимно типизированного объекта, причем имена свойств анонимного типа соответствуют именам параметров маршрута.The typical usage of these parameters is to pass an anonymously typed object, where the property names of the anonymous type match route parameter names.

В следующих примерах MapRoute создаются эквивалентные маршруты:The following MapRoute examples create equivalent routes:

routes.MapRoute(
    name: "default_route",
    template: "{controller}/{action}/{id?}",
    defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
    name: "default_route",
    template: "{controller=Home}/{action=Index}/{id?}");

Совет

Встроенный синтаксис определения ограничений и значений по умолчанию может быть удобнее для простых маршрутов.The inline syntax for defining constraints and defaults can be convenient for simple routes. Однако некоторые сценарии, например токены данных, не поддерживаются встроенным синтаксисом.However, there are scenarios, such as data tokens, that aren't supported by inline syntax.

В следующем примере показано еще несколько сценариев:The following example demonstrates a few additional scenarios:

routes.MapRoute(
    name: "blog",
    template: "Blog/{**article}",
    defaults: new { controller = "Blog", action = "ReadArticle" });

Предыдущий шаблон соответствует такому пути URL-адреса, как /Blog/All-About-Routing/Introduction, и извлекает значения { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }.The preceding template matches a URL path like /Blog/All-About-Routing/Introduction and extracts the values { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }. Значения маршрута по умолчанию для controller и action предоставляются маршрутом несмотря на то, что в шаблоне нет соответствующих параметров маршрута.The default route values for controller and action are produced by the route even though there are no corresponding route parameters in the template. Значения по умолчанию можно указать в шаблоне маршрута.Default values can be specified in the route template. Параметр маршрута article определяется как универсальный с помощью двух звездочек (**) перед именем.The article route parameter is defined as a catch-all by the appearance of an double asterisk (**) before the route parameter name. Универсальные параметры маршрута служат для фиксации оставшейся части пути URL-адреса, а также могут соответствовать пустой строке.Catch-all route parameters capture the remainder of the URL path and can also match the empty string.

В следующем примере добавляются ограничения маршрута и токены данных:The following example adds route constraints and data tokens:

routes.MapRoute(
    name: "us_english_products",
    template: "en-US/Products/{id}",
    defaults: new { controller = "Products", action = "Details" },
    constraints: new { id = new IntRouteConstraint() },
    dataTokens: new { locale = "en-US" });

Предыдущий шаблон будет соответствовать такому пути URL-адреса, как /en-US/Products/5, и будет извлекать значения { controller = Products, action = Details, id = 5 } и токены данных { locale = en-US }.The preceding template matches a URL path like /en-US/Products/5 and extracts the values { controller = Products, action = Details, id = 5 } and the data tokens { locale = en-US }.

Токены в окне "Локальные"

Формирование URL-адреса класса маршрутаRoute class URL generation

Класс Route может также формировать URL-адрес, объединяя набор значений маршрута с шаблоном маршрута.The Route class can also perform URL generation by combining a set of route values with its route template. С логической точки зрения, этот процесс обратен сопоставлению пути URL-адреса.This is logically the reverse process of matching the URL path.

Совет

Чтобы лучше понять процесс формирования URL-адреса, представьте себе, какой URL-адрес нужно создать, а затем подумайте, как шаблон маршрута будет сопоставляться с этим URL-адресом.To better understand URL generation, imagine what URL you want to generate and then think about how a route template would match that URL. Какие значения будут получены?What values would be produced? Примерно так производится формирование URL-адреса в классе Route.This is the rough equivalent of how URL generation works in the Route class.

В следующем примере используется общий маршрут по умолчанию ASP.NET Core MVC:The following example uses a general ASP.NET Core MVC default route:

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

При значениях маршрута { controller = Products, action = List } создается URL-адрес /Products/List.With the route values { controller = Products, action = List }, the URL /Products/List is generated. Значения маршрута заменяются на соответствующие параметры маршрута для образования пути URL-адреса.The route values are substituted for the corresponding route parameters to form the URL path. Так как id является необязательным параметром маршрута, URL-адрес успешно создается без значения для id.Since id is an optional route parameter, the URL is successfully generated without a value for id.

При значениях маршрута { controller = Home, action = Index } создается URL-адрес /.With the route values { controller = Home, action = Index }, the URL / is generated. Предоставленные значения маршрута соответствуют значениям по умолчанию, поэтому сегменты, соответствующие значениям по умолчанию, можно спокойно опустить.The provided route values match the default values, and the segments corresponding to the default values are safely omitted.

Оба созданных URL-адреса будут совершать круговой путь с таким же определением маршрута (/Home/Index и /) и предоставлять те же значения маршрута, которые использовались для формирования URL-адреса.Both URLs generated round-trip with the following route definition (/Home/Index and /) produce the same route values that were used to generate the URL.

Примечание

Приложение, использующее платформу ASP.NET Core MVC, должно создавать URL-адреса с помощью объекта UrlHelper, а не вызывать маршрутизацию напрямую.An app using ASP.NET Core MVC should use UrlHelper to generate URLs instead of calling into routing directly.

Дополнительные сведения о формировании URL-адресов см. в справочнике по формированию URL-адресов.For more information on URL generation, see the Url generation reference section.

Использование ПО промежуточного слоя маршрутизацииUse Routing Middleware

Ссылка на метапакет Microsoft.AspNetCore.App в файле проекта приложения.Reference the Microsoft.AspNetCore.App metapackage in the app's project file.

Добавьте маршрутизацию в контейнер службы в файле Startup.ConfigureServices:Add routing to the service container in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRouting();
}

Маршруты должны настраиваться в методе Startup.Configure.Routes must be configured in the Startup.Configure method. В этом примере приложения используются следующие API:The sample app uses the following APIs:

var trackPackageRouteHandler = new RouteHandler(context =>
{
    var routeValues = context.GetRouteData().Values;
    return context.Response.WriteAsync(
        $"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
    "Track Package Route",
    "package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>
{
    var name = context.GetRouteValue("name");
    // The route handler when HTTP GET "hello/<anything>" matches
    // To match HTTP GET "hello/<anything>/<anything>, 
    // use routeBuilder.MapGet("hello/{*name}"
    return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();
app.UseRouter(routes);

В таблице ниже приведены ответы с данными универсальными кодами ресурсов (URI).The following table shows the responses with the given URIs.

URIURI ОтветResponse
/package/create/3 Hello!Hello! Значения маршрута: [operation, create], [id, 3]Route values: [operation, create], [id, 3]
/package/track/-3 Hello!Hello! Значения маршрута: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/-3/ Hello!Hello! Значения маршрута: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/ Запрос не дал результата, нет совпадений.The request falls through, no match.
GET /hello/Joe Hi, Joe!Hi, Joe!
POST /hello/Joe Запрос не дал результата, совпадение только с HTTP GET.The request falls through, matches HTTP GET only.
GET /hello/Joe/Smith Запрос не дал результата, нет совпадений.The request falls through, no match.

Платформа предоставляет наборов методов расширения для создания маршрутов (RequestDelegateRouteBuilderExtensions):The framework provides a set of extension methods for creating routes (RequestDelegateRouteBuilderExtensions):

Методы Map[Verb] используют ограничения, чтобы ограничить маршрут к HTTP-команде в имени метода.The Map[Verb] methods use constraints to limit the route to the HTTP Verb in the method name. Например, см. класс MapGet и тип MapVerb.For example, see MapGet and MapVerb.

Справочник по шаблону маршрутаRoute template reference

Токены в фигурных скобках ({ ... }) определяют параметры маршрута, которые будут привязаны при совпадении маршрута.Tokens within curly braces ({ ... }) define route parameters that are bound if the route is matched. В сегменте маршрута можно определить несколько параметров маршрута, но они должны разделяться литеральным значением.You can define more than one route parameter in a route segment, but they must be separated by a literal value. Например, {controller=Home}{action=Index} будет недопустимым маршрутом, так как между {controller} и {action} нет литерального значения.For example, {controller=Home}{action=Index} isn't a valid route, since there's no literal value between {controller} and {action}. Эти параметры маршрута должны иметь имена, и для них могут быть определены дополнительные атрибуты.These route parameters must have a name and may have additional attributes specified.

Весь текст, кроме параметров маршрута (например, {id}) и разделителя пути /, должен соответствовать тексту в URL-адресе.Literal text other than route parameters (for example, {id}) and the path separator / must match the text in the URL. Сопоставление текста производится без учета регистра на основе декодированного представления путь URL-адреса.Text matching is case-insensitive and based on the decoded representation of the URLs path. Для сопоставления с литеральным разделителем параметров маршрута ({ или }) разделитель следует экранировать путем повтора символа ({{ или }}).To match a literal route parameter delimiter ({ or }), escape the delimiter by repeating the character ({{ or }}).

Шаблоны URL-адресов, которые пытаются получить имя файла с необязательным расширением, имеют свои особенности.URL patterns that attempt to capture a file name with an optional file extension have additional considerations. Например, рассмотрим шаблон files/{filename}.{ext?}.For example, consider the template files/{filename}.{ext?}. Когда значения для filename и ext существуют, заполняются оба значения.When values for both filename and ext exist, both values are populated. Если в URL-адресе есть только значение для filename, маршрут совпадает, так как точка в конце (.) является необязательной.If only a value for filename exists in the URL, the route matches because the trailing period (.) is optional. Следующие URL-адреса соответствуют этому маршруту:The following URLs match this route:

  • /files/myFile.txt
  • /files/myFile

Вы можете использовать звездочку (*) или две звездочки (**) в качестве префикса параметра маршрута для привязки к остальной части URI.You can use an asterisk (*) or double asterisk (**) as a prefix to a route parameter to bind to the rest of the URI. Такие параметры называются универсальными.These are called a catch-all parameters. Например, blog/{**slug} соответствует любому URI, начинающемуся с сегмента /blog, за которым следует любое значение, присваиваемое в качестве значения маршрута slug.For example, blog/{**slug} matches any URI that starts with /blog and has any value following it, which is assigned to the slug route value. Универсальные параметры также могут соответствовать пустой строке.Catch-all parameters can also match the empty string.

Универсальный параметр экранирует соответствующие символы, если маршрут использует для формирования URL-адрес, включая символы разделителей пути (/).The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator (/) characters. Например, маршрут foo/{*path} со значениями маршрутов { path = "my/path" } формирует foo/my%2Fpath.For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Обратите внимание на экранированный знак косой черты.Note the escaped forward slash. В качестве символов разделителя кругового пути используйте префикс параметра маршрута **.To round-trip path separator characters, use the ** route parameter prefix. Маршрут foo/{**path} с { path = "my/path" } формирует foo/my/path.The route foo/{**path} with { path = "my/path" } generates foo/my/path.

Параметры маршрута могут иметь значения по умолчанию. Они указываются после имени параметра и знака равенства (=).Route parameters may have default values designated by specifying the default value after the parameter name separated by an equals sign (=). Например, {controller=Home} определяет Home в качестве значения по умолчанию для controller.For example, {controller=Home} defines Home as the default value for controller. Значение по умолчанию используется, если для параметра нет значения в URL-адресе.The default value is used if no value is present in the URL for the parameter. Параметры маршрута могут быть необязательными (для этого необходимо добавить вопросительный знак (?) в конец имени параметра, например id?).Route parameters are made optional by appending a question mark (?) to the end of the parameter name, as in id?. Различие между необязательными параметрами и параметрами маршрута по умолчанию в том, что вторые всегда имеют значения — необязательный параметр имеет значение, только если оно предоставлено URL-адресом запроса.The difference between optional values and default route parameters is that a route parameter with a default value always produces a value—an optional parameter has a value only when a value is provided by the request URL.

Параметры маршрута могут иметь ограничения, которые должны соответствовать значению маршрута из URL-адреса.Route parameters may have constraints that must match the route value bound from the URL. Добавив двоеточие (:) и имя ограничения после имени параметра маршрута, можно указать встроенные ограничения для параметра маршрута.Adding a colon (:) and constraint name after the route parameter name specifies an inline constraint on a route parameter. Если для ограничения требуются аргументы, они указываются в скобках ((...)) после имени ограничения.If the constraint requires arguments, they're enclosed in parentheses ((...)) after the constraint name. Чтобы указать несколько встроенных ограничений, добавьте еще одно двоеточие (:) и имя ограничения.Multiple inline constraints can be specified by appending another colon (:) and constraint name.

Имя и аргументы ограничения передаются в службу IInlineConstraintResolver для создания экземпляра интерфейса IRouteConstraint, который будет использоваться при обработке URL-адреса.The constraint name and arguments are passed to the IInlineConstraintResolver service to create an instance of IRouteConstraint to use in URL processing. Например, в шаблоне маршрута blog/{article:minlength(10)} определяется ограничение minlength с аргументом 10.For example, the route template blog/{article:minlength(10)} specifies a minlength constraint with the argument 10. Более подробное описание ограничений маршрутов и список ограничений, предоставляемых платформой, см. в разделе Справочник по ограничениям маршрутов.For more information on route constraints and a list of the constraints provided by the framework, see the Route constraint reference section.

Параметры маршрута также могут иметь преобразователи параметров, которые преобразуют значение параметра при создании ссылок и сопоставлении действий и страниц с URL-адресами.Route parameters may also have parameter transformers, which transform a parameter's value when generating links and matching actions and pages to URLs. Как и ограничения, преобразователи параметров можно включать в параметр маршрута, добавив двоеточие (:) и имя преобразователя после имени параметра маршрута.Like constraints, parameter transformers can be added inline to a route parameter by adding a colon (:) and transformer name after the route parameter name. Например, шаблон маршрута blog/{article:slugify} задает преобразователь slugify.For example, the route template blog/{article:slugify} specifies a slugify transformer. Дополнительные сведения о преобразователях параметров см. в разделе Справочник по преобразователям параметров.For more information on parameter transformers, see the Parameter transformer reference section.

В приведенной ниже таблице показаны некоторые примеры шаблонов маршрутов и их поведение.The following table demonstrates example route templates and their behavior.

Шаблон маршрутаRoute Template Пример соответствующего URIExample Matching URI URI запроса…The request URI…
hello /hello Соответствует только одному пути /hello.Only matches the single path /hello.
{Page=Home} / Соответствует и задает для параметра Page значение Home.Matches and sets Page to Home.
{Page=Home} /Contact Соответствует и задает для параметра Page значение Contact.Matches and sets Page to Contact.
{controller}/{action}/{id?} /Products/List Сопоставляется с контроллером Products и действием List.Maps to the Products controller and List action.
{controller}/{action}/{id?} /Products/Details/123 Сопоставляется с контроллером Products и действием Details (id имеет значение 123).Maps to the Products controller and Details action (id set to 123).
{controller=Home}/{action=Index}/{id?} / Сопоставляется с контроллером Home и методом Index (id пропускается).Maps to the Home controller and Index method (id is ignored).

Использование шаблона — это, как правило, самый простой подход к маршрутизации.Using a template is generally the simplest approach to routing. Ограничения и значения по умолчанию также могут указываться вне шаблона маршрута.Constraints and defaults can also be specified outside the route template.

Совет

Чтобы увидеть, как встроенные реализации маршрутизации, такие как Route, сопоставляются с запросами, включите ведение журнала.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Зарезервированные имена маршрутизацииReserved routing names

Следующие ключевые слова являются зарезервированными именами и не могут использоваться как имена маршрутов или параметры:The following keywords are reserved names and can't be used as route names or parameters:

  • action
  • area
  • controller
  • handler
  • page

Справочник по ограничениям маршрутовRoute constraint reference

Ограничения маршрута применяются, когда найдено соответствие входящему URL-адресу и путь URL-адреса был разобран на значения маршрута.Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values. Как правило, ограничения маршрута служат для проверки значения маршрута, связанного посредством шаблона маршрута, и принятия решения касательно того, является ли значение приемлемым (да или нет).Route constraints generally inspect the route value associated via the route template and make a yes/no decision about whether or not the value is acceptable. Некоторые ограничения маршрута используют данные, не относящиеся к значению маршрута, для определения возможности маршрутизации запроса.Some route constraints use data outside the route value to consider whether the request can be routed. Например, HttpMethodRouteConstraint может принимать или отклонять запрос в зависимости от HTTP-команды.For example, the HttpMethodRouteConstraint can accept or reject a request based on its HTTP verb. Ограничения используются в маршрутизации запросов и создании ссылок.Constraints are used in routing requests and link generation.

Предупреждение

Не используйте ограничения для проверки входных данных.Don't use constraints for input validation. Если ограничения используются для проверки входных данных, недопустимые входные данные будут вызывать ошибку 404 (не найдено) вместо ошибки 400 (неверный запрос) с соответствующим сообщением.If constraints are used for input validation, invalid input results in a 404 - Not Found response instead of a 400 - Bad Request with an appropriate error message. Ограничения маршрутов следует использовать для разрешения неоднозначности похожих маршрутов, а не для проверки входных данных определенного маршрута.Route constraints are used to disambiguate similar routes, not to validate the inputs for a particular route.

В приведенной ниже таблице показаны примеры ограничения маршрутов и их ожидаемое поведение.The following table demonstrates example route constraints and their expected behavior.

ограничениеconstraint ПримерExample Примеры совпаденийExample Matches ПримечанияNotes
int {id:int} 123456789, -123456789123456789, -123456789 Соответствует любому целому числуMatches any integer
bool {active:bool} true, FALSEtrue, FALSE Соответствует true или false (без учета регистра)Matches true or false (case-insensitive)
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Соответствует допустимому значению DateTime (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid DateTime value (in the invariant culture - see warning)
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Соответствует допустимому значению decimal (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid decimal value (in the invariant culture - see warning)
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Соответствует допустимому значению double (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid double value (in the invariant culture - see warning)
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Соответствует допустимому значению float (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid float value (in the invariant culture - see warning)
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} Соответствует допустимому значению GuidMatches a valid Guid value
long {ticks:long} 123456789, -123456789123456789, -123456789 Соответствует допустимому значению longMatches a valid long value
minlength(value) {username:minlength(4)} Rick Строка должна содержать не менее 4 символовString must be at least 4 characters
maxlength(value) {filename:maxlength(8)} Richard Строка должна содержать не более 8 символовString must be no more than 8 characters
length(length) {filename:length(12)} somefile.txt Длина строки должна составлять ровно 12 символовString must be exactly 12 characters long
length(min,max) {filename:length(8,16)} somefile.txt Строка должна содержать от 8 до 16 символовString must be at least 8 and no more than 16 characters long
min(value) {age:min(18)} 19 Целочисленное значение не меньше 18Integer value must be at least 18
max(value) {age:max(120)} 91 Целочисленное значение не больше 120Integer value must be no more than 120
range(min,max) {age:range(18,120)} 91 Целочисленное значение от 18 до 120Integer value must be at least 18 but no more than 120
alpha {name:alpha} Rick Строка должна состоять из одной или нескольких букв (a-z, без учета регистра)String must consist of one or more alphabetical characters (a-z, case-insensitive)
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 Строка должна соответствовать регулярному выражению (см. советы по определению регулярного выражения)String must match the regular expression (see tips about defining a regular expression)
required {name:required} Rick Определяет обязательное наличие значения, не относящегося к параметру, во время формирования URL-адресаUsed to enforce that a non-parameter value is present during URL generation

К одному параметру может применяться несколько разделенных запятой ограничений.Multiple, colon-delimited constraints can be applied to a single parameter. Например, следующее ограничение ограничивает параметр целочисленным значением 1 или больше:For example, the following constraint restricts a parameter to an integer value of 1 or greater:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

Предупреждение

Ограничения маршрута, которые проверяют URL-адрес и могут быть преобразованы в тип CLR (например, int или DateTime), всегда используют инвариантные язык и региональные параметры.Route constraints that verify the URL and are converted to a CLR type (such as int or DateTime) always use the invariant culture. Эти ограничения предполагают, что URL-адрес является нелокализуемым.These constraints assume that the URL is non-localizable. Предоставляемые платформой ограничения маршрутов не изменяют значения, хранящиеся в значениях маршрута.The framework-provided route constraints don't modify the values stored in route values. Все значения маршрута, переданные из URL-адреса, сохраняются как строки.All route values parsed from the URL are stored as strings. Например, ограничение float пытается преобразовать значение маршрута в число с плавающей запятой, но преобразованное значение служит только для проверки возможности такого преобразования.For example, the float constraint attempts to convert the route value to a float, but the converted value is used only to verify it can be converted to a float.

Регулярные выраженияRegular expressions

В платформе ASP.NET Core в конструктор регулярных выражений добавляются члены RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant.The ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant to the regular expression constructor. Описание этих членов см. в разделе RegexOptions.See RegexOptions for a description of these members.

В регулярных выражениях применяются разделители и токены, аналогичные используемым функцией маршрутизации и в языке C#.Regular expressions use delimiters and tokens similar to those used by Routing and the C# language. Токены регулярного выражения должны быть экранированы.Regular expression tokens must be escaped. Чтобы использовать регулярное выражение ^\d{3}-\d{2}-\d{4}$ при маршрутизации, выражение должно иметь символы \ (обратная косая черта), представленные в строке в виде символов \\ (двойная обратная косая черта) в исходном файле C#, для экранирования escape-символов строки \ (если не используются буквальные строковые литералы).To use the regular expression ^\d{3}-\d{2}-\d{4}$ in routing, the expression must have the \ (single backslash) characters provided in the string as \\ (double backslash) characters in the C# source file in order to escape the \ string escape character (unless using verbatim string literals). Чтобы экранировать символы разделения параметров маршрутизации ({, }, [, ]), используйте их дважды в выражении ({{, }, [[, ]]).To escape routing parameter delimiter characters ({, }, [, ]), double the characters in the expression ({{, }, [[, ]]). В следующей таблице показаны регулярные выражения и их экранированные варианты.The following table shows a regular expression and the escaped version.

Регулярное выражениеRegular Expression Экранированное регулярное выражениеEscaped Regular Expression
^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$ ^[[a-z]]{{2}}$

Регулярные выражения, используемые при маршрутизации, часто начинаются с символа карета (^) и соответствуют начальной позиции строки.Regular expressions used in routing often start with the caret (^) character and match starting position of the string. Выражения часто заканчиваются знаком доллара ($) и соответствуют концу строки.The expressions often end with the dollar sign ($) character and match end of the string. Благодаря символам ^ и $ регулярное выражение сопоставляется со всем значением параметра маршрута.The ^ and $ characters ensure that the regular expression match the entire route parameter value. Если символы ^ и $ отсутствуют, регулярное выражение сопоставляется с любой подстрокой внутри строки, что обычно нежелательно.Without the ^ and $ characters, the regular expression match any substring within the string, which is often undesirable. В следующей таблице представлен ряд примеров и объясняются причины соответствия или несоответствия.The following table provides examples and explains why they match or fail to match.

ВыражениеExpression СтрокаString СоответствиеMatch Добавление примечанийComment
[a-z]{2} hellohello ДаYes Соответствие подстрокиSubstring matches
[a-z]{2} 123abc456123abc456 ДаYes Соответствие подстрокиSubstring matches
[a-z]{2} mzmz ДаYes Соответствует выражениюMatches expression
[a-z]{2} MZMZ ДаYes Без учета регистраNot case sensitive
^[a-z]{2}$ hellohello НетNo См. замечания, касающиеся символов ^ и $, вышеSee ^ and $ above
^[a-z]{2}$ 123abc456123abc456 НетNo См. замечания, касающиеся символов ^ и $, вышеSee ^ and $ above

Дополнительные сведения о синтаксисе регулярных выражений см. в статье Регулярные выражения в .NET Framework.For more information on regular expression syntax, see .NET Framework Regular Expressions.

Чтобы ограничить возможные значения параметра набором известных значений, используйте регулярное выражение.To constrain a parameter to a known set of possible values, use a regular expression. Например, при использовании выражения {action:regex(^(list|get|create)$)} значение маршрута action будет соответствовать только list, get или create.For example, {action:regex(^(list|get|create)$)} only matches the action route value to list, get, or create. При передаче в словарь ограничений строка ^(list|get|create)$ будет эквивалентной.If passed into the constraints dictionary, the string ^(list|get|create)$ is equivalent. Ограничения, которые передаются в словарь ограничений (то есть не являются встроенными ограничениями шаблона) и не соответствуют одному из известных ограничений, также рассматриваются как регулярные выражения.Constraints that are passed in the constraints dictionary (not inline within a template) that don't match one of the known constraints are also treated as regular expressions.

Пользовательские ограничения маршрутовCustom Route Constraints

Помимо встроенных ограничений маршрутов пользовательские ограничения маршрутов можно создать путем внедрения интерфейса IRouteConstraint.In addition to the built-in route constraints, custom route constraints can be created by implementing the IRouteConstraint interface. Интерфейс IRouteConstraint содержит один метод, Match, который возвращает true, если ограничение удовлетворяется, и false — если нет.The IRouteConstraint interface contains a single method, Match, which returns true if the constraint is satisfied and false otherwise.

Чтобы применить пользовательский метод IRouteConstraint, тип ограничения маршрута необходимо зарегистрировать с помощью ConstraintMap приложения в контейнере службы приложения.To use a custom IRouteConstraint, the route constraint type must be registered with the app's ConstraintMap in the app's service container. Объект ConstraintMap — это словарь, который сопоставляет ключи ограничений пути с реализациями IRouteConstraint, которые проверяют эти ограничения.A ConstraintMap is a dictionary that maps route constraint keys to IRouteConstraint implementations that validate those constraints. ConstraintMap приложения можно преобразовать в Startup.ConfigureServices как часть вызова services.AddRouting или путем настройки RouteOptions непосредственно с помощью services.Configure<RouteOptions>.An app's ConstraintMap can be updated in Startup.ConfigureServices either as part of a services.AddRouting call or by configuring RouteOptions directly with services.Configure<RouteOptions>. Пример:For example:

services.AddRouting(options =>
{
    options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

Ограничения могут применяться к маршрутам обычным способом с использованием имени, указанного при регистрации типа ограничения.The constraint can then be applied to routes in the usual manner, using the name specified when registering the constraint type. Пример:For example:

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

Справочник по преобразователям параметровParameter transformer reference

Преобразователи параметров:Parameter transformers:

  • Выполняются при формировании ссылки для Route.Execute when generating a link for a Route.
  • Реализуйте расширение Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.Implement Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
  • Настраиваются с помощью ConstraintMap.Are configured using ConstraintMap.
  • Принимают значение маршрута параметра и изменяют его на новое строковое значение.Take the parameter's route value and transform it to a new string value.
  • Приводят к использованию преобразованного значения в сформированной ссылке.Result in using the transformed value in the generated link.

Например, пользовательский преобразователь параметра slugify в шаблоне маршрута blog\{article:slugify} с Url.Action(new { article = "MyTestArticle" }) формирует значение blog\my-test-article.For example, a custom slugify parameter transformer in route pattern blog\{article:slugify} with Url.Action(new { article = "MyTestArticle" }) generates blog\my-test-article.

Чтобы использовать преобразователь параметров в шаблоне маршрута, сначала настройте его с помощью ConstraintMap в Startup.ConfigureServices:To use a parameter transformer in a route pattern, configure it first using ConstraintMap in Startup.ConfigureServices:

services.AddRouting(options =>
{
    // Replace the type and the name used to refer to it with your own
    // IOutboundParameterTransformer implementation
    options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

Преобразователи параметров также используются платформами для преобразования URI, где разрешается конечная точка.Parameter transformers are used by the framework to transform the URI where an endpoint resolves. Например, ASP.NET Core MVC с помощью преобразователей параметров преобразует значение маршрута, используемое для сопоставления area, controller, action и page.For example, ASP.NET Core MVC uses parameter transformers to transform the route value used to match an area, controller, action, and page.

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

С помощью предыдущего маршрута действие SubscriptionManagementController.GetAll() сопоставляется с URI /subscription-management/get-all.With the preceding route, the action SubscriptionManagementController.GetAll() is matched with the URI /subscription-management/get-all. Преобразователь параметра не изменяет значения маршрута, используемые для формирования ссылки.A parameter transformer doesn't change the route values used to generate a link. Например, Url.Action("GetAll", "SubscriptionManagement") выводит /subscription-management/get-all.For example, Url.Action("GetAll", "SubscriptionManagement") outputs /subscription-management/get-all.

ASP.NET Core предоставляет соглашения об API для использования преобразователей параметров со сформированными маршрутами:ASP.NET Core provides API conventions for using a parameter transformers with generated routes:

  • ASP.NET Core MVC поддерживает соглашение об API Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention.ASP.NET Core MVC has the Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention API convention. Это соглашение применяет указанный преобразователь параметров ко всем маршрутам атрибутов в приложении.This convention applies a specified parameter transformer to all attribute routes in the app. Преобразователь параметров преобразует маркеры маршрутов атрибутов по мере их замены.The parameter transformer transforms attribute route tokens as they are replaced. Дополнительные сведения см. в разделе об использовании преобразователя параметров для настройки замены маркеров.For more information, see Use a parameter transformer to customize token replacement.
  • Razor Pages поддерживает соглашение об API Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention.Razor Pages has the Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API convention. Это соглашение применяет указанный преобразователь параметров ко всем автоматически обнаруженным страницам Razor Pages.This convention applies a specified parameter transformer to all automatically discovered Razor Pages. Преобразователь параметров преобразует сегменты папок и имен файлов маршрутов Razor Pages.The parameter transformer transforms the folder and file name segments of Razor Pages routes. Дополнительные сведения см. в разделе об использовании преобразователя параметров для настройки маршрутов страниц.For more information, see Use a parameter transformer to customize page routes.

Справочник по формированию URL-адресовURL generation reference

В приведенном ниже примере показано, как создать ссылку на маршрут с использованием словаря значений маршрута и коллекции RouteCollection.The following example shows how to generate a link to a route given a dictionary of route values and a RouteCollection.

app.Run(async (context) =>
{
    var dictionary = new RouteValueDictionary
    {
        { "operation", "create" },
        { "id", 123}
    };

    var vpc = new VirtualPathContext(context, null, dictionary, 
        "Track Package Route");
    var path = routes.GetVirtualPath(vpc).VirtualPath;

    context.Response.ContentType = "text/html";
    await context.Response.WriteAsync("Menu<hr/>");
    await context.Response.WriteAsync(
        $"<a href='{path}'>Create Package 123</a><br/>");
});

В результате приведенного выше примера создается VirtualPath со значением /package/create/123.The VirtualPath generated at the end of the preceding sample is /package/create/123. Словарь предоставляет значения маршрута operation и id шаблона "Отслеживание маршрута пакета", package/{operation}/{id}.The dictionary supplies the operation and id route values of the "Track Package Route" template, package/{operation}/{id}. Дополнительные сведения см. в примере кода в разделе Использование ПО промежуточного слоя маршрутизации или в примере приложения.For details, see the sample code in the Use Routing Middleware section or the sample app.

Второй параметр конструктора VirtualPathContext — это коллекция значений окружения.The second parameter to the VirtualPathContext constructor is a collection of ambient values. Значения окружения упрощают разработку, ограничивая число значений, которые необходимо указывать в определенном контексте запроса.Ambient values are convenient to use because they limit the number of values a developer must specify within a request context. Текущие значения маршрута текущего запроса считаются значениями окружения для создания ссылки.The current route values of the current request are considered ambient values for link generation. В приложении ASP.NET MVC в действии About контроллера HomeController не нужно задавать значение маршрута контроллера, указывающее на действие Index— используется значение окружения Home.In an ASP.NET Core MVC app's About action of the HomeController, you don't need to specify the controller route value to link to the Index action—the ambient value of Home is used.

Значения окружения, которые не соответствуют параметру, игнорируются.Ambient values that don't match a parameter are ignored. Значения окружения также не учитываются, когда явно указанное значение переопределяет значение окружения.Ambient values are also ignored when an explicitly provided value overrides the ambient value. Сопоставление выполняется слева направо в URL-адресе.Matching occurs from left to right in the URL.

Явно предоставленные значения, которые не соответствуют сегменту маршрута, добавляются в строку запроса.Values explicitly provided but that don't match a segment of the route are added to the query string. В приведенной ниже таблице показан результат использования шаблона маршрута {controller}/{action}/{id?}.The following table shows the result when using the route template {controller}/{action}/{id?}.

Значения окруженияAmbient Values Явные значенияExplicit Values РезультатResult
controller = "Home"controller = "Home" action = "About"action = "About" /Home/About
controller = "Home"controller = "Home" controller = "Order", action = "About"controller = "Order", action = "About" /Order/About
controller = "Home", color = "Red"controller = "Home", color = "Red" action = "About"action = "About" /Home/About
controller = "Home"controller = "Home" action = "About", color = "Red"action = "About", color = "Red" /Home/About?color=Red

Если маршрут имеет значение по умолчанию, которое не соответствует параметру, и это значение предоставлено явным образом, оно должно соответствовать значению по умолчанию:If a route has a default value that doesn't correspond to a parameter and that value is explicitly provided, it must match the default value:

routes.MapRoute("blog_route", "blog/{*slug}",
    defaults: new { controller = "Blog", action = "ReadPost" });

Для этого маршрута ссылка будет создана только в том случае, если предоставлены соответствующие значения для controller и action.Link generation only generates a link for this route when the matching values for controller and action are provided.

Сложные сегментыComplex segments

Сложные сегменты (например, [Route("/x{token}y")]) обрабатываются путем "нежадного" сопоставления литералов справа налево.Complex segments (for example [Route("/x{token}y")]) are processed by matching up literals from right to left in a non-greedy way. Подробные сведения о сопоставлении сложных сегментов см. в этом коде.See this code for a detailed explanation of how complex segments are matched. Пример кода не используется в ASP.NET Core, но он предоставляет подробное объяснение сложных сегментов.The code sample is not used by ASP.NET Core, but it provides a good explanation of complex segments.

Настройка метаданных конечной точкиConfiguring endpoint metadata

Сведения о настройке метаданных конечной точки см. на следующих веб-страницах:The following links provide information on configuring endpoint metadata:

Сопоставление узлов в маршрутах с помощью RequireHostHost matching in routes with RequireHost

RequireHost применяет к ограничение маршруту, которому требуется указанный узел.RequireHost applies a constraint to the route which requires the specified host. Параметр RequireHost или [Host] может иметь следующее значение:The RequireHost or [Host] parameter can be:

  • Узел: www.domain.com (соответствует www.domain.com с любым портом)Host: www.domain.com (matches www.domain.com with any port)
  • Узел с подстановочным знаком: *.domain.com (соответствует www.domain.com, subdomain.domain.com или www.subdomain.domain.com для любого порта)Host with wildcard: *.domain.com (matches www.domain.com, subdomain.domain.com, or www.subdomain.domain.com on any port)
  • Порт: *:5000 (соответствует порту 5000 с любым узлом)Port: *:5000 (matches port 5000 with any host)
  • Узел и порт: www.domain.com:5000, *.domain.com:5000 (соответствует узлу и порту)Host and port: www.domain.com:5000, *.domain.com:5000 (matches host and port)

С помощью RequireHost или [Host] можно указать несколько параметров.Multiple parameters can be specified using RequireHost or [Host]. Ограничение будет соответствовать узлам, допустимым для любого из параметров.The constraint will match hosts valid for any of the parameters. Например, [Host("domain.com", "*.domain.com")] будет соответствовать domain.com, www.domain.com или subdomain.domain.com.For example, [Host("domain.com", "*.domain.com")] will match domain.com, www.domain.com, or subdomain.domain.com.

Следующий код использует RequireHost, чтобы запрашивать указанный узел в маршруте:The following code uses RequireHost to require the specified host on the route:

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", context => context.Response.WriteAsync("Hi Contoso!"))
            .RequireHost("contoso.com");
        endpoints.MapGet("/", context => context.Response.WriteAsync("Hi AdventureWorks!"))
            .RequireHost("adventure-works.com");
        endpoints.MapHealthChecks("/healthz").RequireHost("*:8080");
    });
}

Следующий код использует атрибут [Host], чтобы запрашивать указанный узел в контроллере:The following code uses the [Host] attribute to require the specified host on the controller:

[Host("contoso.com", "adventure-works.com")]
public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

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

    [Host("example.com:8080")]
    public IActionResult Privacy()
    {
        return View();
    }

}

Если атрибут [Host] применяется как к контроллеру, так и к методу действия, выполняется следующее.When the [Host] attribute is applied to both the controller and action method:

  • Используется атрибут действия.The attribute on the action is used.
  • Атрибут контроллера не учитывается.The controller attribute is ignored.

Маршрутизация отвечает за сопоставление URI запросов с конечными точками и отправку входящих запросов к этим конечным точкам.Routing is responsible for mapping request URIs to endpoints and dispatching incoming requests to those endpoints. Маршруты определяются в приложении и настраиваются при его запуске.Routes are defined in the app and configured when the app starts. Маршрут может также извлекать значения из содержащегося в запросе URL-адреса, которые затем используются для обработки запроса.A route can optionally extract values from the URL contained in the request, and these values can then be used for request processing. С помощью сведений о маршрутах из приложения маршрутизация также может формировать URL-адреса, которые сопоставляются с конечными точками.Using route information from the app, routing is also able to generate URLs that map to endpoints.

Чтобы использовать новейшие сценарии маршрутизации в ASP.NET Core 2.2, укажите совместимую версию для регистрации служб MVC в Startup.ConfigureServices:To use the latest routing scenarios in ASP.NET Core 2.2, specify the compatibility version to the MVC services registration in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Параметр EnableEndpointRouting определяет, должна ли маршрутизация внутренне использовать логику, основанную на конечных точках, или логику, основанную на IRouter, в ASP.NET Core 2.1 или более ранней версии.The EnableEndpointRouting option determines if routing should internally use endpoint-based logic or the IRouter-based logic of ASP.NET Core 2.1 or earlier. Если установлена совместимая версия 2.2 или более поздняя, значение по умолчанию — true.When the compatibility version is set to 2.2 or later, the default value is true. Задайте значение false, чтобы использовать предыдущую логику маршрутизации:Set the value to false to use the prior routing logic:

// Use the routing logic of ASP.NET Core 2.1 or earlier:
services.AddMvc(options => options.EnableEndpointRouting = false)
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

Дополнительные сведения о маршрутизации на основе IRouter см. в разделе о версии ASP.NET Core 2.1 в этой статье.For more information on IRouter-based routing, see the ASP.NET Core 2.1 version of this topic.

Важно!

В этом документе рассматривается низкоуровневая маршрутизация ASP.NET Core.This document covers low-level ASP.NET Core routing. Сведения о маршрутизации ASP.NET Core MVC см. в разделе Маршрутизация к действиям контроллера в ASP.NET Core.For information on ASP.NET Core MVC routing, see Маршрутизация к действиям контроллера в ASP.NET Core. Сведения о соглашениях о маршрутизации в Razor Pages см. в разделе Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.For information on routing conventions in Razor Pages, see Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

Основы маршрутизацииRouting basics

Для большинства приложений следует выбрать базовую описательную схему маршрутизации таким образом, чтобы URL-адреса были удобочитаемыми и осмысленными.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. Традиционный маршрут по умолчанию {controller=Home}/{action=Index}/{id?}.The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Поддерживает основную и описательную схемы маршрутизации.Supports a basic and descriptive routing scheme.
  • Является отправной точкой для приложений на базе пользовательского интерфейса.Is a useful starting point for UI-based apps.

Как правило, в зонах приложения с высоким трафиком и в особых случаях (например, конечные точки блога, интернет-магазина) добавляются дополнительные краткие маршруты с использованием маршрутизации с помощью атрибутов или выделенные традиционные маршруты.Developers commonly add additional terse routes to high-traffic areas of an app in specialized situations (for example, blog and ecommerce endpoints) using attribute routing or dedicated conventional routes.

Веб-интерфейсы API должны использовать маршрутизацию с помощью атрибутов, чтобы моделировать функциональность приложения в качестве набора ресурсов, где операции представлены с помощью команд HTTP.Web APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs. Это означает, что многие операции (например, GET, POST) на одном логическом ресурсе будут использовать одинаковый URL-адрес.This means that many operations (for example, GET, POST) on the same logical resource will use the same URL. Маршрутизация с помощью атрибутов обеспечивает необходимый уровень контроля, позволяющий тщательно разработать схему общедоступных конечных точек API-интерфейса.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Приложения Razor Pages используют стандартную маршрутизацию по умолчанию для предоставления именованных ресурсов в папке Pages приложения.Razor Pages apps use default conventional routing to serve named resources in the Pages folder of an app. Доступны дополнительные соглашения, которые позволяют настроить поведение маршрутизации Razor Pages.Additional conventions are available that allow you to customize Razor Pages routing behavior. Дополнительные сведения см. в разделах Введение в Razor Pages в ASP.NET Core и Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.For more information, see Введение в Razor Pages в ASP.NET Core and Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.

Благодаря поддержке создания URL-адресов приложение можно разрабатывать без жесткого программирования URL-адресов для связывания компонентов приложения.URL generation support allows the app to be developed without hard-coding URLs to link the app together. Это обеспечивает начало работы с основной конфигурацией маршрутизации и изменение маршрутов после определения схемы ресурсов приложения.This support allows for starting with a basic routing configuration and modifying the routes after the app's resource layout is determined.

Маршрутизация использует конечные точки (Endpoint) для представления логических конечных точек в приложении.Routing uses endpoints (Endpoint) to represent logical endpoints in an app.

Конечная точка определяет делегат для обработки запросов и коллекцию произвольных метаданных.An endpoint defines a delegate to process requests and a collection of arbitrary metadata. Метаданные используются для реализации сквозной функциональности на основе политик и конфигурации каждой конечной точки.The metadata is used implement cross-cutting concerns based on policies and configuration attached to each endpoint.

Система маршрутизации обладает следующими характеристиками:The routing system has the following characteristics:

  • Синтаксис шаблона маршрута используется для определения маршрутов с помощью параметров размеченного маршрута.Route template syntax is used to define routes with tokenized route parameters.

  • Допускается конфигурация конечной точки в стандартном стиле и с атрибутами.Conventional-style and attribute-style endpoint configuration is permitted.

  • IRouteConstraint используется для определения того, содержит ли параметр URL-адреса допустимое значение для ограничения заданной конечной точки.IRouteConstraint is used to determine whether a URL parameter contains a valid value for a given endpoint constraint.

  • Модели приложения, такие как MVC и Razor Pages, регистрируют все свои конечные точки, имеющие предсказуемую реализацию сценариев маршрутизации.App models, such as MVC/Razor Pages, register all of their endpoints, which have a predictable implementation of routing scenarios.

  • Реализация маршрутизации принимает решения о маршрутизации в нужном месте конвейера ПО промежуточного слоя.The routing implementation makes routing decisions wherever desired in the middleware pipeline.

  • ПО промежуточного слоя, которое появляется после ПО промежуточного слоя маршрутизации, может проверить результат принятия решений о конечной точке, принятое ПО промежуточного слоя маршрутизации для заданного URI запроса.Middleware that appears after a Routing Middleware can inspect the result of the Routing Middleware's endpoint decision for a given request URI.

  • Можно перечислить все конечные точки в приложении в любом месте конвейера ПО промежуточного слоя.It's possible to enumerate all of the endpoints in the app anywhere in the middleware pipeline.

  • Приложение может использовать маршрутизацию для формирования URL-адресов (например, для перенаправления или ссылок) на основе сведений о конечной точке, что позволяет избежать жесткого задания URL-адресов и упрощает поддержку.An app can use routing to generate URLs (for example, for redirection or links) based on endpoint information and thus avoid hard-coded URLs, which helps maintainability.

  • Формирование URL-адреса основано на адресах, которые поддерживают произвольную расширяемость:URL generation is based on addresses, which support arbitrary extensibility:

    • API генератора ссылок (LinkGenerator) может быть разрешено в любом месте с помощью внедрения зависимостей (DI) для формирования URL-адреса.The Link Generator API (LinkGenerator) can be resolved anywhere using dependency injection (DI) to generate URLs.
    • Если API генератора ссылок недоступно через внедрение зависимостей, IUrlHelper предлагает методы для создания URL-адреса.Where the Link Generator API isn't available via DI, IUrlHelper offers methods to build URLs.

Примечание

С появлением маршрутизации по конечным точкам в ASP.NET Core 2.2 связывание конечных точек стало ограничено действиями и страницами MVC и Razor Pages.With the release of endpoint routing in ASP.NET Core 2.2, endpoint linking is limited to MVC/Razor Pages actions and pages. Расширение функций связывания конечных точек планируется в будущих выпусках.The expansions of endpoint-linking capabilities is planned for future releases.

Функция маршрутизации подключается к конвейеру ПО промежуточного слоя с помощью класса RouterMiddleware.Routing is connected to the middleware pipeline by the RouterMiddleware class. ASP.NET Core MVC добавляет функцию маршрутизации в конвейер ПО промежуточного слоя в процессе настройки и обрабатывает маршрутизацию в приложениях MVC и Razor Pages.ASP.NET Core MVC adds routing to the middleware pipeline as part of its configuration and handles routing in MVC and Razor Pages apps. Сведения об использовании маршрутизации в виде отдельного компонента см. в руководстве по использованию ПО промежуточного слоя маршрутизации.To learn how to use routing as a standalone component, see the Use Routing Middleware section.

Соответствие URL-адресовURL matching

Сопоставление URL-адресов — это процесс, с помощью которого функция маршрутизации отправляет входящий запрос в конечную точку.URL matching is the process by which routing dispatches an incoming request to an endpoint. Этот процесс основывается на данных в пути URL-адреса, но может быть расширен для учета любых данных в запросе.This process is based on data in the URL path but can be extended to consider any data in the request. Возможность отправки запросов в отдельные обработчики имеет первостепенное значение для масштабирования размера и сложности приложения.The ability to dispatch requests to separate handlers is key to scaling the size and complexity of an app.

Система маршрутизации в маршрутизации по конечным точкам принимает все решения об отправке.The routing system in endpoint routing is responsible for all dispatching decisions. Так как ПО промежуточного слоя применяет политики в зависимости от выбранной конечной точки, очень важно, чтобы любое решение, которое может повлиять на отправку или применение политик безопасности, принималось внутри системы маршрутизации.Since the middleware applies policies based on the selected endpoint, it's important that any decision that can affect dispatching or the application of security policies is made inside the routing system.

Когда делегат конечной точки выполняется, свойствам RouteContext.RouteData присваиваются значения с учетом уже выполненной на текущий момент обработки.When the endpoint delegate is executed, the properties of RouteContext.RouteData are set to appropriate values based on the request processing performed thus far.

RouteData.Values — это словарь значений маршрута, полученных из маршрута.RouteData.Values is a dictionary of route values produced from the route. Как правило, эти значения определяются путем разбивки URL-адреса на сегменты и могут использоваться для принятия входных данных пользователя или принятия дальнейших решений об отправке в приложении.These values are usually determined by tokenizing the URL and can be used to accept user input or to make further dispatching decisions inside the app.

RouteData.DataTokens — это контейнер свойств с дополнительными данными, связанными с соответствующим маршрутом.RouteData.DataTokens is a property bag of additional data related to the matched route. Свойства DataTokens обеспечивают связывание данных состояния с каждым маршрутом, что позволяет приложению принимать решения в зависимости от соответствующего маршрута.DataTokens are provided to support associating state data with each route so that the app can make decisions based on which route matched. Эти значения определяются разработчиком и никоим образом не влияют на поведение маршрутизации.These values are developer-defined and do not affect the behavior of routing in any way. Кроме того, значения, спрятанные в токенах RouteData.DataToken, могут быть любого типа в отличие от значений RouteData.Value, которые должны легко преобразовываться в строки и из строк.Additionally, values stashed in RouteData.DataTokens can be of any type, in contrast to RouteData.Values, which must be convertible to and from strings.

RouteData.Routers — это список маршрутов, которые участвовали в успешном сопоставлении с запросом.RouteData.Routers is a list of the routes that took part in successfully matching the request. Маршруты могут быть вложены друг в друга.Routes can be nested inside of one another. Свойство Routers отражает путь по логическому дереву маршрутов, который привел к совпадению.The Routers property reflects the path through the logical tree of routes that resulted in a match. Как правило, первый элемент в свойстве Routers — это коллекция маршрутов, используемая для формирования URL-адресов.Generally, the first item in Routers is the route collection and should be used for URL generation. Последний элемент в свойстве Routers — это соответствующий обработчик маршрутов.The last item in Routers is the route handler that matched.

Создание URL-адреса с помощью LinkGeneratorURL generation with LinkGenerator

Формирование URL-адреса — это процесс создания пути URL-адреса функцией маршрутизации на основе набора значений маршрута.URL generation is the process by which routing can create a URL path based on a set of route values. Он обеспечивает логическое разделение конечных точек и URL-адресов, по которым к ним осуществляется доступ.This allows for a logical separation between your endpoints and the URLs that access them.

Маршрутизация по конечным точкам включает в себя API генератора ссылок (LinkGenerator).Endpoint routing includes the Link Generator API (LinkGenerator). LinkGenerator — это отдельная служба, которую можно получить посредством внедрения зависимостей.LinkGenerator is a singleton service that can be retrieved from DI. API можно использовать вне контекста выполнения запроса.The API can be used outside of the context of an executing request. IUrlHelper MVC и сценарии, которые зависят от IUrlHelper, такие как вспомогательные функции тегов, вспомогательные методы HTML и результаты действий, используют генератор ссылок для предоставления возможностей создания ссылок.MVC's IUrlHelper and scenarios that rely on IUrlHelper, such as Tag Helpers, HTML Helpers, and Action Results, use the link generator to provide link generating capabilities.

Генератор ссылок использует концепции адреса и схем адресов.The link generator is backed by the concept of an address and address schemes. Схема адресов — это способ определения конечных точек, которые должны рассматриваться для создания ссылки.An address scheme is a way of determining the endpoints that should be considered for link generation. Например, сценарии с именем маршрута и значениями маршрута, с которыми многие пользователи знакомы по MVC и Razor Pages, реализуются как схема адресов.For example, the route name and route values scenarios many users are familiar with from MVC/Razor Pages are implemented as an address scheme.

Генератор ссылок может установить связь с действиями и страницами MVC и Razor Pages с помощью следующих методов расширения:The link generator can link to MVC/Razor Pages actions and pages via the following extension methods:

Перегрузка этих методов принимает аргументы, которые включают HttpContext.An overload of these methods accepts arguments that include the HttpContext. Эти методы являются функциональными эквивалентами Url.Action и Url.Page, но предлагают дополнительную гибкость и параметры.These methods are functionally equivalent to Url.Action and Url.Page but offer additional flexibility and options.

Методы GetPath* наиболее схожи с Url.Action и Url.Page в том, что создают URI, содержащий абсолютный путь.The GetPath* methods are most similar to Url.Action and Url.Page in that they generate a URI containing an absolute path. Методы GetUri* всегда создают абсолютный URI, содержащий схему и узел.The GetUri* methods always generate an absolute URI containing a scheme and host. Методы, которые принимают HttpContext, создают URI в контексте выполнения запроса.The methods that accept an HttpContext generate a URI in the context of the executing request. Используются значения окружения маршрута, базовый URL-адрес, схема и узел из выполняющегося запроса, если не указано иное.The ambient route values, URL base path, scheme, and host from the executing request are used unless overridden.

LinkGenerator вызывается с адресом.LinkGenerator is called with an address. Создание URI происходит в два этапа:Generating a URI occurs in two steps:

  1. Адрес привязан к списку конечных точек, соответствующих адресу.An address is bound to a list of endpoints that match the address.
  2. RoutePattern конечной точки вычисляется, пока не будет найден шаблон маршрута, который соответствует предоставленным значениям.Each endpoint's RoutePattern is evaluated until a route pattern that matches the supplied values is found. Полученный результат объединяется с другими частями URI, предоставленными генератору ссылок и возвращенными.The resulting output is combined with the other URI parts supplied to the link generator and returned.

Методы, предоставляемые LinkGenerator, поддерживают стандартные возможности создания ссылки для любого типа адреса.The methods provided by LinkGenerator support standard link generation capabilities for any type of address. Самый удобный способ использовать генератор ссылки — через методы расширения, которые выполняют операции для определенного типа адреса.The most convenient way to use the link generator is through extension methods that perform operations for a specific address type.

Метод расширенияExtension Method ОписаниеDescription
GetPathByAddress Создает URI с абсолютным путем на основе предоставленных значений.Generates a URI with an absolute path based on the provided values.
GetUriByAddress Создает абсолютный URI на основе предоставленных значений.Generates an absolute URI based on the provided values.

Предупреждение

Обратите внимание на следующие последствия вызова методов LinkGenerator:Pay attention to the following implications of calling LinkGenerator methods:

  • Используйте методы расширения GetUri* с осторожностью в конфигурации приложения, которая не проверяет заголовок входящих запросов Host.Use GetUri* extension methods with caution in an app configuration that doesn't validate the Host header of incoming requests. Если не проверить заголовок входящих запросов Host, входные данные в запросе без доверия могут отправляться обратно клиенту в URI в представлении или странице.If the Host header of incoming requests isn't validated, untrusted request input can be sent back to the client in URIs in a view/page. Рекомендуется, чтобы все рабочие приложения настраивали свой сервер на проверку заголовка Host относительно известных допустимых значений.We recommend that all production apps configure their server to validate the Host header against known valid values.

  • Используйте LinkGenerator с осторожностью в ПО промежуточного слоя в сочетании с Map или MapWhen.Use LinkGenerator with caution in middleware in combination with Map or MapWhen. Map* изменяет базовый путь выполняющегося запроса, что влияет на выходные данные создания ссылки.Map* changes the base path of the executing request, which affects the output of link generation. Все API LinkGenerator разрешают указание базового пути.All of the LinkGenerator APIs allow specifying a base path. Всегда указывайте пустой базовый путь для отмены влияния Map* на создание ссылок.Always specify an empty base path to undo Map*'s affect on link generation.

Отличия от более ранних версий маршрутизацииDifferences from earlier versions of routing

Существует несколько различий между маршрутизацией по конечным точкам в ASP.NET Core 2.2 или более поздней версии и более ранними версиями маршрутизации в ASP.NET Core:A few differences exist between endpoint routing in ASP.NET Core 2.2 or later and earlier versions of routing in ASP.NET Core:

  • Система маршрутизации по конечным точкам не поддерживает расширяемость на основе IRouter, включая наследование от Route.The endpoint routing system doesn't support IRouter-based extensibility, including inheriting from Route.

  • Маршрутизация по конечным точкам не поддерживает WebApiCompatShim.Endpoint routing doesn't support WebApiCompatShim. Используйте совместимую версию 2.1 (.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)), чтобы продолжить использование оболочек совместимости.Use the 2.1 compatibility version (.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)) to continue using the compatibility shim.

  • Маршрутизация по конечным точкам иначе обрабатывает регистр созданных URI при использовании стандартных маршрутов.Endpoint Routing has different behavior for the casing of generated URIs when using conventional routes.

    Рассмотрим следующий шаблон маршрута по умолчанию:Consider the following default route template:

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

    Предположим, вы создаете ссылку на действие с помощью следующего маршрута:Suppose you generate a link to an action using the following route:

    var link = Url.Action("ReadPost", "blog", new { id = 17, });
    

    С помощью маршрутизации на основе IRouter этот код создает URI из /blog/ReadPost/17, который учитывает регистр предоставленного значения маршрута.With IRouter-based routing, this code generates a URI of /blog/ReadPost/17, which respects the casing of the provided route value. Маршрутизация по конечным точкам в ASP.NET Core 2.2 или более поздней версии создает /Blog/ReadPost/17 ("Blog" — с прописной буквы).Endpoint routing in ASP.NET Core 2.2 or later produces /Blog/ReadPost/17 ("Blog" is capitalized). Маршрутизация по конечным точкам предоставляет интерфейс IOutboundParameterTransformer, который можно использовать для настройки этого поведения на глобальном уровне или применения других соглашения для сопоставления URL-адресов.Endpoint routing provides the IOutboundParameterTransformer interface that can be used to customize this behavior globally or to apply different conventions for mapping URLs.

    Дополнительные сведения см. в разделе Справочник по преобразователям параметров.For more information, see the Parameter transformer reference section.

  • Создание ссылок, используемых MVC и Razor Pages со стандартными маршрутами, работает иначе при попытке сослаться на контроллер/действие или страницу, которые не существуют.Link Generation used by MVC/Razor Pages with conventional routes behaves differently when attempting to link to an controller/action or page that doesn't exist.

    Рассмотрим следующий шаблон маршрута по умолчанию:Consider the following default route template:

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

    Предположим, вы создаете ссылку на действие с помощью шаблона по умолчанию:Suppose you generate a link to an action using the default template with the following:

    var link = Url.Action("ReadPost", "Blog", new { id = 17, });
    

    С маршрутизацией на основе IRouter результатом всегда будет /Blog/ReadPost/17, даже если BlogController не существует или не имеет метода действия ReadPost.With IRouter-based routing, the result is always /Blog/ReadPost/17, even if the BlogController doesn't exist or doesn't have a ReadPost action method. Как и ожидалось, маршрутизация по конечным точкам в ASP.NET Core 2.2 или более поздней версии создает /Blog/ReadPost/17, если метод действия существует.As expected, endpoint routing in ASP.NET Core 2.2 or later produces /Blog/ReadPost/17 if the action method exists. Но маршрутизация по конечным точкам создает пустую строку, если действие не существует.However, endpoint routing produces an empty string if the action doesn't exist. По существу, маршрутизация по конечным точкам не предполагает, что конечная точка существует, если действие не существует.Conceptually, endpoint routing doesn't assume that the endpoint exists if the action doesn't exist.

  • Алгоритм отмены значения окружения при создании ссылок работает иначе при маршрутизации по конечным точкам.The link generation ambient value invalidation algorithm behaves differently when used with endpoint routing.

    Отмена значения окружения — это алгоритм, который решает, какие значения маршрута из текущего выполняемого запроса (значения окружения) могут использоваться в операции создания ссылки.Ambient value invalidation is the algorithm that decides which route values from the currently executing request (the ambient values) can be used in link generation operations. Стандартная маршрутизация всегда отменяет лишние значения маршрута при привязке к другому действию.Conventional routing always invalidated extra route values when linking to a different action. Маршрутизация с помощью атрибутов работала иначе до выпуска ASP.NET Core 2.2.Attribute routing didn't have this behavior prior to the release of ASP.NET Core 2.2. В более ранних версиях ASP.NET Core ссылки на другое действие, которые используют те же имена параметров маршрута, приводили к ошибкам создания ссылки.In earlier versions of ASP.NET Core, links to another action that use the same route parameter names resulted in link generation errors. В ASP.NET Core 2.2 или более поздней версии обе формы маршрутизации отменяют значения при привязке к другому действию.In ASP.NET Core 2.2 or later, both forms of routing invalidate values when linking to another action.

    Рассмотрим следующий пример в ASP.NET Core 2.1 или более ранней версии.Consider the following example in ASP.NET Core 2.1 or earlier. При привязке к другому действию (или странице) значения маршрута могут использоваться повторно нежелательным образом.When linking to another action (or another page), route values can be reused in undesirable ways.

    В /Pages/Store/Product.cshtml:In /Pages/Store/Product.cshtml:

    @page "{id}"
    @Url.Page("/Login")
    

    В /Pages/Login.cshtml:In /Pages/Login.cshtml:

    @page "{id?}"
    

    Если URI — /Store/Product/18 в ASP.NET Core 2.1 или более ранней версии, ссылка, созданная на странице Store/Info с помощью @Url.Page("/Login") — /Login/18.If the URI is /Store/Product/18 in ASP.NET Core 2.1 or earlier, the link generated on the Store/Info page by @Url.Page("/Login") is /Login/18. Значение id 18 используется повторно, хотя конечный объект ссылки является совсем другой частью приложения.The id value of 18 is reused, even though the link destination is different part of the app entirely. Значение маршрута id в контексте страницы /Login, вероятно, является значением идентификатора пользователя, а не кодом хранимого продукта.The id route value in the context of the /Login page is probably a user ID value, not a store product ID value.

    При маршрутизации по конечным точкам в ASP.NET Core 2.2 или более поздней версии результатом является /Login.In endpoint routing with ASP.NET Core 2.2 or later, the result is /Login. Значения окружения не используются повторно, если конечный объект ссылки является другим действием или страницей.Ambient values aren't reused when the linked destination is a different action or page.

  • Синтаксис параметра кругового маршрута: символы прямой косой черты не кодируются при использовании синтаксиса универсального параметра с двумя звездочками (**).Round-tripping route parameter syntax: Forward slashes aren't encoded when using a double-asterisk (**) catch-all parameter syntax.

    Во время создания ссылки система маршрутизации кодирует значение, записанное в универсальном параметре с двумя звездочками (**) (например, {**myparametername}), за исключением прямой косой черты.During link generation, the routing system encodes the value captured in a double-asterisk (**) catch-all parameter (for example, {**myparametername}) except the forward slashes. Универсальный параметр с двумя звездочками поддерживается в маршрутизации на основе IRouter в ASP.NET Core 2.2 или более поздней версии.The double-asterisk catch-all is supported with IRouter-based routing in ASP.NET Core 2.2 or later.

    Синтаксис универсального параметра с одной звездочкой в предыдущих версиях ASP.NET Core ({*myparametername}) поддерживается, и прямая косая черта кодируется.The single asterisk catch-all parameter syntax in prior versions of ASP.NET Core ({*myparametername}) remains supported, and forward slashes are encoded.

    МаршрутRoute Ссылка, созданная с помощьюLink generated with
    Url.Action(new { category = "admin/products" })
    /search/{*page} /search/admin%2Fproducts (прямая косая черта кодируется)/search/admin%2Fproducts (the forward slash is encoded)
    /search/{**page} /search/admin/products

Пример ПО промежуточного слояMiddleware example

В следующем примере ПО промежуточного слоя использует API LinkGenerator, чтобы создать ссылку на метод действия, который перечисляет хранимые продукты.In the following example, a middleware uses the LinkGenerator API to create link to an action method that lists store products. Использование генератора ссылок путем его внедрения в класс и вызова GenerateLink доступно для любого класса в приложении.Using the link generator by injecting it into a class and calling GenerateLink is available to any class in an app.

using Microsoft.AspNetCore.Routing;

public class ProductsLinkMiddleware
{
    private readonly LinkGenerator _linkGenerator;

    public ProductsLinkMiddleware(RequestDelegate next, LinkGenerator linkGenerator)
    {
        _linkGenerator = linkGenerator;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        var url = _linkGenerator.GetPathByAction("ListProducts", "Store");

        httpContext.Response.ContentType = "text/plain";

        await httpContext.Response.WriteAsync($"Go to {url} to see our products.");
    }
}

Создание маршрутовCreate routes

Большинство приложений создают маршруты, вызывая метод MapRoute или один из аналогичных методов расширения, определенных в интерфейсе IRouteBuilder.Most apps create routes by calling MapRoute or one of the similar extension methods defined on IRouteBuilder. Все методы расширения IRouteBuilder создают экземпляр Route и добавляют его в коллекцию маршрутов.Any of the IRouteBuilder extension methods create an instance of Route and add it to the route collection.

MapRoute не принимает параметр обработчика маршрутов.MapRoute doesn't accept a route handler parameter. MapRoute только добавляет маршруты, которые обрабатываются DefaultHandler.MapRoute only adds routes that are handled by the DefaultHandler. Дополнительные сведения о маршрутизации в MVC см. в разделе Маршрутизация к действиям контроллера в ASP.NET Core.To learn more about routing in MVC, see Маршрутизация к действиям контроллера в ASP.NET Core.

В следующем коде приводится пример вызова MapRoute, используемого в типичном определении маршрута ASP.NET Core MVC:The following code example is an example of a MapRoute call used by a typical ASP.NET Core MVC route definition:

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

Этот шаблон соответствует пути URL-адреса и извлекает значения маршрута.This template matches a URL path and extracts the route values. Например, путь /Products/Details/17 создает следующие значения маршрута: { controller = Products, action = Details, id = 17 }.For example, the path /Products/Details/17 generates the following route values: { controller = Products, action = Details, id = 17 }.

Значения маршрута определяются с помощью разделения пути URL-адреса на сегменты и сопоставления каждого сегмента с именем параметра маршрута в шаблоне маршрута.Route values are determined by splitting the URL path into segments and matching each segment with the route parameter name in the route template. Параметры маршрута являются именованными.Route parameters are named. Параметры определяются путем заключения имени параметра в фигурные скобки { ... }.The parameters defined by enclosing the parameter name in braces { ... }.

Приведенный выше шаблон может также соответствовать пути URL-адреса /. В этом случае он предоставляет значения { controller = Home, action = Index }.The preceding template could also match the URL path / and produce the values { controller = Home, action = Index }. Связано это с тем, что параметры маршрута {controller} и {action} имеют значения по умолчанию, а параметр маршрута id является необязательным.This occurs because the {controller} and {action} route parameters have default values and the id route parameter is optional. Значение по умолчанию для параметра маршрута определяется с помощью знака равенства (=), за которым следует значение после имени параметра.An equals sign (=) followed by a value after the route parameter name defines a default value for the parameter. Вопросительный знак (?) после имени параметра маршрута определяет параметр как необязательный.A question mark (?) after the route parameter name defines an optional parameter.

Параметры маршрута со значением по умолчанию всегда предоставляют значения маршрута при совпадении маршрута.Route parameters with a default value always produce a route value when the route matches. Необязательные параметры не предоставляют значение маршрута, если нет соответствующего сегмента пути URL-адреса.Optional parameters don't produce a route value if there was no corresponding URL path segment. Подробное описание сценариев и синтаксиса шаблона маршрута см. в разделе Справочник по шаблонам маршрутов.See the Route template reference section for a thorough description of route template scenarios and syntax.

В следующем примере в определении параметра маршрута {id:int} определяется ограничение маршрута для параметра маршрута id:In the following example, the route parameter definition {id:int} defines a route constraint for the id route parameter:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id:int}");

Этот шаблон соответствует такому пути URL-адреса, как /Products/Details/17, но не /Products/Details/Apples.This template matches a URL path like /Products/Details/17 but not /Products/Details/Apples. Ограничения маршрута реализуют интерфейс IRouteConstraint и проверяют значения маршрута.Route constraints implement IRouteConstraint and inspect route values to verify them. В этом примере значение маршрута id должно иметь возможность преобразования в целое число.In this example, the route value id must be convertible to an integer. Более подробное описание ограничений маршрутов, предоставляемых платформой, см. в разделе Справочник по ограничениям маршрутов.See route-constraint-reference for an explanation of route constraints provided by the framework.

Дополнительные перегрузки MapRoute принимают значения для параметров constraints, dataTokens и defaults.Additional overloads of MapRoute accept values for constraints, dataTokens, and defaults. Типичное применение этих параметров состоит в передаче анонимно типизированного объекта, причем имена свойств анонимного типа соответствуют именам параметров маршрута.The typical usage of these parameters is to pass an anonymously typed object, where the property names of the anonymous type match route parameter names.

В следующих примерах MapRoute создаются эквивалентные маршруты:The following MapRoute examples create equivalent routes:

routes.MapRoute(
    name: "default_route",
    template: "{controller}/{action}/{id?}",
    defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
    name: "default_route",
    template: "{controller=Home}/{action=Index}/{id?}");

Совет

Встроенный синтаксис определения ограничений и значений по умолчанию может быть удобнее для простых маршрутов.The inline syntax for defining constraints and defaults can be convenient for simple routes. Однако некоторые сценарии, например токены данных, не поддерживаются встроенным синтаксисом.However, there are scenarios, such as data tokens, that aren't supported by inline syntax.

В следующем примере показано еще несколько сценариев:The following example demonstrates a few additional scenarios:

routes.MapRoute(
    name: "blog",
    template: "Blog/{**article}",
    defaults: new { controller = "Blog", action = "ReadArticle" });

Предыдущий шаблон соответствует такому пути URL-адреса, как /Blog/All-About-Routing/Introduction, и извлекает значения { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }.The preceding template matches a URL path like /Blog/All-About-Routing/Introduction and extracts the values { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }. Значения маршрута по умолчанию для controller и action предоставляются маршрутом несмотря на то, что в шаблоне нет соответствующих параметров маршрута.The default route values for controller and action are produced by the route even though there are no corresponding route parameters in the template. Значения по умолчанию можно указать в шаблоне маршрута.Default values can be specified in the route template. Параметр маршрута article определяется как универсальный с помощью двух звездочек (**) перед именем.The article route parameter is defined as a catch-all by the appearance of an double asterisk (**) before the route parameter name. Универсальные параметры маршрута служат для фиксации оставшейся части пути URL-адреса, а также могут соответствовать пустой строке.Catch-all route parameters capture the remainder of the URL path and can also match the empty string.

В следующем примере добавляются ограничения маршрута и токены данных:The following example adds route constraints and data tokens:

routes.MapRoute(
    name: "us_english_products",
    template: "en-US/Products/{id}",
    defaults: new { controller = "Products", action = "Details" },
    constraints: new { id = new IntRouteConstraint() },
    dataTokens: new { locale = "en-US" });

Предыдущий шаблон будет соответствовать такому пути URL-адреса, как /en-US/Products/5, и будет извлекать значения { controller = Products, action = Details, id = 5 } и токены данных { locale = en-US }.The preceding template matches a URL path like /en-US/Products/5 and extracts the values { controller = Products, action = Details, id = 5 } and the data tokens { locale = en-US }.

Токены в окне "Локальные"

Формирование URL-адреса класса маршрутаRoute class URL generation

Класс Route может также формировать URL-адрес, объединяя набор значений маршрута с шаблоном маршрута.The Route class can also perform URL generation by combining a set of route values with its route template. С логической точки зрения, этот процесс обратен сопоставлению пути URL-адреса.This is logically the reverse process of matching the URL path.

Совет

Чтобы лучше понять процесс формирования URL-адреса, представьте себе, какой URL-адрес нужно создать, а затем подумайте, как шаблон маршрута будет сопоставляться с этим URL-адресом.To better understand URL generation, imagine what URL you want to generate and then think about how a route template would match that URL. Какие значения будут получены?What values would be produced? Примерно так производится формирование URL-адреса в классе Route.This is the rough equivalent of how URL generation works in the Route class.

В следующем примере используется общий маршрут по умолчанию ASP.NET Core MVC:The following example uses a general ASP.NET Core MVC default route:

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

При значениях маршрута { controller = Products, action = List } создается URL-адрес /Products/List.With the route values { controller = Products, action = List }, the URL /Products/List is generated. Значения маршрута заменяются на соответствующие параметры маршрута для образования пути URL-адреса.The route values are substituted for the corresponding route parameters to form the URL path. Так как id является необязательным параметром маршрута, URL-адрес успешно создается без значения для id.Since id is an optional route parameter, the URL is successfully generated without a value for id.

При значениях маршрута { controller = Home, action = Index } создается URL-адрес /.With the route values { controller = Home, action = Index }, the URL / is generated. Предоставленные значения маршрута соответствуют значениям по умолчанию, поэтому сегменты, соответствующие значениям по умолчанию, можно спокойно опустить.The provided route values match the default values, and the segments corresponding to the default values are safely omitted.

Оба созданных URL-адреса будут совершать круговой путь с таким же определением маршрута (/Home/Index и /) и предоставлять те же значения маршрута, которые использовались для формирования URL-адреса.Both URLs generated round-trip with the following route definition (/Home/Index and /) produce the same route values that were used to generate the URL.

Примечание

Приложение, использующее платформу ASP.NET Core MVC, должно создавать URL-адреса с помощью объекта UrlHelper, а не вызывать маршрутизацию напрямую.An app using ASP.NET Core MVC should use UrlHelper to generate URLs instead of calling into routing directly.

Дополнительные сведения о формировании URL-адресов см. в справочнике по формированию URL-адресов.For more information on URL generation, see the Url generation reference section.

Использование ПО промежуточного слоя маршрутизацииUse Routing Middleware

Ссылка на метапакет Microsoft.AspNetCore.App в файле проекта приложения.Reference the Microsoft.AspNetCore.App metapackage in the app's project file.

Добавьте маршрутизацию в контейнер службы в файле Startup.ConfigureServices:Add routing to the service container in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRouting();
}

Маршруты должны настраиваться в методе Startup.Configure.Routes must be configured in the Startup.Configure method. В этом примере приложения используются следующие API:The sample app uses the following APIs:

var trackPackageRouteHandler = new RouteHandler(context =>
{
    var routeValues = context.GetRouteData().Values;
    return context.Response.WriteAsync(
        $"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
    "Track Package Route",
    "package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>
{
    var name = context.GetRouteValue("name");
    // The route handler when HTTP GET "hello/<anything>" matches
    // To match HTTP GET "hello/<anything>/<anything>, 
    // use routeBuilder.MapGet("hello/{*name}"
    return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();
app.UseRouter(routes);

В таблице ниже приведены ответы с данными универсальными кодами ресурсов (URI).The following table shows the responses with the given URIs.

URIURI ОтветResponse
/package/create/3 Hello!Hello! Значения маршрута: [operation, create], [id, 3]Route values: [operation, create], [id, 3]
/package/track/-3 Hello!Hello! Значения маршрута: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/-3/ Hello!Hello! Значения маршрута: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/ Запрос не дал результата, нет совпадений.The request falls through, no match.
GET /hello/Joe Hi, Joe!Hi, Joe!
POST /hello/Joe Запрос не дал результата, совпадение только с HTTP GET.The request falls through, matches HTTP GET only.
GET /hello/Joe/Smith Запрос не дал результата, нет совпадений.The request falls through, no match.

Платформа предоставляет наборов методов расширения для создания маршрутов (RequestDelegateRouteBuilderExtensions):The framework provides a set of extension methods for creating routes (RequestDelegateRouteBuilderExtensions):

Методы Map[Verb] используют ограничения, чтобы ограничить маршрут к HTTP-команде в имени метода.The Map[Verb] methods use constraints to limit the route to the HTTP Verb in the method name. Например, см. класс MapGet и тип MapVerb.For example, see MapGet and MapVerb.

Справочник по шаблону маршрутаRoute template reference

Токены в фигурных скобках ({ ... }) определяют параметры маршрута, которые будут привязаны при совпадении маршрута.Tokens within curly braces ({ ... }) define route parameters that are bound if the route is matched. В сегменте маршрута можно определить несколько параметров маршрута, но они должны разделяться литеральным значением.You can define more than one route parameter in a route segment, but they must be separated by a literal value. Например, {controller=Home}{action=Index} будет недопустимым маршрутом, так как между {controller} и {action} нет литерального значения.For example, {controller=Home}{action=Index} isn't a valid route, since there's no literal value between {controller} and {action}. Эти параметры маршрута должны иметь имена, и для них могут быть определены дополнительные атрибуты.These route parameters must have a name and may have additional attributes specified.

Весь текст, кроме параметров маршрута (например, {id}) и разделителя пути /, должен соответствовать тексту в URL-адресе.Literal text other than route parameters (for example, {id}) and the path separator / must match the text in the URL. Сопоставление текста производится без учета регистра на основе декодированного представления путь URL-адреса.Text matching is case-insensitive and based on the decoded representation of the URLs path. Для сопоставления с литеральным разделителем параметров маршрута ({ или }) разделитель следует экранировать путем повтора символа ({{ или }}).To match a literal route parameter delimiter ({ or }), escape the delimiter by repeating the character ({{ or }}).

Шаблоны URL-адресов, которые пытаются получить имя файла с необязательным расширением, имеют свои особенности.URL patterns that attempt to capture a file name with an optional file extension have additional considerations. Например, рассмотрим шаблон files/{filename}.{ext?}.For example, consider the template files/{filename}.{ext?}. Когда значения для filename и ext существуют, заполняются оба значения.When values for both filename and ext exist, both values are populated. Если в URL-адресе есть только значение для filename, маршрут совпадает, так как точка в конце (.) является необязательной.If only a value for filename exists in the URL, the route matches because the trailing period (.) is optional. Следующие URL-адреса соответствуют этому маршруту:The following URLs match this route:

  • /files/myFile.txt
  • /files/myFile

Вы можете использовать звездочку (*) или две звездочки (**) в качестве префикса параметра маршрута для привязки к остальной части URI.You can use an asterisk (*) or double asterisk (**) as a prefix to a route parameter to bind to the rest of the URI. Такие параметры называются универсальными.These are called a catch-all parameters. Например, blog/{**slug} соответствует любому URI, начинающемуся с сегмента /blog, за которым следует любое значение, присваиваемое в качестве значения маршрута slug.For example, blog/{**slug} matches any URI that starts with /blog and has any value following it, which is assigned to the slug route value. Универсальные параметры также могут соответствовать пустой строке.Catch-all parameters can also match the empty string.

Универсальный параметр экранирует соответствующие символы, если маршрут использует для формирования URL-адрес, включая символы разделителей пути (/).The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator (/) characters. Например, маршрут foo/{*path} со значениями маршрутов { path = "my/path" } формирует foo/my%2Fpath.For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Обратите внимание на экранированный знак косой черты.Note the escaped forward slash. В качестве символов разделителя кругового пути используйте префикс параметра маршрута **.To round-trip path separator characters, use the ** route parameter prefix. Маршрут foo/{**path} с { path = "my/path" } формирует foo/my/path.The route foo/{**path} with { path = "my/path" } generates foo/my/path.

Параметры маршрута могут иметь значения по умолчанию. Они указываются после имени параметра и знака равенства (=).Route parameters may have default values designated by specifying the default value after the parameter name separated by an equals sign (=). Например, {controller=Home} определяет Home в качестве значения по умолчанию для controller.For example, {controller=Home} defines Home as the default value for controller. Значение по умолчанию используется, если для параметра нет значения в URL-адресе.The default value is used if no value is present in the URL for the parameter. Параметры маршрута могут быть необязательными (для этого необходимо добавить вопросительный знак (?) в конец имени параметра, например id?).Route parameters are made optional by appending a question mark (?) to the end of the parameter name, as in id?. Различие между необязательными параметрами и параметрами маршрута по умолчанию в том, что вторые всегда имеют значения — необязательный параметр имеет значение, только если оно предоставлено URL-адресом запроса.The difference between optional values and default route parameters is that a route parameter with a default value always produces a value—an optional parameter has a value only when a value is provided by the request URL.

Параметры маршрута могут иметь ограничения, которые должны соответствовать значению маршрута из URL-адреса.Route parameters may have constraints that must match the route value bound from the URL. Добавив двоеточие (:) и имя ограничения после имени параметра маршрута, можно указать встроенные ограничения для параметра маршрута.Adding a colon (:) and constraint name after the route parameter name specifies an inline constraint on a route parameter. Если для ограничения требуются аргументы, они указываются в скобках ((...)) после имени ограничения.If the constraint requires arguments, they're enclosed in parentheses ((...)) after the constraint name. Чтобы указать несколько встроенных ограничений, добавьте еще одно двоеточие (:) и имя ограничения.Multiple inline constraints can be specified by appending another colon (:) and constraint name.

Имя и аргументы ограничения передаются в службу IInlineConstraintResolver для создания экземпляра интерфейса IRouteConstraint, который будет использоваться при обработке URL-адреса.The constraint name and arguments are passed to the IInlineConstraintResolver service to create an instance of IRouteConstraint to use in URL processing. Например, в шаблоне маршрута blog/{article:minlength(10)} определяется ограничение minlength с аргументом 10.For example, the route template blog/{article:minlength(10)} specifies a minlength constraint with the argument 10. Более подробное описание ограничений маршрутов и список ограничений, предоставляемых платформой, см. в разделе Справочник по ограничениям маршрутов.For more information on route constraints and a list of the constraints provided by the framework, see the Route constraint reference section.

Параметры маршрута также могут иметь преобразователи параметров, которые преобразуют значение параметра при создании ссылок и сопоставлении действий и страниц с URL-адресами.Route parameters may also have parameter transformers, which transform a parameter's value when generating links and matching actions and pages to URLs. Как и ограничения, преобразователи параметров можно включать в параметр маршрута, добавив двоеточие (:) и имя преобразователя после имени параметра маршрута.Like constraints, parameter transformers can be added inline to a route parameter by adding a colon (:) and transformer name after the route parameter name. Например, шаблон маршрута blog/{article:slugify} задает преобразователь slugify.For example, the route template blog/{article:slugify} specifies a slugify transformer. Дополнительные сведения о преобразователях параметров см. в разделе Справочник по преобразователям параметров.For more information on parameter transformers, see the Parameter transformer reference section.

В приведенной ниже таблице показаны некоторые примеры шаблонов маршрутов и их поведение.The following table demonstrates example route templates and their behavior.

Шаблон маршрутаRoute Template Пример соответствующего URIExample Matching URI URI запроса…The request URI…
hello /hello Соответствует только одному пути /hello.Only matches the single path /hello.
{Page=Home} / Соответствует и задает для параметра Page значение Home.Matches and sets Page to Home.
{Page=Home} /Contact Соответствует и задает для параметра Page значение Contact.Matches and sets Page to Contact.
{controller}/{action}/{id?} /Products/List Сопоставляется с контроллером Products и действием List.Maps to the Products controller and List action.
{controller}/{action}/{id?} /Products/Details/123 Сопоставляется с контроллером Products и действием Details (id имеет значение 123).Maps to the Products controller and Details action (id set to 123).
{controller=Home}/{action=Index}/{id?} / Сопоставляется с контроллером Home и методом Index (id пропускается).Maps to the Home controller and Index method (id is ignored).

Использование шаблона — это, как правило, самый простой подход к маршрутизации.Using a template is generally the simplest approach to routing. Ограничения и значения по умолчанию также могут указываться вне шаблона маршрута.Constraints and defaults can also be specified outside the route template.

Совет

Чтобы увидеть, как встроенные реализации маршрутизации, такие как Route, сопоставляются с запросами, включите ведение журнала.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Зарезервированные имена маршрутизацииReserved routing names

Следующие ключевые слова являются зарезервированными именами и не могут использоваться как имена маршрутов или параметры:The following keywords are reserved names and can't be used as route names or parameters:

  • action
  • area
  • controller
  • handler
  • page

Справочник по ограничениям маршрутовRoute constraint reference

Ограничения маршрута применяются, когда найдено соответствие входящему URL-адресу и путь URL-адреса был разобран на значения маршрута.Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values. Как правило, ограничения маршрута служат для проверки значения маршрута, связанного посредством шаблона маршрута, и принятия решения касательно того, является ли значение приемлемым (да или нет).Route constraints generally inspect the route value associated via the route template and make a yes/no decision about whether or not the value is acceptable. Некоторые ограничения маршрута используют данные, не относящиеся к значению маршрута, для определения возможности маршрутизации запроса.Some route constraints use data outside the route value to consider whether the request can be routed. Например, HttpMethodRouteConstraint может принимать или отклонять запрос в зависимости от HTTP-команды.For example, the HttpMethodRouteConstraint can accept or reject a request based on its HTTP verb. Ограничения используются в маршрутизации запросов и создании ссылок.Constraints are used in routing requests and link generation.

Предупреждение

Не используйте ограничения для проверки входных данных.Don't use constraints for input validation. Если ограничения используются для проверки входных данных, недопустимые входные данные будут вызывать ошибку 404 (не найдено) вместо ошибки 400 (неверный запрос) с соответствующим сообщением.If constraints are used for input validation, invalid input results in a 404 - Not Found response instead of a 400 - Bad Request with an appropriate error message. Ограничения маршрутов следует использовать для разрешения неоднозначности похожих маршрутов, а не для проверки входных данных определенного маршрута.Route constraints are used to disambiguate similar routes, not to validate the inputs for a particular route.

В приведенной ниже таблице показаны примеры ограничения маршрутов и их ожидаемое поведение.The following table demonstrates example route constraints and their expected behavior.

ограничениеconstraint ПримерExample Примеры совпаденийExample Matches ПримечанияNotes
int {id:int} 123456789, -123456789123456789, -123456789 Соответствует любому целому числуMatches any integer
bool {active:bool} true, FALSEtrue, FALSE Соответствует true или false (без учета регистра)Matches true or false (case-insensitive)
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Соответствует допустимому значению DateTime (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid DateTime value (in the invariant culture - see warning)
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Соответствует допустимому значению decimal (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid decimal value (in the invariant culture - see warning)
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Соответствует допустимому значению double (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid double value (in the invariant culture - see warning)
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Соответствует допустимому значению float (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid float value (in the invariant culture - see warning)
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} Соответствует допустимому значению GuidMatches a valid Guid value
long {ticks:long} 123456789, -123456789123456789, -123456789 Соответствует допустимому значению longMatches a valid long value
minlength(value) {username:minlength(4)} Rick Строка должна содержать не менее 4 символовString must be at least 4 characters
maxlength(value) {filename:maxlength(8)} Richard Строка должна содержать не более 8 символовString must be no more than 8 characters
length(length) {filename:length(12)} somefile.txt Длина строки должна составлять ровно 12 символовString must be exactly 12 characters long
length(min,max) {filename:length(8,16)} somefile.txt Строка должна содержать от 8 до 16 символовString must be at least 8 and no more than 16 characters long
min(value) {age:min(18)} 19 Целочисленное значение не меньше 18Integer value must be at least 18
max(value) {age:max(120)} 91 Целочисленное значение не больше 120Integer value must be no more than 120
range(min,max) {age:range(18,120)} 91 Целочисленное значение от 18 до 120Integer value must be at least 18 but no more than 120
alpha {name:alpha} Rick Строка должна состоять из одной или нескольких букв (a-z, без учета регистра)String must consist of one or more alphabetical characters (a-z, case-insensitive)
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 Строка должна соответствовать регулярному выражению (см. советы по определению регулярного выражения)String must match the regular expression (see tips about defining a regular expression)
required {name:required} Rick Определяет обязательное наличие значения, не относящегося к параметру, во время формирования URL-адресаUsed to enforce that a non-parameter value is present during URL generation

К одному параметру может применяться несколько разделенных запятой ограничений.Multiple, colon-delimited constraints can be applied to a single parameter. Например, следующее ограничение ограничивает параметр целочисленным значением 1 или больше:For example, the following constraint restricts a parameter to an integer value of 1 or greater:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

Предупреждение

Ограничения маршрута, которые проверяют URL-адрес и могут быть преобразованы в тип CLR (например, int или DateTime), всегда используют инвариантные язык и региональные параметры.Route constraints that verify the URL and are converted to a CLR type (such as int or DateTime) always use the invariant culture. Эти ограничения предполагают, что URL-адрес является нелокализуемым.These constraints assume that the URL is non-localizable. Предоставляемые платформой ограничения маршрутов не изменяют значения, хранящиеся в значениях маршрута.The framework-provided route constraints don't modify the values stored in route values. Все значения маршрута, переданные из URL-адреса, сохраняются как строки.All route values parsed from the URL are stored as strings. Например, ограничение float пытается преобразовать значение маршрута в число с плавающей запятой, но преобразованное значение служит только для проверки возможности такого преобразования.For example, the float constraint attempts to convert the route value to a float, but the converted value is used only to verify it can be converted to a float.

Регулярные выраженияRegular expressions

В платформе ASP.NET Core в конструктор регулярных выражений добавляются члены RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant.The ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant to the regular expression constructor. Описание этих членов см. в разделе RegexOptions.See RegexOptions for a description of these members.

В регулярных выражениях применяются разделители и токены, аналогичные используемым функцией маршрутизации и в языке C#.Regular expressions use delimiters and tokens similar to those used by Routing and the C# language. Токены регулярного выражения должны быть экранированы.Regular expression tokens must be escaped. Чтобы использовать регулярное выражение ^\d{3}-\d{2}-\d{4}$ при маршрутизации, выражение должно иметь символы \ (обратная косая черта), представленные в строке в виде символов \\ (двойная обратная косая черта) в исходном файле C#, для экранирования escape-символов строки \ (если не используются буквальные строковые литералы).To use the regular expression ^\d{3}-\d{2}-\d{4}$ in routing, the expression must have the \ (single backslash) characters provided in the string as \\ (double backslash) characters in the C# source file in order to escape the \ string escape character (unless using verbatim string literals). Чтобы экранировать символы разделения параметров маршрутизации ({, }, [, ]), используйте их дважды в выражении ({{, }, [[, ]]).To escape routing parameter delimiter characters ({, }, [, ]), double the characters in the expression ({{, }, [[, ]]). В следующей таблице показаны регулярные выражения и их экранированные варианты.The following table shows a regular expression and the escaped version.

Регулярное выражениеRegular Expression Экранированное регулярное выражениеEscaped Regular Expression
^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$ ^[[a-z]]{{2}}$

Регулярные выражения, используемые при маршрутизации, часто начинаются с символа карета (^) и соответствуют начальной позиции строки.Regular expressions used in routing often start with the caret (^) character and match starting position of the string. Выражения часто заканчиваются знаком доллара ($) и соответствуют концу строки.The expressions often end with the dollar sign ($) character and match end of the string. Благодаря символам ^ и $ регулярное выражение сопоставляется со всем значением параметра маршрута.The ^ and $ characters ensure that the regular expression match the entire route parameter value. Если символы ^ и $ отсутствуют, регулярное выражение сопоставляется с любой подстрокой внутри строки, что обычно нежелательно.Without the ^ and $ characters, the regular expression match any substring within the string, which is often undesirable. В следующей таблице представлен ряд примеров и объясняются причины соответствия или несоответствия.The following table provides examples and explains why they match or fail to match.

ВыражениеExpression СтрокаString СоответствиеMatch Добавление примечанийComment
[a-z]{2} hellohello ДаYes Соответствие подстрокиSubstring matches
[a-z]{2} 123abc456123abc456 ДаYes Соответствие подстрокиSubstring matches
[a-z]{2} mzmz ДаYes Соответствует выражениюMatches expression
[a-z]{2} MZMZ ДаYes Без учета регистраNot case sensitive
^[a-z]{2}$ hellohello НетNo См. замечания, касающиеся символов ^ и $, вышеSee ^ and $ above
^[a-z]{2}$ 123abc456123abc456 НетNo См. замечания, касающиеся символов ^ и $, вышеSee ^ and $ above

Дополнительные сведения о синтаксисе регулярных выражений см. в статье Регулярные выражения в .NET Framework.For more information on regular expression syntax, see .NET Framework Regular Expressions.

Чтобы ограничить возможные значения параметра набором известных значений, используйте регулярное выражение.To constrain a parameter to a known set of possible values, use a regular expression. Например, при использовании выражения {action:regex(^(list|get|create)$)} значение маршрута action будет соответствовать только list, get или create.For example, {action:regex(^(list|get|create)$)} only matches the action route value to list, get, or create. При передаче в словарь ограничений строка ^(list|get|create)$ будет эквивалентной.If passed into the constraints dictionary, the string ^(list|get|create)$ is equivalent. Ограничения, которые передаются в словарь ограничений (то есть не являются встроенными ограничениями шаблона) и не соответствуют одному из известных ограничений, также рассматриваются как регулярные выражения.Constraints that are passed in the constraints dictionary (not inline within a template) that don't match one of the known constraints are also treated as regular expressions.

Пользовательские ограничения маршрутовCustom Route Constraints

Помимо встроенных ограничений маршрутов пользовательские ограничения маршрутов можно создать путем внедрения интерфейса IRouteConstraint.In addition to the built-in route constraints, custom route constraints can be created by implementing the IRouteConstraint interface. Интерфейс IRouteConstraint содержит один метод, Match, который возвращает true, если ограничение удовлетворяется, и false — если нет.The IRouteConstraint interface contains a single method, Match, which returns true if the constraint is satisfied and false otherwise.

Чтобы применить пользовательский метод IRouteConstraint, тип ограничения маршрута необходимо зарегистрировать с помощью ConstraintMap приложения в контейнере службы приложения.To use a custom IRouteConstraint, the route constraint type must be registered with the app's ConstraintMap in the app's service container. Объект ConstraintMap — это словарь, который сопоставляет ключи ограничений пути с реализациями IRouteConstraint, которые проверяют эти ограничения.A ConstraintMap is a dictionary that maps route constraint keys to IRouteConstraint implementations that validate those constraints. ConstraintMap приложения можно преобразовать в Startup.ConfigureServices как часть вызова services.AddRouting или путем настройки RouteOptions непосредственно с помощью services.Configure<RouteOptions>.An app's ConstraintMap can be updated in Startup.ConfigureServices either as part of a services.AddRouting call or by configuring RouteOptions directly with services.Configure<RouteOptions>. Пример:For example:

services.AddRouting(options =>
{
    options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

Ограничения могут применяться к маршрутам обычным способом с использованием имени, указанного при регистрации типа ограничения.The constraint can then be applied to routes in the usual manner, using the name specified when registering the constraint type. Пример:For example:

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

Справочник по преобразователям параметровParameter transformer reference

Преобразователи параметров:Parameter transformers:

  • Выполняются при формировании ссылки для Route.Execute when generating a link for a Route.
  • Реализуйте расширение Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.Implement Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
  • Настраиваются с помощью ConstraintMap.Are configured using ConstraintMap.
  • Принимают значение маршрута параметра и изменяют его на новое строковое значение.Take the parameter's route value and transform it to a new string value.
  • Приводят к использованию преобразованного значения в сформированной ссылке.Result in using the transformed value in the generated link.

Например, пользовательский преобразователь параметра slugify в шаблоне маршрута blog\{article:slugify} с Url.Action(new { article = "MyTestArticle" }) формирует значение blog\my-test-article.For example, a custom slugify parameter transformer in route pattern blog\{article:slugify} with Url.Action(new { article = "MyTestArticle" }) generates blog\my-test-article.

Чтобы использовать преобразователь параметров в шаблоне маршрута, сначала настройте его с помощью ConstraintMap в Startup.ConfigureServices:To use a parameter transformer in a route pattern, configure it first using ConstraintMap in Startup.ConfigureServices:

services.AddRouting(options =>
{
    // Replace the type and the name used to refer to it with your own
    // IOutboundParameterTransformer implementation
    options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
});

Преобразователи параметров также используются платформами для преобразования URI, где разрешается конечная точка.Parameter transformers are used by the framework to transform the URI where an endpoint resolves. Например, ASP.NET Core MVC с помощью преобразователей параметров преобразует значение маршрута, используемое для сопоставления area, controller, action и page.For example, ASP.NET Core MVC uses parameter transformers to transform the route value used to match an area, controller, action, and page.

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

С помощью предыдущего маршрута действие SubscriptionManagementController.GetAll() сопоставляется с URI /subscription-management/get-all.With the preceding route, the action SubscriptionManagementController.GetAll() is matched with the URI /subscription-management/get-all. Преобразователь параметра не изменяет значения маршрута, используемые для формирования ссылки.A parameter transformer doesn't change the route values used to generate a link. Например, Url.Action("GetAll", "SubscriptionManagement") выводит /subscription-management/get-all.For example, Url.Action("GetAll", "SubscriptionManagement") outputs /subscription-management/get-all.

ASP.NET Core предоставляет соглашения об API для использования преобразователей параметров со сформированными маршрутами:ASP.NET Core provides API conventions for using a parameter transformers with generated routes:

  • ASP.NET Core MVC поддерживает соглашение об API Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention.ASP.NET Core MVC has the Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention API convention. Это соглашение применяет указанный преобразователь параметров ко всем маршрутам атрибутов в приложении.This convention applies a specified parameter transformer to all attribute routes in the app. Преобразователь параметров преобразует маркеры маршрутов атрибутов по мере их замены.The parameter transformer transforms attribute route tokens as they are replaced. Дополнительные сведения см. в разделе об использовании преобразователя параметров для настройки замены маркеров.For more information, see Use a parameter transformer to customize token replacement.
  • Razor Pages поддерживает соглашение об API Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention.Razor Pages has the Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API convention. Это соглашение применяет указанный преобразователь параметров ко всем автоматически обнаруженным страницам Razor Pages.This convention applies a specified parameter transformer to all automatically discovered Razor Pages. Преобразователь параметров преобразует сегменты папок и имен файлов маршрутов Razor Pages.The parameter transformer transforms the folder and file name segments of Razor Pages routes. Дополнительные сведения см. в разделе об использовании преобразователя параметров для настройки маршрутов страниц.For more information, see Use a parameter transformer to customize page routes.

Справочник по формированию URL-адресовURL generation reference

В приведенном ниже примере показано, как создать ссылку на маршрут с использованием словаря значений маршрута и коллекции RouteCollection.The following example shows how to generate a link to a route given a dictionary of route values and a RouteCollection.

app.Run(async (context) =>
{
    var dictionary = new RouteValueDictionary
    {
        { "operation", "create" },
        { "id", 123}
    };

    var vpc = new VirtualPathContext(context, null, dictionary, 
        "Track Package Route");
    var path = routes.GetVirtualPath(vpc).VirtualPath;

    context.Response.ContentType = "text/html";
    await context.Response.WriteAsync("Menu<hr/>");
    await context.Response.WriteAsync(
        $"<a href='{path}'>Create Package 123</a><br/>");
});

В результате приведенного выше примера создается VirtualPath со значением /package/create/123.The VirtualPath generated at the end of the preceding sample is /package/create/123. Словарь предоставляет значения маршрута operation и id шаблона "Отслеживание маршрута пакета", package/{operation}/{id}.The dictionary supplies the operation and id route values of the "Track Package Route" template, package/{operation}/{id}. Дополнительные сведения см. в примере кода в разделе Использование ПО промежуточного слоя маршрутизации или в примере приложения.For details, see the sample code in the Use Routing Middleware section or the sample app.

Второй параметр конструктора VirtualPathContext — это коллекция значений окружения.The second parameter to the VirtualPathContext constructor is a collection of ambient values. Значения окружения упрощают разработку, ограничивая число значений, которые необходимо указывать в определенном контексте запроса.Ambient values are convenient to use because they limit the number of values a developer must specify within a request context. Текущие значения маршрута текущего запроса считаются значениями окружения для создания ссылки.The current route values of the current request are considered ambient values for link generation. В приложении ASP.NET MVC в действии About контроллера HomeController не нужно задавать значение маршрута контроллера, указывающее на действие Index— используется значение окружения Home.In an ASP.NET Core MVC app's About action of the HomeController, you don't need to specify the controller route value to link to the Index action—the ambient value of Home is used.

Значения окружения, которые не соответствуют параметру, игнорируются.Ambient values that don't match a parameter are ignored. Значения окружения также не учитываются, когда явно указанное значение переопределяет значение окружения.Ambient values are also ignored when an explicitly provided value overrides the ambient value. Сопоставление выполняется слева направо в URL-адресе.Matching occurs from left to right in the URL.

Явно предоставленные значения, которые не соответствуют сегменту маршрута, добавляются в строку запроса.Values explicitly provided but that don't match a segment of the route are added to the query string. В приведенной ниже таблице показан результат использования шаблона маршрута {controller}/{action}/{id?}.The following table shows the result when using the route template {controller}/{action}/{id?}.

Значения окруженияAmbient Values Явные значенияExplicit Values РезультатResult
controller = "Home"controller = "Home" action = "About"action = "About" /Home/About
controller = "Home"controller = "Home" controller = "Order", action = "About"controller = "Order", action = "About" /Order/About
controller = "Home", color = "Red"controller = "Home", color = "Red" action = "About"action = "About" /Home/About
controller = "Home"controller = "Home" action = "About", color = "Red"action = "About", color = "Red" /Home/About?color=Red

Если маршрут имеет значение по умолчанию, которое не соответствует параметру, и это значение предоставлено явным образом, оно должно соответствовать значению по умолчанию:If a route has a default value that doesn't correspond to a parameter and that value is explicitly provided, it must match the default value:

routes.MapRoute("blog_route", "blog/{*slug}",
    defaults: new { controller = "Blog", action = "ReadPost" });

Для этого маршрута ссылка будет создана только в том случае, если предоставлены соответствующие значения для controller и action.Link generation only generates a link for this route when the matching values for controller and action are provided.

Сложные сегментыComplex segments

Сложные сегменты (например, [Route("/x{token}y")]) обрабатываются путем "нежадного" сопоставления литералов справа налево.Complex segments (for example [Route("/x{token}y")]) are processed by matching up literals from right to left in a non-greedy way. Подробные сведения о сопоставлении сложных сегментов см. в этом коде.See this code for a detailed explanation of how complex segments are matched. Пример кода не используется в ASP.NET Core, но он предоставляет подробное объяснение сложных сегментов.The code sample is not used by ASP.NET Core, but it provides a good explanation of complex segments.

Маршрутизация отвечает за сопоставление URI запросов с обработчиками маршрутов и отправку входящих запросов.Routing is responsible for mapping request URIs to route handlers and dispatching an incoming requests. Маршруты определяются в приложении и настраиваются при его запуске.Routes are defined in the app and configured when the app starts. Маршрут может также извлекать значения из содержащегося в запросе URL-адреса, которые затем используются для обработки запроса.A route can optionally extract values from the URL contained in the request, and these values can then be used for request processing. С помощью настроенных маршрутов из приложения маршрутизация создает URL-адреса, которые сопоставляются с обработчиками маршрутов.Using configured routes from the app, routing is able to generate URLs that map to route handlers.

Чтобы использовать новейшие сценарии маршрутизации в ASP.NET Core 2.1, укажите совместимую версию для регистрации служб MVC в Startup.ConfigureServices:To use the latest routing scenarios in ASP.NET Core 2.1, specify the compatibility version to the MVC services registration in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Важно!

В этом документе рассматривается низкоуровневая маршрутизация ASP.NET Core.This document covers low-level ASP.NET Core routing. Сведения о маршрутизации ASP.NET Core MVC см. в разделе Маршрутизация к действиям контроллера в ASP.NET Core.For information on ASP.NET Core MVC routing, see Маршрутизация к действиям контроллера в ASP.NET Core. Сведения о соглашениях о маршрутизации в Razor Pages см. в разделе Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.For information on routing conventions in Razor Pages, see Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.

Просмотреть или скачать образец кода (как скачивать)View or download sample code (how to download)

Основы маршрутизацииRouting basics

Для большинства приложений следует выбрать базовую описательную схему маршрутизации таким образом, чтобы URL-адреса были удобочитаемыми и осмысленными.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. Традиционный маршрут по умолчанию {controller=Home}/{action=Index}/{id?}.The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Поддерживает основную и описательную схемы маршрутизации.Supports a basic and descriptive routing scheme.
  • Является отправной точкой для приложений на базе пользовательского интерфейса.Is a useful starting point for UI-based apps.

Как правило, в зонах приложения с высоким трафиком и в особых случаях (например, конечные точки блога, интернет-магазина) добавляются дополнительные краткие маршруты с использованием маршрутизации с помощью атрибутов или выделенные традиционные маршруты.Developers commonly add additional terse routes to high-traffic areas of an app in specialized situations (for example, blog and ecommerce endpoints) using attribute routing or dedicated conventional routes.

Веб-интерфейсы API должны использовать маршрутизацию с помощью атрибутов, чтобы моделировать функциональность приложения в качестве набора ресурсов, где операции представлены с помощью команд HTTP.Web APIs should use attribute routing to model the app's functionality as a set of resources where operations are represented by HTTP verbs. Это означает, что многие операции (например, GET, POST) на одном логическом ресурсе будут использовать одинаковый URL-адрес.This means that many operations (for example, GET, POST) on the same logical resource will use the same URL. Маршрутизация с помощью атрибутов обеспечивает необходимый уровень контроля, позволяющий тщательно разработать схему общедоступных конечных точек API-интерфейса.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Приложения Razor Pages используют стандартную маршрутизацию по умолчанию для предоставления именованных ресурсов в папке Pages приложения.Razor Pages apps use default conventional routing to serve named resources in the Pages folder of an app. Доступны дополнительные соглашения, которые позволяют настроить поведение маршрутизации Razor Pages.Additional conventions are available that allow you to customize Razor Pages routing behavior. Дополнительные сведения см. в разделах Введение в Razor Pages в ASP.NET Core и Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.For more information, see Введение в Razor Pages в ASP.NET Core and Соглашения для маршрутов и приложений Razor Pages в ASP.NET Core.

Благодаря поддержке создания URL-адресов приложение можно разрабатывать без жесткого программирования URL-адресов для связывания компонентов приложения.URL generation support allows the app to be developed without hard-coding URLs to link the app together. Это обеспечивает начало работы с основной конфигурацией маршрутизации и изменение маршрутов после определения схемы ресурсов приложения.This support allows for starting with a basic routing configuration and modifying the routes after the app's resource layout is determined.

Маршрутизация использует маршруты (реализации интерфейса IRouter) в следующих целях:Routing uses routes (implementations of IRouter) to:

  • для сопоставления входящих запросов с обработчиками маршрутов;Map incoming requests to route handlers.
  • для создания URL-адресов, используемых в ответах.Generate the URLs used in responses.

По умолчанию приложение имеет одну коллекцию маршрутов.By default, an app has a single collection of routes. Когда запрос прибывает, маршруты в коллекции обрабатываются в порядке, в котором они существуют в коллекции.When a request arrives, the routes in the collection are processed in the order that they exist in the collection. Платформа пытается сопоставить URL-адрес входящего запроса с маршрутом в коллекции, вызывая метод RouteAsync для каждого маршрута в коллекции.The framework attempts to match an incoming request URL to a route in the collection by calling the RouteAsync method on each route in the collection. Отклик может использовать маршрутизацию для формирования URL-адресов (например, для перенаправления или ссылок) на основе сведений о маршруте, что позволяет избежать жесткого задания URL-адресов и упрощает поддержку.A response can use routing to generate URLs (for example, for redirection or links) based on route information and thus avoid hard-coded URLs, which helps maintainability.

Система маршрутизации обладает следующими характеристиками:The routing system has the following characteristics:

  • Синтаксис шаблона маршрута используется для определения маршрутов с помощью параметров размеченного маршрута.Route template syntax is used to define routes with tokenized route parameters.
  • Допускается конфигурация конечной точки в стандартном стиле и с атрибутами.Conventional-style and attribute-style endpoint configuration is permitted.
  • IRouteConstraint используется для определения того, содержит ли параметр URL-адреса допустимое значение для ограничения заданной конечной точки.IRouteConstraint is used to determine whether a URL parameter contains a valid value for a given endpoint constraint.
  • Модели приложения, такие как MVC и Razor Pages, регистрируют все свои маршруты, имеющие предсказуемую реализацию сценариев маршрутизации.App models, such as MVC/Razor Pages, register all of their routes, which have a predictable implementation of routing scenarios.
  • Отклик может использовать маршрутизацию для формирования URL-адресов (например, для перенаправления или ссылок) на основе сведений о маршруте, что позволяет избежать жесткого задания URL-адресов и упрощает поддержку.A response can use routing to generate URLs (for example, for redirection or links) based on route information and thus avoid hard-coded URLs, which helps maintainability.
  • Формирование URL-адреса основано на маршрутах, которые поддерживают произвольную расширяемость.URL generation is based on routes, which support arbitrary extensibility. IUrlHelper предоставляет методы для создания URL-адресов.IUrlHelper offers methods to build URLs.

Функция маршрутизации подключается к конвейеру ПО промежуточного слоя с помощью класса RouterMiddleware.Routing is connected to the middleware pipeline by the RouterMiddleware class. ASP.NET Core MVC добавляет функцию маршрутизации в конвейер ПО промежуточного слоя в процессе настройки и обрабатывает маршрутизацию в приложениях MVC и Razor Pages.ASP.NET Core MVC adds routing to the middleware pipeline as part of its configuration and handles routing in MVC and Razor Pages apps. Сведения об использовании маршрутизации в виде отдельного компонента см. в руководстве по использованию ПО промежуточного слоя маршрутизации.To learn how to use routing as a standalone component, see the Use Routing Middleware section.

Соответствие URL-адресовURL matching

Соответствие URL-адресов — это процесс, с помощью которого функция маршрутизации отправляет входящий запрос в обработчик.URL matching is the process by which routing dispatches an incoming request to a handler. Этот процесс основывается на данных в пути URL-адреса, но может быть расширен для учета любых данных в запросе.This process is based on data in the URL path but can be extended to consider any data in the request. Возможность отправки запросов в отдельные обработчики имеет первостепенное значение для масштабирования размера и сложности приложения.The ability to dispatch requests to separate handlers is key to scaling the size and complexity of an app.

Входящие запросы поступают в объект RouterMiddleware, который вызывает метод RouteAsync для каждого маршрута по порядку.Incoming requests enter the RouterMiddleware, which calls the RouteAsync method on each route in sequence. Экземпляр IRouter решает, следует ли обрабатывать запрос, присваивая свойству RouteContext.Handler значение RequestDelegate, отличное от NULL.The IRouter instance chooses whether to handle the request by setting the RouteContext.Handler to a non-null RequestDelegate. Если маршрут задает обработчик для запроса, обработка маршрутов останавливается и обработчик вызывается для обработки запроса.If a route sets a handler for the request, route processing stops, and the handler is invoked to process the request. Если обработчик маршрута для обработки запроса не найден, ПО промежуточного слоя передает запрос следующему ПО промежуточного слоя в конвейере запросов.If no route handler is found to process the request, the middleware hands the request off to the next middleware in the request pipeline.

Основные входные данные метода RouteAsync — это объект RouteContext.HttpContext, связанный с текущим запросом.The primary input to RouteAsync is the RouteContext.HttpContext associated with the current request. RouteContext.Handler и RouteContext.RouteData — это выходные значения, заданные после нахождения соответствующего маршрута.The RouteContext.Handler and RouteContext.RouteData are outputs set after a route is matched.

При нахождении соответствия, которое вызывает RouteAsync, свойствам RouteContext.RouteData также присваиваются значения с учетом уже выполненной на текущий момент обработки.A match that calls RouteAsync also sets the properties of the RouteContext.RouteData to appropriate values based on the request processing performed thus far.

RouteData.Values — это словарь значений маршрута, полученных из маршрута.RouteData.Values is a dictionary of route values produced from the route. Как правило, эти значения определяются путем разбивки URL-адреса на сегменты и могут использоваться для принятия входных данных пользователя или принятия дальнейших решений об отправке в приложении.These values are usually determined by tokenizing the URL and can be used to accept user input or to make further dispatching decisions inside the app.

RouteData.DataTokens — это контейнер свойств с дополнительными данными, связанными с соответствующим маршрутом.RouteData.DataTokens is a property bag of additional data related to the matched route. Свойства DataTokens обеспечивают связывание данных состояния с каждым маршрутом, что позволяет приложению принимать решения в зависимости от соответствующего маршрута.DataTokens are provided to support associating state data with each route so that the app can make decisions based on which route matched. Эти значения определяются разработчиком и никоим образом не влияют на поведение маршрутизации.These values are developer-defined and do not affect the behavior of routing in any way. Кроме того, значения, спрятанные в токенах RouteData.DataToken, могут быть любого типа в отличие от значений RouteData.Value, которые должны легко преобразовываться в строки и из строк.Additionally, values stashed in RouteData.DataTokens can be of any type, in contrast to RouteData.Values, which must be convertible to and from strings.

RouteData.Routers — это список маршрутов, которые участвовали в успешном сопоставлении с запросом.RouteData.Routers is a list of the routes that took part in successfully matching the request. Маршруты могут быть вложены друг в друга.Routes can be nested inside of one another. Свойство Routers отражает путь по логическому дереву маршрутов, который привел к совпадению.The Routers property reflects the path through the logical tree of routes that resulted in a match. Как правило, первый элемент в свойстве Routers — это коллекция маршрутов, используемая для формирования URL-адресов.Generally, the first item in Routers is the route collection and should be used for URL generation. Последний элемент в свойстве Routers — это соответствующий обработчик маршрутов.The last item in Routers is the route handler that matched.

Формирование URL-адресаURL generation

Формирование URL-адреса — это процесс создания пути URL-адреса функцией маршрутизации на основе набора значений маршрута.URL generation is the process by which routing can create a URL path based on a set of route values. Он обеспечивает логическое разделение обработчиков маршрутов и URL-адресов, которые получают к ним доступ.This allows for a logical separation between route handlers and the URLs that access them.

Формирование URL-адреса — это итеративный процесс, который начинается с того, что пользовательский код или код платформы вызывает метод GetVirtualPath коллекции маршрутов.URL generation follows a similar iterative process, but it starts with user or framework code calling into the GetVirtualPath method of the route collection. Метод GetVirtualPath каждого маршрута вызывается по очереди, пока не будет возвращен объект VirtualPathData, отличный от NULL.Each route has its GetVirtualPath method called in sequence until a non-null VirtualPathData is returned.

Основные входные параметры метода GetVirtualPath:The primary inputs to GetVirtualPath are:

Для определения возможности создания URL-адреса и включаемых значений в первую очередь используются значения, передаваемые в свойствах Values и AmbientValues.Routes primarily use the route values provided by Values and AmbientValues to decide whether it's possible to generate a URL and what values to include. AmbientValues — это набор значений маршрута, полученных в результате сопоставления текущего запроса.The AmbientValues are the set of route values that were produced from matching the current request. В свою очередь, Values — это значения, определяющие способ создания нужного URL-адреса для текущей операции.In contrast, Values are the route values that specify how to generate the desired URL for the current operation. HttpContext предоставляется в том случае, если маршруту необходимо получить службы или дополнительные данные, связанные с текущим контекстом.The HttpContext is provided in case a route should obtain services or additional data associated with the current context.

Совет

Можно рассматривать VirtualPathContext.Values как набор переопределений для VirtualPathContext.AmbientValues.Think of VirtualPathContext.Values as a set of overrides for the VirtualPathContext.AmbientValues. При формировании URL-адреса производится попытка повторного использования значений маршрута из текущего запроса для создания URL-адресов для ссылок с помощью того же маршрута или значений маршрута.URL generation attempts to reuse route values from the current request to generate URLs for links using the same route or route values.

Выходные данные метода GetVirtualPath содержатся в объекте VirtualPathData.The output of GetVirtualPath is a VirtualPathData. Объект VirtualPathData аналогичен RouteData.VirtualPathData is a parallel of RouteData. VirtualPathData содержит VirtualPath для выходного URL-адреса, а также ряд дополнительных свойств, которые должны быть заданы маршрутом.VirtualPathData contains the VirtualPath for the output URL and some additional properties that should be set by the route.

Свойство VirtualPathData.VirtualPath содержит виртуальный путь, создаваемый маршрутом.The VirtualPathData.VirtualPath property contains the virtual path produced by the route. В зависимости от ситуации путь может требовать дальнейшей обработки.Depending on your needs, you may need to process the path further. Чтобы представить созданный URL-адрес в формате HTML, добавьте в его начало базовый путь приложения.If you want to render the generated URL in HTML, prepend the base path of the app.

VirtualPathData.Router — это ссылка на маршрут, который успешно создал URL-адрес.The VirtualPathData.Router is a reference to the route that successfully generated the URL.

Свойства VirtualPathData.DataTokens представляют собой словарь дополнительных данных, связанных с маршрутом, который создал URL-адрес.The VirtualPathData.DataTokens properties is a dictionary of additional data related to the route that generated the URL. Это эквивалент объекта RouteData.DataTokens.This is the parallel of RouteData.DataTokens.

Создание маршрутовCreate routes

Маршрутизация предоставляет класс Route в качестве стандартной реализации IRouter.Routing provides the Route class as the standard implementation of IRouter. Класс Route использует синтаксис шаблона маршрута для определения шаблонов, которые будут сопоставляться с путем URL-адреса при вызове метода RouteAsync.Route uses the route template syntax to define patterns to match against the URL path when RouteAsync is called. При вызове метода GetVirtualPath объект Route будет использовать тот же шаблон маршрута для создания URL-адреса.Route uses the same route template to generate a URL when GetVirtualPath is called.

Большинство приложений создают маршруты, вызывая метод MapRoute или один из аналогичных методов расширения, определенных в интерфейсе IRouteBuilder.Most apps create routes by calling MapRoute or one of the similar extension methods defined on IRouteBuilder. Все методы расширения IRouteBuilder создают экземпляр Route и добавляют его в коллекцию маршрутов.Any of the IRouteBuilder extension methods create an instance of Route and add it to the route collection.

MapRoute не принимает параметр обработчика маршрутов.MapRoute doesn't accept a route handler parameter. MapRoute только добавляет маршруты, которые обрабатываются DefaultHandler.MapRoute only adds routes that are handled by the DefaultHandler. Обработчиком по умолчанию является IRouter, и обработчик может не обработать запрос.The default handler is an IRouter, and the handler might not handle the request. Например, ASP.NET Core MVC обычно настраивается в качестве обработчика по умолчанию, который обрабатывает только те запросы, которые соответствуют доступным контроллеру и действию.For example, ASP.NET Core MVC is typically configured as a default handler that only handles requests that match an available controller and action. Дополнительные сведения о маршрутизации в MVC см. в разделе Маршрутизация к действиям контроллера в ASP.NET Core.To learn more about routing in MVC, see Маршрутизация к действиям контроллера в ASP.NET Core.

В следующем коде приводится пример вызова MapRoute, используемого в типичном определении маршрута ASP.NET Core MVC:The following code example is an example of a MapRoute call used by a typical ASP.NET Core MVC route definition:

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

Этот шаблон соответствует пути URL-адреса и извлекает значения маршрута.This template matches a URL path and extracts the route values. Например, путь /Products/Details/17 создает следующие значения маршрута: { controller = Products, action = Details, id = 17 }.For example, the path /Products/Details/17 generates the following route values: { controller = Products, action = Details, id = 17 }.

Значения маршрута определяются с помощью разделения пути URL-адреса на сегменты и сопоставления каждого сегмента с именем параметра маршрута в шаблоне маршрута.Route values are determined by splitting the URL path into segments and matching each segment with the route parameter name in the route template. Параметры маршрута являются именованными.Route parameters are named. Параметры определяются путем заключения имени параметра в фигурные скобки { ... }.The parameters defined by enclosing the parameter name in braces { ... }.

Приведенный выше шаблон может также соответствовать пути URL-адреса /. В этом случае он предоставляет значения { controller = Home, action = Index }.The preceding template could also match the URL path / and produce the values { controller = Home, action = Index }. Связано это с тем, что параметры маршрута {controller} и {action} имеют значения по умолчанию, а параметр маршрута id является необязательным.This occurs because the {controller} and {action} route parameters have default values and the id route parameter is optional. Значение по умолчанию для параметра маршрута определяется с помощью знака равенства (=), за которым следует значение после имени параметра.An equals sign (=) followed by a value after the route parameter name defines a default value for the parameter. Вопросительный знак (?) после имени параметра маршрута определяет параметр как необязательный.A question mark (?) after the route parameter name defines an optional parameter.

Параметры маршрута со значением по умолчанию всегда предоставляют значения маршрута при совпадении маршрута.Route parameters with a default value always produce a route value when the route matches. Необязательные параметры не предоставляют значение маршрута, если нет соответствующего сегмента пути URL-адреса.Optional parameters don't produce a route value if there was no corresponding URL path segment. Подробное описание сценариев и синтаксиса шаблона маршрута см. в разделе Справочник по шаблонам маршрутов.See the Route template reference section for a thorough description of route template scenarios and syntax.

В следующем примере в определении параметра маршрута {id:int} определяется ограничение маршрута для параметра маршрута id:In the following example, the route parameter definition {id:int} defines a route constraint for the id route parameter:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id:int}");

Этот шаблон соответствует такому пути URL-адреса, как /Products/Details/17, но не /Products/Details/Apples.This template matches a URL path like /Products/Details/17 but not /Products/Details/Apples. Ограничения маршрута реализуют интерфейс IRouteConstraint и проверяют значения маршрута.Route constraints implement IRouteConstraint and inspect route values to verify them. В этом примере значение маршрута id должно иметь возможность преобразования в целое число.In this example, the route value id must be convertible to an integer. Более подробное описание ограничений маршрутов, предоставляемых платформой, см. в разделе Справочник по ограничениям маршрутов.See route-constraint-reference for an explanation of route constraints provided by the framework.

Дополнительные перегрузки MapRoute принимают значения для параметров constraints, dataTokens и defaults.Additional overloads of MapRoute accept values for constraints, dataTokens, and defaults. Типичное применение этих параметров состоит в передаче анонимно типизированного объекта, причем имена свойств анонимного типа соответствуют именам параметров маршрута.The typical usage of these parameters is to pass an anonymously typed object, where the property names of the anonymous type match route parameter names.

В следующих примерах MapRoute создаются эквивалентные маршруты:The following MapRoute examples create equivalent routes:

routes.MapRoute(
    name: "default_route",
    template: "{controller}/{action}/{id?}",
    defaults: new { controller = "Home", action = "Index" });

routes.MapRoute(
    name: "default_route",
    template: "{controller=Home}/{action=Index}/{id?}");

Совет

Встроенный синтаксис определения ограничений и значений по умолчанию может быть удобнее для простых маршрутов.The inline syntax for defining constraints and defaults can be convenient for simple routes. Однако некоторые сценарии, например токены данных, не поддерживаются встроенным синтаксисом.However, there are scenarios, such as data tokens, that aren't supported by inline syntax.

В следующем примере показано еще несколько сценариев:The following example demonstrates a few additional scenarios:

routes.MapRoute(
    name: "blog",
    template: "Blog/{*article}",
    defaults: new { controller = "Blog", action = "ReadArticle" });

Предыдущий шаблон соответствует такому пути URL-адреса, как /Blog/All-About-Routing/Introduction, и извлекает значения { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }.The preceding template matches a URL path like /Blog/All-About-Routing/Introduction and extracts the values { controller = Blog, action = ReadArticle, article = All-About-Routing/Introduction }. Значения маршрута по умолчанию для controller и action предоставляются маршрутом несмотря на то, что в шаблоне нет соответствующих параметров маршрута.The default route values for controller and action are produced by the route even though there are no corresponding route parameters in the template. Значения по умолчанию можно указать в шаблоне маршрута.Default values can be specified in the route template. Параметр маршрута article определяется как универсальный с помощью звездочки (*) перед его именем.The article route parameter is defined as a catch-all by the appearance of an asterisk (*) before the route parameter name. Универсальные параметры маршрута служат для фиксации оставшейся части пути URL-адреса, а также могут соответствовать пустой строке.Catch-all route parameters capture the remainder of the URL path and can also match the empty string.

В следующем примере добавляются ограничения маршрута и токены данных:The following example adds route constraints and data tokens:

routes.MapRoute(
    name: "us_english_products",
    template: "en-US/Products/{id}",
    defaults: new { controller = "Products", action = "Details" },
    constraints: new { id = new IntRouteConstraint() },
    dataTokens: new { locale = "en-US" });

Предыдущий шаблон будет соответствовать такому пути URL-адреса, как /en-US/Products/5, и будет извлекать значения { controller = Products, action = Details, id = 5 } и токены данных { locale = en-US }.The preceding template matches a URL path like /en-US/Products/5 and extracts the values { controller = Products, action = Details, id = 5 } and the data tokens { locale = en-US }.

Токены в окне "Локальные"

Формирование URL-адреса класса маршрутаRoute class URL generation

Класс Route может также формировать URL-адрес, объединяя набор значений маршрута с шаблоном маршрута.The Route class can also perform URL generation by combining a set of route values with its route template. С логической точки зрения, этот процесс обратен сопоставлению пути URL-адреса.This is logically the reverse process of matching the URL path.

Совет

Чтобы лучше понять процесс формирования URL-адреса, представьте себе, какой URL-адрес нужно создать, а затем подумайте, как шаблон маршрута будет сопоставляться с этим URL-адресом.To better understand URL generation, imagine what URL you want to generate and then think about how a route template would match that URL. Какие значения будут получены?What values would be produced? Примерно так производится формирование URL-адреса в классе Route.This is the rough equivalent of how URL generation works in the Route class.

В следующем примере используется общий маршрут по умолчанию ASP.NET Core MVC:The following example uses a general ASP.NET Core MVC default route:

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

При значениях маршрута { controller = Products, action = List } создается URL-адрес /Products/List.With the route values { controller = Products, action = List }, the URL /Products/List is generated. Значения маршрута заменяются на соответствующие параметры маршрута для образования пути URL-адреса.The route values are substituted for the corresponding route parameters to form the URL path. Так как id является необязательным параметром маршрута, URL-адрес успешно создается без значения для id.Since id is an optional route parameter, the URL is successfully generated without a value for id.

При значениях маршрута { controller = Home, action = Index } создается URL-адрес /.With the route values { controller = Home, action = Index }, the URL / is generated. Предоставленные значения маршрута соответствуют значениям по умолчанию, поэтому сегменты, соответствующие значениям по умолчанию, можно спокойно опустить.The provided route values match the default values, and the segments corresponding to the default values are safely omitted.

Оба созданных URL-адреса будут совершать круговой путь с таким же определением маршрута (/Home/Index и /) и предоставлять те же значения маршрута, которые использовались для формирования URL-адреса.Both URLs generated round-trip with the following route definition (/Home/Index and /) produce the same route values that were used to generate the URL.

Примечание

Приложение, использующее платформу ASP.NET Core MVC, должно создавать URL-адреса с помощью объекта UrlHelper, а не вызывать маршрутизацию напрямую.An app using ASP.NET Core MVC should use UrlHelper to generate URLs instead of calling into routing directly.

Дополнительные сведения о формировании URL-адресов см. в справочнике по формированию URL-адресов.For more information on URL generation, see the Url generation reference section.

Использование ПО промежуточного слоя маршрутизацииUse Routing Middleware

Ссылка на метапакет Microsoft.AspNetCore.App в файле проекта приложения.Reference the Microsoft.AspNetCore.App metapackage in the app's project file.

Добавьте маршрутизацию в контейнер службы в файле Startup.ConfigureServices:Add routing to the service container in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRouting();
}

Маршруты должны настраиваться в методе Startup.Configure.Routes must be configured in the Startup.Configure method. В этом примере приложения используются следующие API:The sample app uses the following APIs:

var trackPackageRouteHandler = new RouteHandler(context =>
{
    var routeValues = context.GetRouteData().Values;
    return context.Response.WriteAsync(
        $"Hello! Route values: {string.Join(", ", routeValues)}");
});

var routeBuilder = new RouteBuilder(app, trackPackageRouteHandler);

routeBuilder.MapRoute(
    "Track Package Route",
    "package/{operation:regex(^track|create$)}/{id:int}");

routeBuilder.MapGet("hello/{name}", context =>
{
    var name = context.GetRouteValue("name");
    // The route handler when HTTP GET "hello/<anything>" matches
    // To match HTTP GET "hello/<anything>/<anything>, 
    // use routeBuilder.MapGet("hello/{*name}"
    return context.Response.WriteAsync($"Hi, {name}!");
});

var routes = routeBuilder.Build();
app.UseRouter(routes);

В таблице ниже приведены ответы с данными универсальными кодами ресурсов (URI).The following table shows the responses with the given URIs.

URIURI ОтветResponse
/package/create/3 Hello!Hello! Значения маршрута: [operation, create], [id, 3]Route values: [operation, create], [id, 3]
/package/track/-3 Hello!Hello! Значения маршрута: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/-3/ Hello!Hello! Значения маршрута: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/ Запрос не дал результата, нет совпадений.The request falls through, no match.
GET /hello/Joe Hi, Joe!Hi, Joe!
POST /hello/Joe Запрос не дал результата, совпадение только с HTTP GET.The request falls through, matches HTTP GET only.
GET /hello/Joe/Smith Запрос не дал результата, нет совпадений.The request falls through, no match.

Если вы настраиваете один маршрут, вызовите UseRouter, передав экземпляр IRouter.If you're configuring a single route, call UseRouter passing in an IRouter instance. Использовать RouteBuilder не нужно.You won't need to use RouteBuilder.

Платформа предоставляет наборов методов расширения для создания маршрутов (RequestDelegateRouteBuilderExtensions):The framework provides a set of extension methods for creating routes (RequestDelegateRouteBuilderExtensions):

Некоторые из перечисленных методов, такие как MapGet, требуют RequestDelegate.Some of listed methods, such as MapGet, require a RequestDelegate. RequestDelegate используется в качестве обработчика маршрутов при совпадении маршрута.The RequestDelegate is used as the route handler when the route matches. Другие методы из этого семейства позволяют настраивать конвейер ПО промежуточного слоя, который будет использоваться в качестве обработчика маршрутов.Other methods in this family allow configuring a middleware pipeline for use as the route handler. Если метод Map* не принимает обработчик, например MapRoute, он будет использовать объект DefaultHandler.If the Map* method doesn't accept a handler, such as MapRoute, it uses the DefaultHandler.

Методы Map[Verb] используют ограничения, чтобы ограничить маршрут к HTTP-команде в имени метода.The Map[Verb] methods use constraints to limit the route to the HTTP Verb in the method name. Например, см. класс MapGet и тип MapVerb.For example, see MapGet and MapVerb.

Справочник по шаблону маршрутаRoute template reference

Токены в фигурных скобках ({ ... }) определяют параметры маршрута, которые будут привязаны при совпадении маршрута.Tokens within curly braces ({ ... }) define route parameters that are bound if the route is matched. В сегменте маршрута можно определить несколько параметров маршрута, но они должны разделяться литеральным значением.You can define more than one route parameter in a route segment, but they must be separated by a literal value. Например, {controller=Home}{action=Index} будет недопустимым маршрутом, так как между {controller} и {action} нет литерального значения.For example, {controller=Home}{action=Index} isn't a valid route, since there's no literal value between {controller} and {action}. Эти параметры маршрута должны иметь имена, и для них могут быть определены дополнительные атрибуты.These route parameters must have a name and may have additional attributes specified.

Весь текст, кроме параметров маршрута (например, {id}) и разделителя пути /, должен соответствовать тексту в URL-адресе.Literal text other than route parameters (for example, {id}) and the path separator / must match the text in the URL. Сопоставление текста производится без учета регистра на основе декодированного представления путь URL-адреса.Text matching is case-insensitive and based on the decoded representation of the URLs path. Для сопоставления с литеральным разделителем параметров маршрута ({ или }) разделитель следует экранировать путем повтора символа ({{ или }}).To match a literal route parameter delimiter ({ or }), escape the delimiter by repeating the character ({{ or }}).

Шаблоны URL-адресов, которые пытаются получить имя файла с необязательным расширением, имеют свои особенности.URL patterns that attempt to capture a file name with an optional file extension have additional considerations. Например, рассмотрим шаблон files/{filename}.{ext?}.For example, consider the template files/{filename}.{ext?}. Когда значения для filename и ext существуют, заполняются оба значения.When values for both filename and ext exist, both values are populated. Если в URL-адресе есть только значение для filename, маршрут совпадает, так как точка в конце (.) является необязательной.If only a value for filename exists in the URL, the route matches because the trailing period (.) is optional. Следующие URL-адреса соответствуют этому маршруту:The following URLs match this route:

  • /files/myFile.txt
  • /files/myFile

Вы можете использовать звездочку (*) в качестве префикса параметра маршрута для привязки к остальной части URI.You can use the asterisk (*) as a prefix to a route parameter to bind to the rest of the URI. Такой параметр называется универсальным.This is called a catch-all parameter. Например, blog/{*slug} соответствует любому URI, начинающемуся с сегмента /blog, за которым следует любое значение, присваиваемое в качестве значения маршрута slug.For example, blog/{*slug} matches any URI that starts with /blog and has any value following it, which is assigned to the slug route value. Универсальные параметры также могут соответствовать пустой строке.Catch-all parameters can also match the empty string.

Универсальный параметр экранирует соответствующие символы, если маршрут использует для формирования URL-адрес, включая символы разделителей пути (/).The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator (/) characters. Например, маршрут foo/{*path} со значениями маршрутов { path = "my/path" } формирует foo/my%2Fpath.For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Обратите внимание на экранированный знак косой черты.Note the escaped forward slash.

Параметры маршрута могут иметь значения по умолчанию. Они указываются после имени параметра и знака равенства (=).Route parameters may have default values designated by specifying the default value after the parameter name separated by an equals sign (=). Например, {controller=Home} определяет Home в качестве значения по умолчанию для controller.For example, {controller=Home} defines Home as the default value for controller. Значение по умолчанию используется, если для параметра нет значения в URL-адресе.The default value is used if no value is present in the URL for the parameter. Параметры маршрута могут быть необязательными (для этого необходимо добавить вопросительный знак (?) в конец имени параметра, например id?).Route parameters are made optional by appending a question mark (?) to the end of the parameter name, as in id?. Различие между необязательными параметрами и параметрами маршрута по умолчанию в том, что вторые всегда имеют значения — необязательный параметр имеет значение, только если оно предоставлено URL-адресом запроса.The difference between optional values and default route parameters is that a route parameter with a default value always produces a value—an optional parameter has a value only when a value is provided by the request URL.

Параметры маршрута могут иметь ограничения, которые должны соответствовать значению маршрута из URL-адреса.Route parameters may have constraints that must match the route value bound from the URL. Добавив двоеточие (:) и имя ограничения после имени параметра маршрута, можно указать встроенные ограничения для параметра маршрута.Adding a colon (:) and constraint name after the route parameter name specifies an inline constraint on a route parameter. Если для ограничения требуются аргументы, они указываются в скобках ((...)) после имени ограничения.If the constraint requires arguments, they're enclosed in parentheses ((...)) after the constraint name. Чтобы указать несколько встроенных ограничений, добавьте еще одно двоеточие (:) и имя ограничения.Multiple inline constraints can be specified by appending another colon (:) and constraint name.

Имя и аргументы ограничения передаются в службу IInlineConstraintResolver для создания экземпляра интерфейса IRouteConstraint, который будет использоваться при обработке URL-адреса.The constraint name and arguments are passed to the IInlineConstraintResolver service to create an instance of IRouteConstraint to use in URL processing. Например, в шаблоне маршрута blog/{article:minlength(10)} определяется ограничение minlength с аргументом 10.For example, the route template blog/{article:minlength(10)} specifies a minlength constraint with the argument 10. Более подробное описание ограничений маршрутов и список ограничений, предоставляемых платформой, см. в разделе Справочник по ограничениям маршрутов.For more information on route constraints and a list of the constraints provided by the framework, see the Route constraint reference section.

В приведенной ниже таблице показаны некоторые примеры шаблонов маршрутов и их поведение.The following table demonstrates example route templates and their behavior.

Шаблон маршрутаRoute Template Пример соответствующего URIExample Matching URI URI запроса…The request URI…
hello /hello Соответствует только одному пути /hello.Only matches the single path /hello.
{Page=Home} / Соответствует и задает для параметра Page значение Home.Matches and sets Page to Home.
{Page=Home} /Contact Соответствует и задает для параметра Page значение Contact.Matches and sets Page to Contact.
{controller}/{action}/{id?} /Products/List Сопоставляется с контроллером Products и действием List.Maps to the Products controller and List action.
{controller}/{action}/{id?} /Products/Details/123 Сопоставляется с контроллером Products и действием Details (id имеет значение 123).Maps to the Products controller and Details action (id set to 123).
{controller=Home}/{action=Index}/{id?} / Сопоставляется с контроллером Home и методом Index (id пропускается).Maps to the Home controller and Index method (id is ignored).

Использование шаблона — это, как правило, самый простой подход к маршрутизации.Using a template is generally the simplest approach to routing. Ограничения и значения по умолчанию также могут указываться вне шаблона маршрута.Constraints and defaults can also be specified outside the route template.

Совет

Чтобы увидеть, как встроенные реализации маршрутизации, такие как Route, сопоставляются с запросами, включите ведение журнала.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Зарезервированные имена маршрутизацииReserved routing names

Следующие ключевые слова являются зарезервированными именами и не могут использоваться как имена маршрутов или параметры:The following keywords are reserved names and can't be used as route names or parameters:

  • action
  • area
  • controller
  • handler
  • page

Справочник по ограничениям маршрутовRoute constraint reference

Ограничения маршрута применяются, когда найдено соответствие входящему URL-адресу и путь URL-адреса был разобран на значения маршрута.Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values. Как правило, ограничения маршрута служат для проверки значения маршрута, связанного посредством шаблона маршрута, и принятия решения касательно того, является ли значение приемлемым (да или нет).Route constraints generally inspect the route value associated via the route template and make a yes/no decision about whether or not the value is acceptable. Некоторые ограничения маршрута используют данные, не относящиеся к значению маршрута, для определения возможности маршрутизации запроса.Some route constraints use data outside the route value to consider whether the request can be routed. Например, HttpMethodRouteConstraint может принимать или отклонять запрос в зависимости от HTTP-команды.For example, the HttpMethodRouteConstraint can accept or reject a request based on its HTTP verb. Ограничения используются в маршрутизации запросов и создании ссылок.Constraints are used in routing requests and link generation.

Предупреждение

Не используйте ограничения для проверки входных данных.Don't use constraints for input validation. Если ограничения используются для проверки входных данных, недопустимые входные данные будут вызывать ошибку 404 (не найдено) вместо ошибки 400 (неверный запрос) с соответствующим сообщением.If constraints are used for input validation, invalid input results in a 404 - Not Found response instead of a 400 - Bad Request with an appropriate error message. Ограничения маршрутов следует использовать для разрешения неоднозначности похожих маршрутов, а не для проверки входных данных определенного маршрута.Route constraints are used to disambiguate similar routes, not to validate the inputs for a particular route.

В приведенной ниже таблице показаны примеры ограничения маршрутов и их ожидаемое поведение.The following table demonstrates example route constraints and their expected behavior.

ограничениеconstraint ПримерExample Примеры совпаденийExample Matches ПримечанияNotes
int {id:int} 123456789, -123456789123456789, -123456789 Соответствует любому целому числуMatches any integer
bool {active:bool} true, FALSEtrue, FALSE Соответствует true или false (без учета регистра)Matches true or false (case-insensitive)
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Соответствует допустимому значению DateTime (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid DateTime value (in the invariant culture - see warning)
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Соответствует допустимому значению decimal (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid decimal value (in the invariant culture - see warning)
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Соответствует допустимому значению double (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid double value (in the invariant culture - see warning)
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Соответствует допустимому значению float (для инвариантного языка и региональных параметров — см. предупреждение)Matches a valid float value (in the invariant culture - see warning)
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} Соответствует допустимому значению GuidMatches a valid Guid value
long {ticks:long} 123456789, -123456789123456789, -123456789 Соответствует допустимому значению longMatches a valid long value
minlength(value) {username:minlength(4)} Rick Строка должна содержать не менее 4 символовString must be at least 4 characters
maxlength(value) {filename:maxlength(8)} Richard Строка должна содержать не более 8 символовString must be no more than 8 characters
length(length) {filename:length(12)} somefile.txt Длина строки должна составлять ровно 12 символовString must be exactly 12 characters long
length(min,max) {filename:length(8,16)} somefile.txt Строка должна содержать от 8 до 16 символовString must be at least 8 and no more than 16 characters long
min(value) {age:min(18)} 19 Целочисленное значение не меньше 18Integer value must be at least 18
max(value) {age:max(120)} 91 Целочисленное значение не больше 120Integer value must be no more than 120
range(min,max) {age:range(18,120)} 91 Целочисленное значение от 18 до 120Integer value must be at least 18 but no more than 120
alpha {name:alpha} Rick Строка должна состоять из одной или нескольких букв (a-z, без учета регистра)String must consist of one or more alphabetical characters (a-z, case-insensitive)
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 Строка должна соответствовать регулярному выражению (см. советы по определению регулярного выражения)String must match the regular expression (see tips about defining a regular expression)
required {name:required} Rick Определяет обязательное наличие значения, не относящегося к параметру, во время формирования URL-адресаUsed to enforce that a non-parameter value is present during URL generation

К одному параметру может применяться несколько разделенных запятой ограничений.Multiple, colon-delimited constraints can be applied to a single parameter. Например, следующее ограничение ограничивает параметр целочисленным значением 1 или больше:For example, the following constraint restricts a parameter to an integer value of 1 or greater:

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { }

Предупреждение

Ограничения маршрута, которые проверяют URL-адрес и могут быть преобразованы в тип CLR (например, int или DateTime), всегда используют инвариантные язык и региональные параметры.Route constraints that verify the URL and are converted to a CLR type (such as int or DateTime) always use the invariant culture. Эти ограничения предполагают, что URL-адрес является нелокализуемым.These constraints assume that the URL is non-localizable. Предоставляемые платформой ограничения маршрутов не изменяют значения, хранящиеся в значениях маршрута.The framework-provided route constraints don't modify the values stored in route values. Все значения маршрута, переданные из URL-адреса, сохраняются как строки.All route values parsed from the URL are stored as strings. Например, ограничение float пытается преобразовать значение маршрута в число с плавающей запятой, но преобразованное значение служит только для проверки возможности такого преобразования.For example, the float constraint attempts to convert the route value to a float, but the converted value is used only to verify it can be converted to a float.

Регулярные выраженияRegular expressions

В платформе ASP.NET Core в конструктор регулярных выражений добавляются члены RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant.The ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant to the regular expression constructor. Описание этих членов см. в разделе RegexOptions.See RegexOptions for a description of these members.

В регулярных выражениях применяются разделители и токены, аналогичные используемым функцией маршрутизации и в языке C#.Regular expressions use delimiters and tokens similar to those used by Routing and the C# language. Токены регулярного выражения должны быть экранированы.Regular expression tokens must be escaped. Чтобы использовать регулярное выражение ^\d{3}-\d{2}-\d{4}$ при маршрутизации, выражение должно иметь символы \ (обратная косая черта), представленные в строке в виде символов \\ (двойная обратная косая черта) в исходном файле C#, для экранирования escape-символов строки \ (если не используются буквальные строковые литералы).To use the regular expression ^\d{3}-\d{2}-\d{4}$ in routing, the expression must have the \ (single backslash) characters provided in the string as \\ (double backslash) characters in the C# source file in order to escape the \ string escape character (unless using verbatim string literals). Чтобы экранировать символы разделения параметров маршрутизации ({, }, [, ]), используйте их дважды в выражении ({{, }, [[, ]]).To escape routing parameter delimiter characters ({, }, [, ]), double the characters in the expression ({{, }, [[, ]]). В следующей таблице показаны регулярные выражения и их экранированные варианты.The following table shows a regular expression and the escaped version.

Регулярное выражениеRegular Expression Экранированное регулярное выражениеEscaped Regular Expression
^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$ ^[[a-z]]{{2}}$

Регулярные выражения, используемые при маршрутизации, часто начинаются с символа карета (^) и соответствуют начальной позиции строки.Regular expressions used in routing often start with the caret (^) character and match starting position of the string. Выражения часто заканчиваются знаком доллара ($) и соответствуют концу строки.The expressions often end with the dollar sign ($) character and match end of the string. Благодаря символам ^ и $ регулярное выражение сопоставляется со всем значением параметра маршрута.The ^ and $ characters ensure that the regular expression match the entire route parameter value. Если символы ^ и $ отсутствуют, регулярное выражение сопоставляется с любой подстрокой внутри строки, что обычно нежелательно.Without the ^ and $ characters, the regular expression match any substring within the string, which is often undesirable. В следующей таблице представлен ряд примеров и объясняются причины соответствия или несоответствия.The following table provides examples and explains why they match or fail to match.

ВыражениеExpression СтрокаString СоответствиеMatch Добавление примечанийComment
[a-z]{2} hellohello ДаYes Соответствие подстрокиSubstring matches
[a-z]{2} 123abc456123abc456 ДаYes Соответствие подстрокиSubstring matches
[a-z]{2} mzmz ДаYes Соответствует выражениюMatches expression
[a-z]{2} MZMZ ДаYes Без учета регистраNot case sensitive
^[a-z]{2}$ hellohello НетNo См. замечания, касающиеся символов ^ и $, вышеSee ^ and $ above
^[a-z]{2}$ 123abc456123abc456 НетNo См. замечания, касающиеся символов ^ и $, вышеSee ^ and $ above

Дополнительные сведения о синтаксисе регулярных выражений см. в статье Регулярные выражения в .NET Framework.For more information on regular expression syntax, see .NET Framework Regular Expressions.

Чтобы ограничить возможные значения параметра набором известных значений, используйте регулярное выражение.To constrain a parameter to a known set of possible values, use a regular expression. Например, при использовании выражения {action:regex(^(list|get|create)$)} значение маршрута action будет соответствовать только list, get или create.For example, {action:regex(^(list|get|create)$)} only matches the action route value to list, get, or create. При передаче в словарь ограничений строка ^(list|get|create)$ будет эквивалентной.If passed into the constraints dictionary, the string ^(list|get|create)$ is equivalent. Ограничения, которые передаются в словарь ограничений (то есть не являются встроенными ограничениями шаблона) и не соответствуют одному из известных ограничений, также рассматриваются как регулярные выражения.Constraints that are passed in the constraints dictionary (not inline within a template) that don't match one of the known constraints are also treated as regular expressions.

Пользовательские ограничения маршрутовCustom Route Constraints

Помимо встроенных ограничений маршрутов пользовательские ограничения маршрутов можно создать путем внедрения интерфейса IRouteConstraint.In addition to the built-in route constraints, custom route constraints can be created by implementing the IRouteConstraint interface. Интерфейс IRouteConstraint содержит один метод, Match, который возвращает true, если ограничение удовлетворяется, и false — если нет.The IRouteConstraint interface contains a single method, Match, which returns true if the constraint is satisfied and false otherwise.

Чтобы применить пользовательский метод IRouteConstraint, тип ограничения маршрута необходимо зарегистрировать с помощью ConstraintMap приложения в контейнере службы приложения.To use a custom IRouteConstraint, the route constraint type must be registered with the app's ConstraintMap in the app's service container. Объект ConstraintMap — это словарь, который сопоставляет ключи ограничений пути с реализациями IRouteConstraint, которые проверяют эти ограничения.A ConstraintMap is a dictionary that maps route constraint keys to IRouteConstraint implementations that validate those constraints. ConstraintMap приложения можно преобразовать в Startup.ConfigureServices как часть вызова services.AddRouting или путем настройки RouteOptions непосредственно с помощью services.Configure<RouteOptions>.An app's ConstraintMap can be updated in Startup.ConfigureServices either as part of a services.AddRouting call or by configuring RouteOptions directly with services.Configure<RouteOptions>. Пример:For example:

services.AddRouting(options =>
{
    options.ConstraintMap.Add("customName", typeof(MyCustomConstraint));
});

Ограничения могут применяться к маршрутам обычным способом с использованием имени, указанного при регистрации типа ограничения.The constraint can then be applied to routes in the usual manner, using the name specified when registering the constraint type. Пример:For example:

[HttpGet("{id:customName}")]
public ActionResult<string> Get(string id)

Справочник по формированию URL-адресовURL generation reference

В приведенном ниже примере показано, как создать ссылку на маршрут с использованием словаря значений маршрута и коллекции RouteCollection.The following example shows how to generate a link to a route given a dictionary of route values and a RouteCollection.

app.Run(async (context) =>
{
    var dictionary = new RouteValueDictionary
    {
        { "operation", "create" },
        { "id", 123}
    };

    var vpc = new VirtualPathContext(context, null, dictionary, 
        "Track Package Route");
    var path = routes.GetVirtualPath(vpc).VirtualPath;

    context.Response.ContentType = "text/html";
    await context.Response.WriteAsync("Menu<hr/>");
    await context.Response.WriteAsync(
        $"<a href='{path}'>Create Package 123</a><br/>");
});

В результате приведенного выше примера создается VirtualPath со значением /package/create/123.The VirtualPath generated at the end of the preceding sample is /package/create/123. Словарь предоставляет значения маршрута operation и id шаблона "Отслеживание маршрута пакета", package/{operation}/{id}.The dictionary supplies the operation and id route values of the "Track Package Route" template, package/{operation}/{id}. Дополнительные сведения см. в примере кода в разделе Использование ПО промежуточного слоя маршрутизации или в примере приложения.For details, see the sample code in the Use Routing Middleware section or the sample app.

Второй параметр конструктора VirtualPathContext — это коллекция значений окружения.The second parameter to the VirtualPathContext constructor is a collection of ambient values. Значения окружения упрощают разработку, ограничивая число значений, которые необходимо указывать в определенном контексте запроса.Ambient values are convenient to use because they limit the number of values a developer must specify within a request context. Текущие значения маршрута текущего запроса считаются значениями окружения для создания ссылки.The current route values of the current request are considered ambient values for link generation. В приложении ASP.NET MVC в действии About контроллера HomeController не нужно задавать значение маршрута контроллера, указывающее на действие Index— используется значение окружения Home.In an ASP.NET Core MVC app's About action of the HomeController, you don't need to specify the controller route value to link to the Index action—the ambient value of Home is used.

Значения окружения, которые не соответствуют параметру, игнорируются.Ambient values that don't match a parameter are ignored. Значения окружения также не учитываются, когда явно указанное значение переопределяет значение окружения.Ambient values are also ignored when an explicitly provided value overrides the ambient value. Сопоставление выполняется слева направо в URL-адресе.Matching occurs from left to right in the URL.

Явно предоставленные значения, которые не соответствуют сегменту маршрута, добавляются в строку запроса.Values explicitly provided but that don't match a segment of the route are added to the query string. В приведенной ниже таблице показан результат использования шаблона маршрута {controller}/{action}/{id?}.The following table shows the result when using the route template {controller}/{action}/{id?}.

Значения окруженияAmbient Values Явные значенияExplicit Values РезультатResult
controller = "Home"controller = "Home" action = "About"action = "About" /Home/About
controller = "Home"controller = "Home" controller = "Order", action = "About"controller = "Order", action = "About" /Order/About
controller = "Home", color = "Red"controller = "Home", color = "Red" action = "About"action = "About" /Home/About
controller = "Home"controller = "Home" action = "About", color = "Red"action = "About", color = "Red" /Home/About?color=Red

Если маршрут имеет значение по умолчанию, которое не соответствует параметру, и это значение предоставлено явным образом, оно должно соответствовать значению по умолчанию:If a route has a default value that doesn't correspond to a parameter and that value is explicitly provided, it must match the default value:

routes.MapRoute("blog_route", "blog/{*slug}",
    defaults: new { controller = "Blog", action = "ReadPost" });

Для этого маршрута ссылка будет создана только в том случае, если предоставлены соответствующие значения для controller и action.Link generation only generates a link for this route when the matching values for controller and action are provided.

Сложные сегментыComplex segments

Сложные сегменты (например, [Route("/x{token}y")]) обрабатываются путем "нежадного" сопоставления литералов справа налево.Complex segments (for example [Route("/x{token}y")]) are processed by matching up literals from right to left in a non-greedy way. Подробные сведения о сопоставлении сложных сегментов см. в этом коде.See this code for a detailed explanation of how complex segments are matched. Пример кода не используется в ASP.NET Core, но он предоставляет подробное объяснение сложных сегментов.The code sample is not used by ASP.NET Core, but it provides a good explanation of complex segments.