Roteamento no ASP.NET CoreRouting in ASP.NET Core

Por Ryan Nowak, Kirk Larkine Rick AndersonBy Ryan Nowak, Kirk Larkin, and Rick Anderson

O roteamento é responsável por corresponder as solicitações HTTP de entrada e expedir essas solicitações aos pontos de extremidade executáveis do aplicativo.Routing is responsible for matching incoming HTTP requests and dispatching those requests to the app's executable endpoints. Os pontos de extremidade são as unidades de código executável de processamento de solicitação do aplicativo.Endpoints are the app's units of executable request-handling code. Os pontos de extremidade são definidos no aplicativo e configurados quando o aplicativo é iniciado.Endpoints are defined in the app and configured when the app starts. O processo de correspondência de ponto de extremidade pode extrair valores da URL da solicitação e fornecer esses valores para o processamento da solicitação.The endpoint matching process can extract values from the request's URL and provide those values for request processing. Usando informações de ponto de extremidade do aplicativo, o roteamento também é capaz de gerar URLs que são mapeadas para pontos de extremidade.Using endpoint information from the app, routing is also able to generate URLs that map to endpoints.

Os aplicativos podem configurar o roteamento usando:Apps can configure routing using:

  • ControladoresControllers
  • Razor PagesRazor Pages
  • SignalR
  • Serviços gRPCsgRPC Services
  • Middleware habilitado para ponto de extremidade, como verificações de integridade.Endpoint-enabled middleware such as Health Checks.
  • Delegados e lambdas registrados no roteamento.Delegates and lambdas registered with routing.

Este documento aborda os detalhes de baixo nível do roteamento de ASP.NET Core.This document covers low-level details of ASP.NET Core routing. Para obter informações sobre como configurar o roteamento:For information on configuring routing:

O sistema de roteamento de ponto de extremidade descrito neste documento se aplica ao ASP.NET Core 3,0 e posterior.The endpoint routing system described in this document applies to ASP.NET Core 3.0 and later. Para obter informações sobre o sistema de roteamento anterior baseado em IRouter , selecione a versão ASP.NET Core 2,1 usando uma das seguintes abordagens:For information on the previous routing system based on IRouter, select the ASP.NET Core 2.1 version using one of the following approaches:

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Os exemplos de download deste documento estão habilitados por uma Startup classe específica.The download samples for this document are enabled by a specific Startup class. Para executar um exemplo específico, modifique Program.cs para chamar a Startup classe desejada.To run a specific sample, modify Program.cs to call the desired Startup class.

Conceitos básicos sobre roteamentoRouting basics

Todos os modelos de ASP.NET Core incluem o roteamento no código gerado.All ASP.NET Core templates include routing in the generated code. O roteamento é registrado no pipeline de middleware no Startup.Configure .Routing is registered in the middleware pipeline in Startup.Configure.

O código a seguir mostra um exemplo básico de roteamento:The following code shows a basic example of routing:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    });
}

O roteamento usa um par de middleware, registrado por UseRouting e UseEndpoints :Routing uses a pair of middleware, registered by UseRouting and UseEndpoints:

  • UseRouting Adiciona correspondência de rota ao pipeline de middleware.UseRouting adds route matching to the middleware pipeline. Esse middleware analisa o conjunto de pontos de extremidade definidos no aplicativo e seleciona a melhor correspondência com base na solicitação.This middleware looks at the set of endpoints defined in the app, and selects the best match based on the request.
  • UseEndpoints Adiciona a execução de ponto de extremidade ao pipeline de middleware.UseEndpoints adds endpoint execution to the middleware pipeline. Ele executa o delegado associado ao ponto de extremidade selecionado.It runs the delegate associated with the selected endpoint.

O exemplo anterior inclui uma única rota para o ponto de extremidade de código usando o método MapGet :The preceding example includes a single route to code endpoint using the MapGet method:

  • Quando uma GET solicitação HTTP é enviada para a URL raiz / :When an HTTP GET request is sent to the root URL /:
    • O delegado de solicitação mostrado é executado.The request delegate shown executes.
    • Hello World! é gravado na resposta HTTP.Hello World! is written to the HTTP response. Por padrão, a URL raiz / é https://localhost:5001/ .By default, the root URL / is https://localhost:5001/.
  • Se o método de solicitação não for GET ou a URL raiz não for / , nenhuma correspondência de rota será retornada e um http 404 será retornado.If the request method is not GET or the root URL is not /, no route matches and an HTTP 404 is returned.

Ponto de extremidadeEndpoint

O MapGet método é usado para definir um ponto de extremidade.The MapGet method is used to define an endpoint. Um ponto de extremidade é algo que pode ser:An endpoint is something that can be:

  • Selecionado, correspondendo à URL e ao método HTTP.Selected, by matching the URL and HTTP method.
  • Executado, executando o delegado.Executed, by running the delegate.

Os pontos de extremidade que podem ser correspondidos e executados pelo aplicativo são configurados no UseEndpoints .Endpoints that can be matched and executed by the app are configured in UseEndpoints. Por exemplo,,, MapGet MapPost e métodos semelhantes conectam delegados de solicitação ao sistema de roteamento.For example, MapGet, MapPost, and similar methods connect request delegates to the routing system. Métodos adicionais podem ser usados para conectar ASP.NET Core recursos do Framework ao sistema de roteamento:Additional methods can be used to connect ASP.NET Core framework features to the routing system:

O exemplo a seguir mostra o roteamento com um modelo de rota mais sofisticado:The following example shows routing with a more sophisticated route template:

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("/hello/{name:alpha}", async context =>
    {
        var name = context.Request.RouteValues["name"];
        await context.Response.WriteAsync($"Hello {name}!");
    });
});

A cadeia de caracteres /hello/{name:alpha} é um modelo de rota.The string /hello/{name:alpha} is a route template. Ele é usado para configurar como o ponto de extremidade é correspondido.It is used to configure how the endpoint is matched. Nesse caso, o modelo corresponde a:In this case, the template matches:

  • Uma URL como /hello/RyanA URL like /hello/Ryan
  • Qualquer caminho de URL que comece com /hello/ seguido por uma sequência de caracteres alfabéticos.Any URL path that begins with /hello/ followed by a sequence of alphabetic characters. :alpha aplica uma restrição de rota que corresponde apenas a caracteres alfabéticos.:alpha applies a route constraint that matches only alphabetic characters. As restrições de rota são explicadas posteriormente neste documento.Route constraints are explained later in this document.

O segundo segmento do caminho da URL, {name:alpha} :The second segment of the URL path, {name:alpha}:

O sistema de roteamento de ponto de extremidade descrito neste documento é novo a partir de ASP.NET Core 3,0.The endpoint routing system described in this document is new as of ASP.NET Core 3.0. No entanto, todas as versões do ASP.NET Core dão suporte ao mesmo conjunto de recursos de modelo de rota e restrições de rota.However, all versions of ASP.NET Core support the same set of route template features and route constraints.

O exemplo a seguir mostra o roteamento com verificações de integridade e autorização:The following example shows routing with health checks and authorization:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    // Matches request to an endpoint.
    app.UseRouting();

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

    // Execute the matched endpoint.
    app.UseEndpoints(endpoints =>
    {
        // Configure the Health Check endpoint and require an authorized user.
        endpoints.MapHealthChecks("/healthz").RequireAuthorization();

        // Configure another endpoint, no authorization requirements.
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    });
}

Se você quiser ver os comentários de código traduzidos para idiomas diferentes do inglês, informe-nos sobre esse problema de discussão do GitHub.If you would like to see code comments translated to languages other than English, let us know in this GitHub discussion issue.

O exemplo anterior demonstra como:The preceding example demonstrates how:

  • O middleware de autorização pode ser usado com o roteamento.The authorization middleware can be used with routing.
  • Os pontos de extremidade podem ser usados para configurar o comportamento de autorização.Endpoints can be used to configure authorization behavior.

A MapHealthChecks chamada adiciona um ponto de extremidade de verificação de integridade.The MapHealthChecks call adds a health check endpoint. O encadeamento RequireAuthorization para essa chamada anexa uma política de autorização ao ponto de extremidade.Chaining RequireAuthorization on to this call attaches an authorization policy to the endpoint.

Chamar UseAuthentication e UseAuthorization Adicionar o middleware de autenticação e autorização.Calling UseAuthentication and UseAuthorization adds the authentication and authorization middleware. Esses middlewares são colocados entre UseRouting e UseEndpoints para que eles possam:These middleware are placed between UseRouting and UseEndpoints so that they can:

  • Veja qual ponto de extremidade foi selecionado por UseRouting .See which endpoint was selected by UseRouting.
  • Aplique uma política de autorização antes de UseEndpoints expedir para o ponto de extremidade.Apply an authorization policy before UseEndpoints dispatches to the endpoint.

Metadados do ponto de extremidadeEndpoint metadata

No exemplo anterior, há dois pontos de extremidade, mas somente o ponto de verificação de integridade tem uma política de autorização anexada.In the preceding example, there are two endpoints, but only the health check endpoint has an authorization policy attached. Se a solicitação corresponder ao ponto de extremidade de verificação de integridade, /healthz uma verificação de autorização será executada.If the request matches the health check endpoint, /healthz, an authorization check is performed. Isso demonstra que os pontos de extremidade podem ter dados adicionais anexados a eles.This demonstrates that endpoints can have extra data attached to them. Esses dados adicionais são chamados de metadados de ponto de extremidade:This extra data is called endpoint metadata :

  • Os metadados podem ser processados pelo middleware com reconhecimento de roteamento.The metadata can be processed by routing-aware middleware.
  • Os metadados podem ser de qualquer tipo .NET.The metadata can be of any .NET type.

Conceitos de roteamentoRouting concepts

O sistema de roteamento baseia-se na parte superior do pipeline de middleware adicionando o poderoso conceito de ponto de extremidade .The routing system builds on top of the middleware pipeline by adding the powerful endpoint concept. Os pontos de extremidade representam unidades da funcionalidade do aplicativo que são diferentes entre si em termos de roteamento, autorização e qualquer número de sistemas de ASP.NET Core.Endpoints represent units of the app's functionality that are distinct from each other in terms of routing, authorization, and any number of ASP.NET Core's systems.

Definição de ponto de extremidade ASP.NET CoreASP.NET Core endpoint definition

Um ponto de extremidade ASP.NET Core é:An ASP.NET Core endpoint is:

O código a seguir mostra como recuperar e inspecionar o ponto de extremidade que corresponde à solicitação atual:The following code shows how to retrieve and inspect the endpoint matching the current request:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.Use(next => context =>
    {
        var endpoint = context.GetEndpoint();
        if (endpoint is null)
        {
            return Task.CompletedTask;
        }
        
        Console.WriteLine($"Endpoint: {endpoint.DisplayName}");

        if (endpoint is RouteEndpoint routeEndpoint)
        {
            Console.WriteLine("Endpoint has route pattern: " +
                routeEndpoint.RoutePattern.RawText);
        }

        foreach (var metadata in endpoint.Metadata)
        {
            Console.WriteLine($"Endpoint has metadata: {metadata}");
        }

        return Task.CompletedTask;
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    });
}

O ponto de extremidade, se selecionado, pode ser recuperado do HttpContext .The endpoint, if selected, can be retrieved from the HttpContext. Suas propriedades podem ser inspecionadas.Its properties can be inspected. Os objetos de ponto de extremidade são imutáveis e não podem ser modificados após a criação.Endpoint objects are immutable and cannot be modified after creation. O tipo de ponto de extremidade mais comum é um RouteEndpoint .The most common type of endpoint is a RouteEndpoint. RouteEndpoint inclui informações que permitem que ele seja selecionado pelo sistema de roteamento.RouteEndpoint includes information that allows it to be to selected by the routing system.

No código anterior, aplicativo. Use configura um middlewareembutido.In the preceding code, app.Use configures an in-line middleware.

O código a seguir mostra que, dependendo de onde app.Use é chamado no pipeline, pode não haver um ponto de extremidade:The following code shows that, depending on where app.Use is called in the pipeline, there may not be an endpoint:

// Location 1: before routing runs, endpoint is always null here
app.Use(next => context =>
{
    Console.WriteLine($"1. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    return next(context);
});

app.UseRouting();

// Location 2: after routing runs, endpoint will be non-null if routing found a match
app.Use(next => context =>
{
    Console.WriteLine($"2. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    return next(context);
});

app.UseEndpoints(endpoints =>
{
    // Location 3: runs when this endpoint matches
    endpoints.MapGet("/", context =>
    {
        Console.WriteLine(
            $"3. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
        return Task.CompletedTask;
    }).WithDisplayName("Hello");
});

// Location 4: runs after UseEndpoints - will only run if there was no match
app.Use(next => context =>
{
    Console.WriteLine($"4. Endpoint: {context.GetEndpoint()?.DisplayName ?? "(null)"}");
    return next(context);
});

O exemplo anterior adiciona Console.WriteLine instruções que exibem se um ponto de extremidade foi selecionado ou não.This preceding sample adds Console.WriteLine statements that display whether or not an endpoint has been selected. Para maior clareza, o exemplo atribui um nome de exibição ao ponto de / extremidade fornecido.For clarity, the sample assigns a display name to the provided / endpoint.

Executar esse código com uma URL de / exibe:Running this code with a URL of / displays:

1. Endpoint: (null)
2. Endpoint: Hello
3. Endpoint: Hello

A execução desse código com qualquer outra URL é exibida:Running this code with any other URL displays:

1. Endpoint: (null)
2. Endpoint: (null)
4. Endpoint: (null)

Essa saída demonstra que:This output demonstrates that:

  • O ponto de extremidade é sempre nulo antes de UseRouting ser chamado.The endpoint is always null before UseRouting is called.
  • Se uma correspondência for encontrada, o ponto de extremidade será não nulo entre UseRouting e UseEndpoints .If a match is found, the endpoint is non-null between UseRouting and UseEndpoints.
  • O UseEndpoints middleware é terminal quando uma correspondência é encontrada.The UseEndpoints middleware is terminal when a match is found. O middleware de terminal é definido mais adiante neste documento.Terminal middleware is defined later in this document.
  • O middleware após UseEndpoints executar somente quando nenhuma correspondência for encontrada.The middleware after UseEndpoints execute only when no match is found.

O UseRouting middleware usa o método SetEndPoint para anexar o ponto de extremidade ao contexto atual.The UseRouting middleware uses the SetEndpoint method to attach the endpoint to the current context. É possível substituir o UseRouting middleware por uma lógica personalizada e ainda obter os benefícios de usar pontos de extremidade.It's possible to replace the UseRouting middleware with custom logic and still get the benefits of using endpoints. Os pontos de extremidade são um primitivo de baixo nível, como middleware, e não são acoplados à implementação de roteamento.Endpoints are a low-level primitive like middleware, and aren't coupled to the routing implementation. A maioria dos aplicativos não precisa substituir UseRouting pela lógica personalizada.Most apps don't need to replace UseRouting with custom logic.

O UseEndpoints middleware foi projetado para ser usado em conjunto com o UseRouting middleware.The UseEndpoints middleware is designed to be used in tandem with the UseRouting middleware. A lógica principal para executar um ponto de extremidade não é complicada.The core logic to execute an endpoint isn't complicated. Use GetEndpoint para recuperar o ponto de extremidade e, em seguida, invoque sua RequestDelegate propriedade.Use GetEndpoint to retrieve the endpoint, and then invoke its RequestDelegate property.

O código a seguir demonstra como o middleware pode influenciar ou reagir ao roteamento:The following code demonstrates how middleware can influence or react to routing:

public class IntegratedMiddlewareStartup
{ 
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // Location 1: Before routing runs. Can influence request before routing runs.
        app.UseHttpMethodOverride();

        app.UseRouting();

        // Location 2: After routing runs. Middleware can match based on metadata.
        app.Use(next => context =>
        {
            var endpoint = context.GetEndpoint();
            if (endpoint?.Metadata.GetMetadata<AuditPolicyAttribute>()?.NeedsAudit
                                                                            == true)
            {
                Console.WriteLine($"ACCESS TO SENSITIVE DATA AT: {DateTime.UtcNow}");
            }

            return next(context);
        });

        app.UseEndpoints(endpoints =>
        {         
            endpoints.MapGet("/", async context =>
            {
                await context.Response.WriteAsync("Hello world!");
            });

            // Using metadata to configure the audit policy.
            endpoints.MapGet("/sensitive", async context =>
            {
                await context.Response.WriteAsync("sensitive data");
            })
            .WithMetadata(new AuditPolicyAttribute(needsAudit: true));
        });

    } 
}

public class AuditPolicyAttribute : Attribute
{
    public AuditPolicyAttribute(bool needsAudit)
    {
        NeedsAudit = needsAudit;
    }

    public bool NeedsAudit { get; }
}

O exemplo anterior demonstra dois conceitos importantes:The preceding example demonstrates two important concepts:

  • O middleware pode ser executado antes UseRouting de modificar os dados nos quais o roteamento Opera.Middleware can run before UseRouting to modify the data that routing operates upon.
  • O middleware pode ser executado entre UseRouting e UseEndpoints para processar os resultados do roteamento antes da execução do ponto de extremidade.Middleware can run between UseRouting and UseEndpoints to process the results of routing before the endpoint is executed.
    • Middleware que é executado entre UseRouting e UseEndpoints :Middleware that runs between UseRouting and UseEndpoints:
      • Geralmente inspeciona os metadados para entender os pontos de extremidade.Usually inspects metadata to understand the endpoints.
      • Geralmente toma decisões de segurança, como feito pelo UseAuthorization e pelo UseCors .Often makes security decisions, as done by UseAuthorization and UseCors.
    • A combinação de middleware e metadados permite configurar políticas por ponto de extremidade.The combination of middleware and metadata allows configuring policies per-endpoint.

O código anterior mostra um exemplo de um middleware personalizado que dá suporte a políticas por ponto de extremidade.The preceding code shows an example of a custom middleware that supports per-endpoint policies. O middleware grava um log de auditoria de acesso a dados confidenciais no console.The middleware writes an audit log of access to sensitive data to the console. O middleware pode ser configurado para auditar um ponto de extremidade com os AuditPolicyAttribute metadados.The middleware can be configured to audit an endpoint with the AuditPolicyAttribute metadata. Este exemplo demonstra um padrão de aceitação em que somente os pontos de extremidade marcados como confidenciais são auditados.This sample demonstrates an opt-in pattern where only endpoints that are marked as sensitive are audited. É possível definir essa lógica na ordem inversa, auditar tudo que não está marcado como seguro, por exemplo.It's possible to define this logic in reverse, auditing everything that isn't marked as safe, for example. O sistema de metadados do ponto de extremidade é flexível.The endpoint metadata system is flexible. Essa lógica poderia ser projetada de qualquer forma adequada ao caso de uso.This logic could be designed in whatever way suits the use case.

O código de exemplo anterior destina-se a demonstrar os conceitos básicos dos pontos de extremidade.The preceding sample code is intended to demonstrate the basic concepts of endpoints. O exemplo não se destina ao uso em produção.The sample is not intended for production use. Uma versão mais completa de um middleware de log de auditoria seria:A more complete version of an audit log middleware would:

  • Faça logon em um arquivo ou banco de dados.Log to a file or database.
  • Inclua detalhes como o usuário, o endereço IP, o nome do ponto de extremidade confidencial e muito mais.Include details such as the user, IP address, name of the sensitive endpoint, and more.

Os metadados da diretiva de auditoria AuditPolicyAttribute são definidos como um Attribute para uso mais fácil com estruturas baseadas em classe, como controladores e SignalR .The audit policy metadata AuditPolicyAttribute is defined as an Attribute for easier use with class-based frameworks such as controllers and SignalR. Ao usar rota para código :When using route to code :

  • Os metadados são anexados a uma API do Builder.Metadata is attached with a builder API.
  • As estruturas baseadas em classe incluem todos os atributos no método e na classe correspondentes ao criar pontos de extremidade.Class-based frameworks include all attributes on the corresponding method and class when creating endpoints.

As práticas recomendadas para tipos de metadados são defini-las como interfaces ou atributos.The best practices for metadata types are to define them either as interfaces or attributes. Interfaces e atributos permitem reutilização de código.Interfaces and attributes allow code reuse. O sistema de metadados é flexível e não impõe nenhuma limitação.The metadata system is flexible and doesn't impose any limitations.

Comparando um middleware e roteamento de terminalComparing a terminal middleware and routing

O exemplo de código a seguir contrasta usando o middleware com o uso de roteamento:The following code sample contrasts using middleware with using routing:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    // Approach 1: Writing a terminal middleware.
    app.Use(next => async context =>
    {
        if (context.Request.Path == "/")
        {
            await context.Response.WriteAsync("Hello terminal middleware!");
            return;
        }

        await next(context);
    });

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        // Approach 2: Using routing.
        endpoints.MapGet("/Movie", async context =>
        {
            await context.Response.WriteAsync("Hello routing!");
        });
    });
}

O estilo de middleware mostrado com o Approach 1: é middleware de terminal.The style of middleware shown with Approach 1: is terminal middleware. Ele é chamado de middleware de terminal porque faz uma operação de correspondência:It's called terminal middleware because it does a matching operation:

  • A operação de correspondência no exemplo anterior é Path == "/" para o middleware e Path == "/Movie" para o roteamento.The matching operation in the preceding sample is Path == "/" for the middleware and Path == "/Movie" for routing.
  • Quando uma correspondência é bem-sucedida, ela executa algumas funcionalidades e retorna, em vez de invocar o next middleware.When a match is successful, it executes some functionality and returns, rather than invoking the next middleware.

Ele é chamado de middleware de terminal porque encerra a pesquisa, executa algumas funcionalidades e, em seguida, retorna.It's called terminal middleware because it terminates the search, executes some functionality, and then returns.

Comparando um middleware e roteamento de terminal:Comparing a terminal middleware and routing:

  • Ambas as abordagens permitem encerrar o pipeline de processamento:Both approaches allow terminating the processing pipeline:
    • O middleware encerra o pipeline retornando em vez de invocar next .Middleware terminates the pipeline by returning rather than invoking next.
    • Os pontos de extremidade são sempre terminal.Endpoints are always terminal.
  • O middleware de terminal permite posicionar o middleware em um local arbitrário no pipeline:Terminal middleware allows positioning the middleware at an arbitrary place in the pipeline:
    • Os pontos de extremidade são executados na posição de UseEndpoints .Endpoints execute at the position of UseEndpoints.
  • O middleware de terminal permite que um código arbitrário determine quando o middleware corresponde a:Terminal middleware allows arbitrary code to determine when the middleware matches:
    • O código de correspondência de rota personalizado pode ser detalhado e difícil de escrever corretamente.Custom route matching code can be verbose and difficult to write correctly.
    • O roteamento fornece soluções diretas para aplicativos típicos.Routing provides straightforward solutions for typical apps. A maioria dos aplicativos não requer código de correspondência de rota personalizado.Most apps don't require custom route matching code.
  • Interface de pontos de extremidade com middleware, como UseAuthorization e UseCors .Endpoints interface with middleware such as UseAuthorization and UseCors.
    • Usar um middleware de terminal com UseAuthorization ou UseCors requer a interface manual com o sistema de autorização.Using a terminal middleware with UseAuthorization or UseCors requires manual interfacing with the authorization system.

Um ponto de extremidade define ambos:An endpoint defines both:

  • Um delegado para processar solicitações.A delegate to process requests.
  • Uma coleção de metadados arbitrários.A collection of arbitrary metadata. Os metadados são usados para implementar preocupações abrangentes com base em políticas e configurações anexadas a cada ponto de extremidade.The metadata is used to implement cross-cutting concerns based on policies and configuration attached to each endpoint.

O middleware de terminal pode ser uma ferramenta eficaz, mas pode exigir:Terminal middleware can be an effective tool, but can require:

  • Uma quantidade significativa de codificação e teste.A significant amount of coding and testing.
  • Integração manual com outros sistemas para atingir o nível desejado de flexibilidade.Manual integration with other systems to achieve the desired level of flexibility.

Considere a integração com o roteamento antes de gravar um middleware de terminal.Consider integrating with routing before writing a terminal middleware.

Middleware de terminal existente que se integra ao MAP ou que MapWhen normalmente pode ser transformado em um ponto de extremidade com reconhecimento de roteamento.Existing terminal middleware that integrates with Map or MapWhen can usually be turned into a routing aware endpoint. MapHealthChecks demonstra o padrão para o roteador-Ware:MapHealthChecks demonstrates the pattern for router-ware:

O código a seguir mostra o uso de MapHealthChecks:The following code shows use of MapHealthChecks:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    // Matches request to an endpoint.
    app.UseRouting();

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

    // Execute the matched endpoint.
    app.UseEndpoints(endpoints =>
    {
        // Configure the Health Check endpoint and require an authorized user.
        endpoints.MapHealthChecks("/healthz").RequireAuthorization();

        // Configure another endpoint, no authorization requirements.
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Hello World!");
        });
    });
}

O exemplo anterior mostra por que retornar o objeto Builder é importante.The preceding sample shows why returning the builder object is important. Retornar o objeto Builder permite que o desenvolvedor do aplicativo Configure políticas como autorização para o ponto de extremidade.Returning the builder object allows the app developer to configure policies such as authorization for the endpoint. Neste exemplo, o middleware de verificações de integridade não tem integração direta com o sistema de autorização.In this example, the health checks middleware has no direct integration with the authorization system.

O sistema de metadados foi criado em resposta aos problemas encontrados por autores de extensibilidade usando o middleware de terminal.The metadata system was created in response to the problems encountered by extensibility authors using terminal middleware. É problemático para cada middleware implementar sua própria integração com o sistema de autorização.It's problematic for each middleware to implement its own integration with the authorization system.

Correspondência de URLURL matching

  • É o processo pelo qual o roteamento corresponde a uma solicitação de entrada para um ponto de extremidade.Is the process by which routing matches an incoming request to an endpoint.
  • Baseia-se nos dados no caminho da URL e nos cabeçalhos.Is based on data in the URL path and headers.
  • Pode ser estendido para considerar todos os dados na solicitação.Can be extended to consider any data in the request.

Quando um middleware de roteamento é executado, ele define um Endpoint e os valores de rota para um recurso de solicitação no HttpContext da solicitação atual:When a routing middleware executes, it sets an Endpoint and route values to a request feature on the HttpContext from the current request:

  • Chamar HttpContext. GetEndPoint Obtém o ponto de extremidade.Calling HttpContext.GetEndpoint gets the endpoint.
  • HttpRequest.RouteValues obtém a coleção de valores de rota.HttpRequest.RouteValues gets the collection of route values.

O middleware em execução após o middleware de roteamento pode inspecionar o ponto de extremidade e tomar medidas.Middleware running after the routing middleware can inspect the endpoint and take action. Por exemplo, um middleware de autorização pode interrogar a coleção de metadados do ponto de extremidade para uma política de autorização.For example, an authorization middleware can interrogate the endpoint's metadata collection for an authorization policy. Depois que todos os middlewares no pipeline de processamento da solicitação forem executados, o representante do ponto de extremidade selecionado será invocado.After all of the middleware in the request processing pipeline is executed, the selected endpoint's delegate is invoked.

O sistema de roteamento no roteamento de ponto de extremidade é responsável por todas as decisões de expedição.The routing system in endpoint routing is responsible for all dispatching decisions. Como o middleware aplica políticas com base no ponto de extremidade selecionado, é importante que:Because the middleware applies policies based on the selected endpoint, it's important that:

  • Qualquer decisão que possa afetar a expedição ou a aplicação de diretivas de segurança é feita dentro do sistema de roteamento.Any decision that can affect dispatching or the application of security policies is made inside the routing system.

Aviso

Para compatibilidade com versões anteriores, quando um delegado de ponto de extremidade de controlador ou de Razor páginas é executado, as propriedades de RouteContext. RouteData são definidas com os valores apropriados com base no processamento de solicitação realizado até o momento.For backwards-compatibility, when a Controller or Razor Pages endpoint delegate is executed, the properties of RouteContext.RouteData are set to appropriate values based on the request processing performed thus far.

O RouteContext tipo será marcado como obsoleto em uma versão futura:The RouteContext type will be marked obsolete in a future release:

  • Migrar RouteData.Values para o HttpRequest.RouteValues .Migrate RouteData.Values to HttpRequest.RouteValues.
  • Migre RouteData.DataTokens para recuperar IDataTokensMetadata dos metadados do ponto de extremidade.Migrate RouteData.DataTokens to retrieve IDataTokensMetadata from the endpoint metadata.

A correspondência de URL opera em um conjunto configurável de fases.URL matching operates in a configurable set of phases. Em cada fase, a saída é um conjunto de correspondências.In each phase, the output is a set of matches. O conjunto de correspondências pode ser restringido ainda mais pela próxima fase.The set of matches can be narrowed down further by the next phase. A implementação de roteamento não garante uma ordem de processamento para pontos de extremidade correspondentes.The routing implementation does not guarantee a processing order for matching endpoints. Todas as possíveis correspondências são processadas de uma vez.All possible matches are processed at once. As fases de correspondência de URL ocorrem na seguinte ordem.The URL matching phases occur in the following order. ASP.NET Core:ASP.NET Core:

  1. Processa o caminho da URL em relação ao conjunto de pontos de extremidade e seus modelos de rota, coletando todas as correspondências.Processes the URL path against the set of endpoints and their route templates, collecting all of the matches.
  2. Usa a lista anterior e remove as correspondências que falham com as restrições de rota aplicadas.Takes the preceding list and removes matches that fail with route constraints applied.
  3. Usa a lista anterior e remove as correspondências que falham no conjunto de instâncias de MatcherPolicy .Takes the preceding list and removes matches that fail the set of MatcherPolicy instances.
  4. Usa o EndpointSelector para tomar uma decisão final da lista anterior.Uses the EndpointSelector to make a final decision from the preceding list.

A lista de pontos de extremidade é priorizada de acordo com:The list of endpoints is prioritized according to:

Todos os pontos de extremidade correspondentes são processados em cada fase até que o EndpointSelector seja atingido.All matching endpoints are processed in each phase until the EndpointSelector is reached. A EndpointSelector é a fase final.The EndpointSelector is the final phase. Ele escolhe o ponto de extremidade de prioridade mais alta das correspondências como a melhor correspondência.It chooses the highest priority endpoint from the matches as the best match. Se houver outras correspondências com a mesma prioridade que a melhor correspondência, uma exceção de correspondência ambígua será gerada.If there are other matches with the same priority as the best match, an ambiguous match exception is thrown.

A precedência de rota é calculada com base em um modelo de rota mais específico que tem uma prioridade mais alta.The route precedence is computed based on a more specific route template being given a higher priority. Por exemplo, considere os modelos /hello e /{message} :For example, consider the templates /hello and /{message}:

  • Ambos correspondem ao caminho da URL /hello .Both match the URL path /hello.
  • /hello é mais específico e, portanto, prioridade mais alta./hello is more specific and therefore higher priority.

Em geral, a precedência de rota faz um bom trabalho de escolher a melhor correspondência para os tipos de esquemas de URL usados na prática.In general, route precedence does a good job of choosing the best match for the kinds of URL schemes used in practice. Use Order somente quando necessário para evitar uma ambiguidade.Use Order only when necessary to avoid an ambiguity.

Devido aos tipos de extensibilidade fornecidos pelo roteamento, não é possível que o sistema de roteamento computar antecipadamente as rotas ambíguas.Due to the kinds of extensibility provided by routing, it isn't possible for the routing system to compute ahead of time the ambiguous routes. Considere um exemplo, como os modelos de rota /{message:alpha} e /{message:int} :Consider an example such as the route templates /{message:alpha} and /{message:int}:

  • A alpha restrição corresponde apenas a caracteres alfabéticos.The alpha constraint matches only alphabetic characters.
  • A int restrição corresponde apenas a números.The int constraint matches only numbers.
  • Esses modelos têm a mesma precedência de rota, mas não há uma URL única que ambos correspondam.These templates have the same route precedence, but there's no single URL they both match.
  • Se o sistema de roteamento relatou um erro de ambiguidade na inicialização, ele bloquearia esse caso de uso válido.If the routing system reported an ambiguity error at startup, it would block this valid use case.

Aviso

A ordem das operações dentro UseEndpoints não influencia o comportamento do roteamento, com uma exceção.The order of operations inside UseEndpoints doesn't influence the behavior of routing, with one exception. MapControllerRoute e MapAreaRoute atribuir automaticamente um valor de pedido a seus pontos de extremidade com base na ordem em que são invocados.MapControllerRoute and MapAreaRoute automatically assign an order value to their endpoints based on the order they are invoked. Isso simula o comportamento a longo prazo de controladores sem o sistema de roteamento fornecendo as mesmas garantias que as implementações de roteamento mais antigas.This simulates long-time behavior of controllers without the routing system providing the same guarantees as older routing implementations.

Na implementação herdada do roteamento, é possível implementar a extensibilidade de roteamento que tem uma dependência na ordem em que as rotas são processadas.In the legacy implementation of routing, it's possible to implement routing extensibility that has a dependency on the order in which routes are processed. Roteamento de ponto de extremidade no ASP.NET Core 3,0 e posterior:Endpoint routing in ASP.NET Core 3.0 and later:

  • Não tem um conceito de rotas.Doesn't have a concept of routes.
  • Não fornece garantias de ordenação.Doesn't provide ordering guarantees. Todos os pontos de extremidade são processados de uma só vez.All endpoints are processed at once.

Ordem de precedência do modelo de rota e seleção de ponto de extremidadeRoute template precedence and endpoint selection order

A precedência de modelo de rota é um sistema que atribui a cada modelo de rota um valor baseado em como ele é específico.Route template precedence is a system that assigns each route template a value based on how specific it is. Precedência do modelo de rota:Route template precedence:

  • Evita a necessidade de ajustar a ordem dos pontos de extremidade em casos comuns.Avoids the need to adjust the order of endpoints in common cases.
  • Tenta corresponder às expectativas de senso comum de comportamento de roteamento.Attempts to match the common-sense expectations of routing behavior.

Por exemplo, considere modelos /Products/List e /Products/{id} .For example, consider templates /Products/List and /Products/{id}. Seria razoável pressupor que /Products/List seja uma correspondência melhor do que /Products/{id} para o caminho da URL /Products/List .It would be reasonable to assume that /Products/List is a better match than /Products/{id} for the URL path /Products/List. Isso funciona porque o segmento literal /List é considerado com precedência melhor do que o segmento de parâmetro /{id} .This works because the literal segment /List is considered to have better precedence than the parameter segment /{id}.

Os detalhes de como a precedência funcionam são acoplados a como os modelos de rota são definidos:The details of how precedence works are coupled to how route templates are defined:

  • Modelos com mais segmentos são considerados mais específicos.Templates with more segments are considered more specific.
  • Um segmento com texto literal é considerado mais específico do que um segmento de parâmetro.A segment with literal text is considered more specific than a parameter segment.
  • Um segmento de parâmetro com uma restrição é considerado mais específico que um sem.A parameter segment with a constraint is considered more specific than one without.
  • Um segmento complexo é considerado específico como um segmento de parâmetro com uma restrição.A complex segment is considered as specific as a parameter segment with a constraint.
  • Catch-todos os parâmetros são os menos específicos.Catch-all parameters are the least specific. Consulte catch-all na referência do modelo de rota para obter informações importantes sobre as rotas catch-all.See catch-all in the Route template reference for important information on catch-all routes.

Consulte o código-fonte no GitHub para obter uma referência de valores exatos.See the source code on GitHub for a reference of exact values.

Conceitos de geração de URLURL generation concepts

Geração de URL:URL generation:

  • É o processo pelo qual o roteamento pode criar um caminho de URL com base em um conjunto de valores de rota.Is the process by which routing can create a URL path based on a set of route values.
  • Permite uma separação lógica entre os pontos de extremidade e as URLs que os acessam.Allows for a logical separation between endpoints and the URLs that access them.

O roteamento de ponto de extremidade inclui a LinkGenerator API.Endpoint routing includes the LinkGenerator API. LinkGenerator é um serviço singleton disponível de di.LinkGenerator is a singleton service available from DI. A LinkGenerator API pode ser usada fora do contexto de uma solicitação em execução.The LinkGenerator API can be used outside of the context of an executing request. MVC. IUrlHelper e cenários que dependem IUrlHelper , como auxiliares de marca, auxiliares de HTML e resultados de ação, usam a LinkGenerator API internamente para fornecer recursos de geração de link.Mvc.IUrlHelper and scenarios that rely on IUrlHelper, such as Tag Helpers, HTML Helpers, and Action Results, use the LinkGenerator API internally to provide link generating capabilities.

O gerador de link é respaldado pelo conceito de um endereço e esquemas de endereço.The link generator is backed by the concept of an address and address schemes. Um esquema de endereço é uma maneira de determinar os pontos de extremidade que devem ser considerados para a geração de link.An address scheme is a way of determining the endpoints that should be considered for link generation. Por exemplo, os valores de rota e de nome da rota muitos usuários estão familiarizados com os controladores e Razor as páginas são implementados como um esquema de endereço.For example, the route name and route values scenarios many users are familiar with from controllers and Razor Pages are implemented as an address scheme.

O gerador de link pode vincular a controladores e Razor páginas por meio dos seguintes métodos de extensão:The link generator can link to controllers and Razor Pages via the following extension methods:

Sobrecargas desses métodos aceitam argumentos que incluem o HttpContext .Overloads of these methods accept arguments that include the HttpContext. Esses métodos são funcionalmente equivalentes a URL. Action e URL. Page, mas oferecem mais flexibilidade e opções.These methods are functionally equivalent to Url.Action and Url.Page, but offer additional flexibility and options.

Os GetPath* métodos são mais semelhantes a Url.Action e Url.Page , no que geram um URI que contém um caminho absoluto.The GetPath* methods are most similar to Url.Action and Url.Page, in that they generate a URI containing an absolute path. Os métodos GetUri* sempre geram um URI absoluto que contém um esquema e um host.The GetUri* methods always generate an absolute URI containing a scheme and host. Os métodos que aceitam um HttpContext geram um URI no contexto da solicitação em execução.The methods that accept an HttpContext generate a URI in the context of the executing request. Os valores de rota de ambiente , caminho base da URL, esquema e host da solicitação em execução são usados, a menos que sejam substituídos.The ambient route values, URL base path, scheme, and host from the executing request are used unless overridden.

LinkGenerator é chamado com um endereço.LinkGenerator is called with an address. A geração de um URI ocorre em duas etapas:Generating a URI occurs in two steps:

  1. Um endereço é associado a uma lista de pontos de extremidade que correspondem ao endereço.An address is bound to a list of endpoints that match the address.
  2. O RoutePattern de cada ponto de extremidade é avaliado até que seja encontrado um padrão de rota correspondente aos valores fornecidos.Each endpoint's RoutePattern is evaluated until a route pattern that matches the supplied values is found. A saída resultante é combinada com as outras partes de URI fornecidas ao gerador de link e é retornada.The resulting output is combined with the other URI parts supplied to the link generator and returned.

Os métodos fornecidos pelo LinkGenerator dão suporte a funcionalidades de geração de link padrão para qualquer tipo de endereço.The methods provided by LinkGenerator support standard link generation capabilities for any type of address. A maneira mais conveniente de usar o link Generator é por meio de métodos de extensão que executam operações para um tipo de endereço específico:The most convenient way to use the link generator is through extension methods that perform operations for a specific address type:

Método de extensãoExtension Method DESCRIÇÃODescription
GetPathByAddress Gera um URI com um caminho absoluto com base nos valores fornecidos.Generates a URI with an absolute path based on the provided values.
GetUriByAddress Gera um URI absoluto com base nos valores fornecidos.Generates an absolute URI based on the provided values.

Aviso

Preste atenção às seguintes implicações da chamada de métodos LinkGenerator:Pay attention to the following implications of calling LinkGenerator methods:

  • Use métodos de extensão de GetUri* com cuidado em uma configuração de aplicativo que não valide o cabeçalho Host das solicitações de entrada.Use GetUri* extension methods with caution in an app configuration that doesn't validate the Host header of incoming requests. Se o Host cabeçalho de solicitações de entrada não for validado, a entrada de solicitação não confiável poderá ser enviada de volta para o cliente em URIs em uma exibição ou página.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 or page. Recomendamos que todos os aplicativos de produção configurem seu servidor para validar o cabeçalho Host com os valores válidos conhecidos.We recommend that all production apps configure their server to validate the Host header against known valid values.

  • Use LinkGenerator com cuidado no middleware em combinação com Map ou MapWhen.Use LinkGenerator with caution in middleware in combination with Map or MapWhen. Map* altera o caminho base da solicitação em execução, o que afeta a saída da geração de link.Map* changes the base path of the executing request, which affects the output of link generation. Todas as APIs de LinkGenerator permitem a especificação de um caminho base.All of the LinkGenerator APIs allow specifying a base path. Especifique um caminho base vazio para desfazer o Map* efeito na geração de link.Specify an empty base path to undo the Map* affect on link generation.

Exemplo de middlewareMiddleware example

No exemplo a seguir, um middleware usa a LinkGenerator API para criar um link para um método de ação que lista os produtos da loja.In the following example, a middleware uses the LinkGenerator API to create a link to an action method that lists store products. Usar o gerador de link injetando-o em uma classe e chamar GenerateLink está disponível para qualquer classe em um aplicativo:Using the link generator by injecting it into a class and calling GenerateLink is available to any class in an app:

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.");
    }
}

Referência de modelo de rotaRoute template reference

Tokens dentro de {} definir parâmetros de rota que são associados se a rota for correspondida.Tokens within {} define route parameters that are bound if the route is matched. Mais de um parâmetro de rota pode ser definido em um segmento de rota, mas os parâmetros de rota devem ser separados por um valor literal.More than one route parameter can be defined in a route segment, but route parameters must be separated by a literal value. Por exemplo, {controller=Home}{action=Index} não é uma rota válida, já que não há nenhum valor literal entre {controller} e {action}.For example, {controller=Home}{action=Index} isn't a valid route, since there's no literal value between {controller} and {action}. Os parâmetros de rota devem ter um nome e podem ter atributos adicionais especificados.Route parameters must have a name and may have additional attributes specified.

Um texto literal diferente dos parâmetros de rota (por exemplo, {id}) e do separador de caminho / precisa corresponder ao texto na URL.Literal text other than route parameters (for example, {id}) and the path separator / must match the text in the URL. A correspondência de texto não diferencia maiúsculas de minúsculas e com base na representação decodificada do caminho da URL.Text matching is case-insensitive and based on the decoded representation of the URL's path. Para corresponder a um delimitador de parâmetro de rota literal { ou } , escape o delimitador repetindo o caractere.To match a literal route parameter delimiter { or }, escape the delimiter by repeating the character. Por exemplo, {{ ou }} .For example {{ or }}.

Asterisco * ou asterisco duplo ** :Asterisk * or double asterisk **:

  • Pode ser usado como um prefixo para um parâmetro de rota para associar ao restante do URI.Can be used as a prefix to a route parameter to bind to the rest of the URI.
  • São chamados de parâmetros catch-all .Are called a catch-all parameters. Por exemplo blog/{**slug}:For example, blog/{**slug}:
    • Corresponde a qualquer URI que comece com /blog e tenha qualquer valor após ele.Matches any URI that starts with /blog and has any value following it.
    • O valor a seguir /blog é atribuído ao valor de rota de espaçador .The value following /blog is assigned to the slug route value.

Aviso

Um parâmetro catch-all pode corresponder a rotas incorretamente devido a um bug no roteamento.A catch-all parameter may match routes incorrectly due to a bug in routing. Os aplicativos afetados por esse bug têm as seguintes características:Apps impacted by this bug have the following characteristics:

  • Uma rota catch-all, por exemplo, {**slug}"A catch-all route, for example, {**slug}"
  • A rota capturar tudo falha ao corresponder às solicitações que devem corresponder.The catch-all route fails to match requests it should match.
  • A remoção de outras rotas faz com que a rota capturar tudo comece a funcionar.Removing other routes makes catch-all route start working.

Veja bugs do GitHub 18677 e 16579 , por exemplo, casos que atingiram esse bug.See GitHub bugs 18677 and 16579 for example cases that hit this bug.

Uma correção de aceitação para esse bug está contida no SDK do .NET Core 3.1.301 e posterior.An opt-in fix for this bug is contained in .NET Core 3.1.301 SDK and later. O código a seguir define uma opção interna que corrige esse bug:The following code sets an internal switch that fixes this bug:

public static void Main(string[] args)
{
   AppContext.SetSwitch("Microsoft.AspNetCore.Routing.UseCorrectCatchAllBehavior", 
                         true);
   CreateHostBuilder(args).Build().Run();
}
// Remaining code removed for brevity.

Os parâmetros catch-all também podem corresponder à cadeia de caracteres vazia.Catch-all parameters can also match the empty string.

O parâmetro catch-all escapa os caracteres apropriados quando a rota é usada para gerar uma URL, incluindo caracteres separadores de caminho / .The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator / characters. Por exemplo, a rota foo/{*path} com valores de rota { path = "my/path" } gera foo/my%2Fpath.For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Observe o escape da barra invertida.Note the escaped forward slash. Para fazer a viagem de ida e volta dos caracteres separadores de caminho, use o prefixo do parâmetro da rota **.To round-trip path separator characters, use the ** route parameter prefix. A rota foo/{**path} com { path = "my/path" } gera foo/my/path.The route foo/{**path} with { path = "my/path" } generates foo/my/path.

Padrões de URL que tentam capturar um nome de arquivo com uma extensão de arquivo opcional apresentam considerações adicionais.URL patterns that attempt to capture a file name with an optional file extension have additional considerations. Por exemplo, considere o modelo files/{filename}.{ext?}.For example, consider the template files/{filename}.{ext?}. Quando existem valores para filename e ext, ambos os valores são populados.When values for both filename and ext exist, both values are populated. Se apenas um valor para filename existir na URL, a rota será correspondente porque a direita . é opcional.If only a value for filename exists in the URL, the route matches because the trailing . is optional. As URLs a seguir correspondem a essa rota:The following URLs match this route:

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

Os parâmetros de rota podem ter valores padrão , designados pela especificação do valor padrão após o nome do parâmetro separado por um sinal de igual (=).Route parameters may have default values designated by specifying the default value after the parameter name separated by an equals sign (=). Por exemplo, {controller=Home} define Home como o valor padrão de controller.For example, {controller=Home} defines Home as the default value for controller. O valor padrão é usado se nenhum valor está presente na URL para o parâmetro.The default value is used if no value is present in the URL for the parameter. Os parâmetros de rota são tornados opcionais acrescentando um ponto de interrogação ( ? ) ao final do nome do parâmetro.Route parameters are made optional by appending a question mark (?) to the end of the parameter name. Por exemplo, id?.For example, id?. A diferença entre os valores opcionais e os parâmetros de rota padrão é:The difference between optional values and default route parameters is:

  • Um parâmetro de rota com um valor padrão sempre produz um valor.A route parameter with a default value always produces a value.
  • Um parâmetro opcional tem um valor somente quando um valor é fornecido pela URL de solicitação.An optional parameter has a value only when a value is provided by the request URL.

Os parâmetros de rota podem ter restrições que precisam corresponder ao valor de rota associado da URL.Route parameters may have constraints that must match the route value bound from the URL. Adicionar : e nome de restrição após o nome do parâmetro de rota especifica uma restrição embutida em um parâmetro de rota.Adding : and constraint name after the route parameter name specifies an inline constraint on a route parameter. Se a restrição exigir argumentos, eles ficarão entre parênteses (...) após o nome da restrição.If the constraint requires arguments, they're enclosed in parentheses (...) after the constraint name. Várias restrições embutidas podem ser especificadas acrescentando outro : nome de restrição.Multiple inline constraints can be specified by appending another : and constraint name.

O nome da restrição e os argumentos são passados para o serviço IInlineConstraintResolver para criar uma instância de IRouteConstraint a ser usada no processamento de URL.The constraint name and arguments are passed to the IInlineConstraintResolver service to create an instance of IRouteConstraint to use in URL processing. Por exemplo, o modelo de rota blog/{article:minlength(10)} especifica uma restrição minlength com o argumento 10.For example, the route template blog/{article:minlength(10)} specifies a minlength constraint with the argument 10. Para obter mais informações sobre as restrições de rota e uma lista das restrições fornecidas pela estrutura, confira a seção Referência de restrição de rota.For more information on route constraints and a list of the constraints provided by the framework, see the Route constraint reference section.

Os parâmetros de rota também podem ter transformadores de parâmetro.Route parameters may also have parameter transformers. Os transformadores de parâmetro convertem o valor de um parâmetro ao gerar links e ações correspondentes e páginas para URLs.Parameter transformers transform a parameter's value when generating links and matching actions and pages to URLs. Assim como as restrições, os transformadores de parâmetros podem ser adicionados embutidos a um parâmetro de rota adicionando um : nome de transformador e após o nome do parâmetro de rota.Like constraints, parameter transformers can be added inline to a route parameter by adding a : and transformer name after the route parameter name. Por exemplo, o modelo de rota blog/{article:slugify} especifica um transformador slugify.For example, the route template blog/{article:slugify} specifies a slugify transformer. Para obter mais informações sobre transformadores de parâmetro, confira a seção Referência de transformador de parâmetro.For more information on parameter transformers, see the Parameter transformer reference section.

A tabela a seguir demonstra os modelos de rota de exemplo e seu comportamento:The following table demonstrates example route templates and their behavior:

Modelo de rotaRoute Template URI de correspondência de exemploExample Matching URI O URI de solicitação…The request URI…
hello /hello Somente corresponde ao caminho único /hello.Only matches the single path /hello.
{Page=Home} / Faz a correspondência e define Page como Home.Matches and sets Page to Home.
{Page=Home} /Contact Faz a correspondência e define Page como Contact.Matches and sets Page to Contact.
{controller}/{action}/{id?} /Products/List É mapeado para o controlador Products e a ação List.Maps to the Products controller and List action.
{controller}/{action}/{id?} /Products/Details/123 Mapeia para o Products controlador e a Details ação com id definido como 123.Maps to the Products controller and Details action withid set to 123.
{controller=Home}/{action=Index}/{id?} / Mapeia para o Home controlador e o Index método.Maps to the Home controller and Index method. id é ignorado.id is ignored.
{controller=Home}/{action=Index}/{id?} /Products Mapeia para o Products controlador e o Index método.Maps to the Products controller and Index method. id é ignorado.id is ignored.

Em geral, o uso de um modelo é a abordagem mais simples para o roteamento.Using a template is generally the simplest approach to routing. Restrições e padrões também podem ser especificados fora do modelo de rota.Constraints and defaults can also be specified outside the route template.

Segmentos complexosComplex segments

Segmentos complexos são processados por correspondência de delimitadores literais da direita para a esquerda de forma não- adequada.Complex segments are processed by matching up literal delimiters from right to left in a non-greedy way. Por exemplo, [Route("/a{b}c{d}")] é um segmento complexo.For example, [Route("/a{b}c{d}")] is a complex segment. Segmentos complexos funcionam de uma maneira específica que devem ser compreendidos para usá-los com êxito.Complex segments work in a particular way that must be understood to use them successfully. O exemplo nesta seção demonstra por que os segmentos complexos só realmente funcionam bem quando o texto delimitador não aparece dentro dos valores de parâmetro.The example in this section demonstrates why complex segments only really work well when the delimiter text doesn't appear inside the parameter values. Usar um Regex e, em seguida, extrair manualmente os valores é necessário para casos mais complexos.Using a regex and then manually extracting the values is needed for more complex cases.

Aviso

Ao usar System.Text.RegularExpressions o para processar a entrada não confiável, passe um tempo limite.When using System.Text.RegularExpressions to process untrusted input, pass a timeout. Um usuário mal-intencionado pode fornecer entrada para RegularExpressions causar um ataque de negação de serviço.A malicious user can provide input to RegularExpressions causing a Denial-of-Service attack. ASP.NET Core APIs do Framework que RegularExpressions usam passar um tempo limite.ASP.NET Core framework APIs that use RegularExpressions pass a timeout.

Este é um resumo das etapas que o roteamento executa com o modelo /a{b}c{d} e o caminho da URL /abcd .This is a summary of the steps that routing performs with the template /a{b}c{d} and the URL path /abcd. O | é usado para ajudar a visualizar como o algoritmo funciona:The | is used to help visualize how the algorithm works:

  • O primeiro literal, da direita para a esquerda, é c .The first literal, right to left, is c. Então, /abcd é pesquisado da direita e encontra /ab|c|d .So /abcd is searched from right and finds /ab|c|d.
  • Tudo para a direita ( d ) agora é correspondido ao parâmetro de rota {d} .Everything to the right (d) is now matched to the route parameter {d}.
  • O próximo literal, da direita para a esquerda, é a .The next literal, right to left, is a. Então, /ab|c|d é pesquisada a partir de onde parou e, em seguida, a é encontrada /|a|b|c|d .So /ab|c|d is searched starting where we left off, then a is found /|a|b|c|d.
  • O valor à direita ( b ) agora é correspondido ao parâmetro de rota {b} .The value to the right (b) is now matched to the route parameter {b}.
  • Não há nenhum texto restante e nenhum modelo de rota restante, portanto, essa é uma correspondência.There is no remaining text and no remaining route template, so this is a match.

Aqui está um exemplo de um caso negativo usando o mesmo modelo /a{b}c{d} e o caminho da URL /aabcd .Here's an example of a negative case using the same template /a{b}c{d} and the URL path /aabcd. O | é usado para ajudar a visualizar como o algoritmo funciona.The | is used to help visualize how the algorithm works. Esse caso não é uma correspondência, que é explicada pelo mesmo algoritmo:This case isn't a match, which is explained by the same algorithm:

  • O primeiro literal, da direita para a esquerda, é c .The first literal, right to left, is c. Então, /aabcd é pesquisado da direita e encontra /aab|c|d .So /aabcd is searched from right and finds /aab|c|d.
  • Tudo para a direita ( d ) agora é correspondido ao parâmetro de rota {d} .Everything to the right (d) is now matched to the route parameter {d}.
  • O próximo literal, da direita para a esquerda, é a .The next literal, right to left, is a. Então, /aab|c|d é pesquisada a partir de onde parou e, em seguida, a é encontrada /a|a|b|c|d .So /aab|c|d is searched starting where we left off, then a is found /a|a|b|c|d.
  • O valor à direita ( b ) agora é correspondido ao parâmetro de rota {b} .The value to the right (b) is now matched to the route parameter {b}.
  • Neste ponto, há um texto restante a , mas o algoritmo ficou sem o modelo de rota para analisar, portanto, isso não é uma correspondência.At this point there is remaining text a, but the algorithm has run out of route template to parse, so this is not a match.

Como o algoritmo de correspondência não é ávido:Since the matching algorithm is non-greedy:

  • Ele corresponde à menor quantidade de texto possível em cada etapa.It matches the smallest amount of text possible in each step.
  • Qualquer caso em que o valor do delimitador aparece dentro dos valores de parâmetro resulta em não correspondente.Any case where the delimiter value appears inside the parameter values results in not matching.

As expressões regulares fornecem muito mais controle sobre o comportamento correspondente.Regular expressions provide much more control over their matching behavior.

A correspondência de ávido, também conhecida como correspondência lenta, corresponde à maior cadeia de caracteres possível.Greedy matching, also know as lazy matching, matches the largest possible string. Non-ávido corresponde à menor Cadeia de caracteres possível.Non-greedy matches the smallest possible string.

Referência de restrição de rotaRoute constraint reference

As restrições de rota são executadas quando ocorre uma correspondência com a URL de entrada e é criado um token do caminho da URL em valores de rota.Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values. Restrições de rota geralmente inspecionam o valor de rota associado por meio do modelo de rota e fazem uma decisão verdadeira ou falsa sobre se o valor é aceitável.Route constraints generally inspect the route value associated via the route template and make a true or false decision about whether the value is acceptable. Algumas restrições da rota usam dados fora do valor de rota para considerar se a solicitação pode ser encaminhada.Some route constraints use data outside the route value to consider whether the request can be routed. Por exemplo, a HttpMethodRouteConstraint pode aceitar ou rejeitar uma solicitação de acordo com o verbo HTTP.For example, the HttpMethodRouteConstraint can accept or reject a request based on its HTTP verb. As restrições são usadas em solicitações de roteamento e na geração de link.Constraints are used in routing requests and link generation.

Aviso

Não use restrições para a validação de entrada.Don't use constraints for input validation. Se as restrições forem usadas para validação de entrada, a entrada inválida resultará em uma 404 resposta não encontrada.If constraints are used for input validation, invalid input results in a 404 Not Found response. A entrada inválida deve produzir uma 400 solicitação incorreta com uma mensagem de erro apropriada.Invalid input should produce a 400 Bad Request with an appropriate error message. As restrições de rota são usadas para desfazer a ambiguidade entre rotas semelhantes, não para validar as entradas de uma rota específica.Route constraints are used to disambiguate similar routes, not to validate the inputs for a particular route.

A tabela a seguir demonstra as restrições de rota de exemplo e seu comportamento esperado:The following table demonstrates example route constraints and their expected behavior:

restriçãoconstraint ExemploExample Correspondências de exemploExample Matches ObservaçõesNotes
int {id:int} 123456789, -123456789123456789, -123456789 Corresponde a qualquer inteiroMatches any integer
bool {active:bool} true, FALSEtrue, FALSE Corresponde a true ou false .Matches true or false. Não diferenciam maiúsculas de minúsculasCase-insensitive
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Corresponde a um DateTime valor válido na cultura invariável.Matches a valid DateTime value in the invariant culture. Consulte o aviso anterior.See preceding warning.
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Corresponde a um decimal valor válido na cultura invariável.Matches a valid decimal value in the invariant culture. Consulte o aviso anterior.See preceding warning.
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Corresponde a um double valor válido na cultura invariável.Matches a valid double value in the invariant culture. Consulte o aviso anterior.See preceding warning.
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Corresponde a um float valor válido na cultura invariável.Matches a valid float value in the invariant culture. Consulte o aviso anterior.See preceding warning.
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638 Corresponde a um valor Guid válidoMatches a valid Guid value
long {ticks:long} 123456789, -123456789123456789, -123456789 Corresponde a um valor long válidoMatches a valid long value
minlength(value) {username:minlength(4)} Rick A cadeia de caracteres deve ter, no mínimo, 4 caracteresString must be at least 4 characters
maxlength(value) {filename:maxlength(8)} MyFile A cadeia de caracteres não pode ser maior que 8 caracteresString must be no more than 8 characters
length(length) {filename:length(12)} somefile.txt A cadeia de caracteres deve ter exatamente 12 caracteresString must be exactly 12 characters long
length(min,max) {filename:length(8,16)} somefile.txt A cadeia de caracteres deve ter, pelo menos, 8 e não mais de 16 caracteresString must be at least 8 and no more than 16 characters long
min(value) {age:min(18)} 19 O valor inteiro deve ser, pelo menos, 18Integer value must be at least 18
max(value) {age:max(120)} 91 O valor inteiro não deve ser maior que 120Integer value must be no more than 120
range(min,max) {age:range(18,120)} 91 O valor inteiro deve ser, pelo menos, 18, mas não maior que 120Integer value must be at least 18 but no more than 120
alpha {name:alpha} Rick A cadeia de caracteres deve consistir em um ou mais caracteres alfabéticos a - z e não diferencia maiúsculas de minúsculas.String must consist of one or more alphabetical characters, a-z and case-insensitive.
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 A cadeia de caracteres deve corresponder à expressão regular.String must match the regular expression. Confira dicas sobre como definir uma expressão regular.See tips about defining a regular expression.
required {name:required} Rick Usado para impor que um valor não parâmetro está presente durante a geração de URLUsed to enforce that a non-parameter value is present during URL generation

Aviso

Ao usar System.Text.RegularExpressions o para processar a entrada não confiável, passe um tempo limite.When using System.Text.RegularExpressions to process untrusted input, pass a timeout. Um usuário mal-intencionado pode fornecer entrada para RegularExpressions causar um ataque de negação de serviço.A malicious user can provide input to RegularExpressions causing a Denial-of-Service attack. ASP.NET Core APIs do Framework que RegularExpressions usam passar um tempo limite.ASP.NET Core framework APIs that use RegularExpressions pass a timeout.

Várias restrições delimitadas por dois-pontos podem ser aplicadas a um único parâmetro.Multiple, colon delimited constraints can be applied to a single parameter. Por exemplo, a restrição a seguir restringe um parâmetro para um valor inteiro de 1 ou maior: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) { }

Aviso

As restrições de rota que verificam a URL e são convertidas em um tipo CLR sempre usam a cultura invariável.Route constraints that verify the URL and are converted to a CLR type always use the invariant culture. Por exemplo, conversão para o tipo CLR int ou DateTime .For example, conversion to the CLR type int or DateTime. Essas restrições pressupõem que a URL não é localizável.These constraints assume that the URL is not localizable. As restrições de rota fornecidas pela estrutura não modificam os valores armazenados nos valores de rota.The framework-provided route constraints don't modify the values stored in route values. Todos os valores de rota analisados com base na URL são armazenados como cadeias de caracteres.All route values parsed from the URL are stored as strings. Por exemplo, a restrição float tenta converter o valor de rota em um float, mas o valor convertido é usado somente para verificar se ele pode ser convertido em um 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.

Expressões regulares em restriçõesRegular expressions in constraints

Aviso

Ao usar System.Text.RegularExpressions o para processar a entrada não confiável, passe um tempo limite.When using System.Text.RegularExpressions to process untrusted input, pass a timeout. Um usuário mal-intencionado pode fornecer entrada para RegularExpressions causar um ataque de negação de serviço.A malicious user can provide input to RegularExpressions causing a Denial-of-Service attack. ASP.NET Core APIs do Framework que RegularExpressions usam passar um tempo limite.ASP.NET Core framework APIs that use RegularExpressions pass a timeout.

As expressões regulares podem ser especificadas como restrições embutidas usando a regex(...) restrição de rota.Regular expressions can be specified as inline constraints using the regex(...) route constraint. Os métodos na MapControllerRoute família também aceitam um literal de objeto de restrições.Methods in the MapControllerRoute family also accept an object literal of constraints. Se esse formulário for usado, os valores de cadeia de caracteres serão interpretados como expressões regulares.If that form is used, string values are interpreted as regular expressions.

O código a seguir usa uma restrição Regex embutida:The following code uses an inline regex constraint:

app.UseEndpoints(endpoints =>
{
    endpoints.MapGet("{message:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}",
        context => 
        {
            return context.Response.WriteAsync("inline-constraint match");
        });
 });

O código a seguir usa um literal de objeto para especificar uma restrição Regex:The following code uses an object literal to specify a regex constraint:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "people",
        pattern: "People/{ssn}",
        constraints: new { ssn = "^\\d{3}-\\d{2}-\\d{4}$", },
        defaults: new { controller = "People", action = "List", });
});

A estrutura do ASP.NET Core adiciona RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant ao construtor de expressão regular.The ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant to the regular expression constructor. Confira RegexOptions para obter uma descrição desses membros.See RegexOptions for a description of these members.

As expressões regulares usam delimitadores e tokens semelhantes aos usados pelo roteamento e pela linguagem C#.Regular expressions use delimiters and tokens similar to those used by routing and the C# language. Os tokens de expressão regular precisam ter escape.Regular expression tokens must be escaped. Para usar a expressão regular ^\d{3}-\d{2}-\d{4}$ em uma restrição embutida, use um dos seguintes:To use the regular expression ^\d{3}-\d{2}-\d{4}$ in an inline constraint, use one of the following:

  • Substitua \ os caracteres fornecidos na String como \\ caracteres no arquivo de origem C# para escapar o caractere de \ escape da cadeia de caracteres.Replace \ characters provided in the string as \\ characters in the C# source file in order to escape the \ string escape character.
  • Literais de cadeia de caracteres textuais.Verbatim string literals.

Para escapar os caracteres delimitadores de parâmetro de roteamento { ,,,, } [ ] Double os caracteres na expressão, por exemplo {{ }} [[ ]] ,,,,.To escape routing parameter delimiter characters {, }, [, ], double the characters in the expression, for example, {{, }}, [[, ]]. A tabela a seguir mostra uma expressão regular e sua versão de escape:The following table shows a regular expression and its escaped version:

Expressão regularRegular expression Expressão regular com escapeEscaped regular expression
^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$ ^[[a-z]]{{2}}$

As expressões regulares usadas no roteamento geralmente começam com o ^ caractere e correspondem à posição inicial da cadeia de caracteres.Regular expressions used in routing often start with the ^ character and match the starting position of the string. As expressões geralmente terminam com o $ caractere e correspondem ao final da cadeia de caracteres.The expressions often end with the $ character and match the end of the string. Os ^ $ caracteres e garantem que a expressão regular corresponda ao valor do parâmetro de rota inteiro.The ^ and $ characters ensure that the regular expression matches the entire route parameter value. Sem os ^ $ caracteres e, a expressão regular corresponde a qualquer subcadeia de caracteres dentro da cadeia de caracteres, o que geralmente é indesejável.Without the ^ and $ characters, the regular expression matches any substring within the string, which is often undesirable. A tabela a seguir fornece exemplos e explica por que eles correspondem ou falham na correspondência:The following table provides examples and explains why they match or fail to match:

ExpressionExpression StringString Corresponder aMatch ComentárioComment
[a-z]{2} hellohello SimYes A subcadeia de caracteres correspondeSubstring matches
[a-z]{2} 123abc456123abc456 SimYes A subcadeia de caracteres correspondeSubstring matches
[a-z]{2} mzmz SimYes Corresponde à expressãoMatches expression
[a-z]{2} MZMZ SimYes Não diferencia maiúsculas de minúsculasNot case sensitive
^[a-z]{2}$ hellohello NãoNo Confira ^ e $ acimaSee ^ and $ above
^[a-z]{2}$ 123abc456123abc456 NãoNo Confira ^ e $ acimaSee ^ and $ above

Para saber mais sobre a sintaxe de expressões regulares, confira Expressões regulares do .NET Framework.For more information on regular expression syntax, see .NET Framework Regular Expressions.

Para restringir um parâmetro a um conjunto conhecido de valores possíveis, use uma expressão regular.To constrain a parameter to a known set of possible values, use a regular expression. Por exemplo, {action:regex(^(list|get|create)$)} apenas corresponde o valor da rota action a list, get ou create.For example, {action:regex(^(list|get|create)$)} only matches the action route value to list, get, or create. Se passada para o dicionário de restrições, a cadeia de caracteres ^(list|get|create)$ é equivalente.If passed into the constraints dictionary, the string ^(list|get|create)$ is equivalent. As restrições que são passadas no dicionário de restrições que não correspondem a uma das restrições conhecidas também são tratadas como expressões regulares.Constraints that are passed in the constraints dictionary that don't match one of the known constraints are also treated as regular expressions. As restrições que são passadas dentro de um modelo que não correspondem a uma das restrições conhecidas não são tratadas como expressões regulares.Constraints that are passed within a template that don't match one of the known constraints are not treated as regular expressions.

Restrições de rotas personalizadasCustom route constraints

Restrições de rotas personalizadas podem ser criadas com a implementação da IRouteConstraint interface.Custom route constraints can be created by implementing the IRouteConstraint interface. A IRouteConstraint interface contém Match , que retorna true se a restrição é satisfeita e false , caso contrário,.The IRouteConstraint interface contains Match, which returns true if the constraint is satisfied and false otherwise.

As restrições de rotas personalizadas raramente são necessárias.Custom route constraints are rarely needed. Antes de implementar uma restrição de rota personalizada, considere alternativas, como associação de modelo.Before implementing a custom route constraint, consider alternatives, such as model binding.

A pasta restrições de ASP.NET Core fornece bons exemplos de criação de restrições.The ASP.NET Core Constraints folder provides good examples of creating a constraints. Por exemplo, GuidRouteConstraint.For example, GuidRouteConstraint.

Para usar um personalizado IRouteConstraint , o tipo de restrição de rota deve ser registrado com o aplicativo ConstraintMap no contêiner de serviço.To use a custom IRouteConstraint, the route constraint type must be registered with the app's ConstraintMap in the service container. O ConstraintMap é um dicionário que mapeia as chaves de restrição de rota para implementações de IRouteConstraint que validam essas restrições.A ConstraintMap is a dictionary that maps route constraint keys to IRouteConstraint implementations that validate those constraints. É possível atualizar o ConstraintMap do aplicativo no Startup.ConfigureServices como parte de uma chamada services.AddRouting ou configurando RouteOptions diretamente com 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>. Por exemplo:For example:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

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

A restrição anterior é aplicada no código a seguir:The preceding constraint is applied in the following code:

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    // GET /api/test/3
    [HttpGet("{id:customName}")]
    public IActionResult Get(string id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }

    // GET /api/test/my/3
    [HttpGet("my/{id:customName}")]
    public IActionResult Get(int id)
    {
        return ControllerContext.MyDisplayRouteInfo(id);
    }
}

MyDisplayRouteInfo é fornecido pelo pacote NuGet Rick. docs. Samples. RouteInfo e exibe informações de rota.MyDisplayRouteInfo is provided by the Rick.Docs.Samples.RouteInfo NuGet package and displays route information.

A implementação de MyCustomConstraint impede a 0 aplicação a um parâmetro de rota:The implementation of MyCustomConstraint prevents 0 being applied to a route parameter:

class MyCustomConstraint : IRouteConstraint
{
    private Regex _regex;

    public MyCustomConstraint()
    {
        _regex = new Regex(@"^[1-9]*$",
                            RegexOptions.CultureInvariant | RegexOptions.IgnoreCase,
                            TimeSpan.FromMilliseconds(100));
    }
    public bool Match(HttpContext httpContext, IRouter route, string routeKey,
                      RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (values.TryGetValue(routeKey, out object value))
        {
            var parameterValueString = Convert.ToString(value,
                                                        CultureInfo.InvariantCulture);
            if (parameterValueString == null)
            {
                return false;
            }

            return _regex.IsMatch(parameterValueString);
        }

        return false;
    }
}

Aviso

Ao usar System.Text.RegularExpressions o para processar a entrada não confiável, passe um tempo limite.When using System.Text.RegularExpressions to process untrusted input, pass a timeout. Um usuário mal-intencionado pode fornecer entrada para RegularExpressions causar um ataque de negação de serviço.A malicious user can provide input to RegularExpressions causing a Denial-of-Service attack. ASP.NET Core APIs do Framework que RegularExpressions usam passar um tempo limite.ASP.NET Core framework APIs that use RegularExpressions pass a timeout.

O código anterior:The preceding code:

  • Impede 0 no {id} segmento da rota.Prevents 0 in the {id} segment of the route.
  • É mostrado para fornecer um exemplo básico de implementação de uma restrição personalizada.Is shown to provide a basic example of implementing a custom constraint. Ele não deve ser usado em um aplicativo de produção.It should not be used in a production app.

O código a seguir é uma abordagem melhor para impedir id que um que contém um 0 seja processado:The following code is a better approach to preventing an id containing a 0 from being processed:

[HttpGet("{id}")]
public IActionResult Get(string id)
{
    if (id.Contains('0'))
    {
        return StatusCode(StatusCodes.Status406NotAcceptable);
    }

    return ControllerContext.MyDisplayRouteInfo(id);
}

O código anterior tem as seguintes vantagens em relação à MyCustomConstraint abordagem:The preceding code has the following advantages over the MyCustomConstraint approach:

  • Ele não requer uma restrição personalizada.It doesn't require a custom constraint.
  • Ele retorna um erro mais descritivo quando o parâmetro de rota inclui 0 .It returns a more descriptive error when the route parameter includes 0.

Referência de parâmetro de transformadorParameter transformer reference

Transformadores de parâmetro:Parameter transformers:

Por exemplo, um transformador de parâmetro slugify personalizado em padrão de rota blog\{article:slugify} com Url.Action(new { article = "MyTestArticle" }) gera 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.

Considere a seguinte IOutboundParameterTransformer implementação:Consider the following IOutboundParameterTransformer implementation:

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

        return Regex.Replace(value.ToString(), 
                             "([a-z])([A-Z])",
                             "$1-$2",
                             RegexOptions.CultureInvariant,
                             TimeSpan.FromMilliseconds(100)).ToLowerInvariant();
    }
}

Para usar um transformador de parâmetro em um padrão de rota, configure-o usando ConstraintMap em Startup.ConfigureServices :To use a parameter transformer in a route pattern, configure it using ConstraintMap in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddRouting(options =>
    {
        options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
    });
}

A estrutura de ASP.NET Core usa transformadores de parâmetro para transformar o URI em que um ponto de extremidade é resolvido.The ASP.NET Core framework uses parameter transformers to transform the URI where an endpoint resolves. Por exemplo, os transformadores de parâmetro transforma os valores de rota usados para corresponder a area , controller , action e page .For example, parameter transformers transform the route values used to match an area, controller, action, and page.

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

Com o modelo de rota anterior, a ação SubscriptionManagementController.GetAll é correspondida com o URI /subscription-management/get-all .With the preceding route template, the action SubscriptionManagementController.GetAll is matched with the URI /subscription-management/get-all. Um transformador de parâmetro não altera os valores de rota usados para gerar um link.A parameter transformer doesn't change the route values used to generate a link. Por exemplo, Url.Action("GetAll", "SubscriptionManagement") gera /subscription-management/get-all.For example, Url.Action("GetAll", "SubscriptionManagement") outputs /subscription-management/get-all.

ASP.NET Core fornece convenções de API para usar transformadores de parâmetro com rotas geradas:ASP.NET Core provides API conventions for using parameter transformers with generated routes:

Referência de geração de URLURL generation reference

Esta seção contém uma referência para o algoritmo implementado pela geração de URL.This section contains a reference for the algorithm implemented by URL generation. Na prática, os exemplos mais complexos de geração de URL usam controladores ou Razor páginas.In practice, most complex examples of URL generation use controllers or Razor Pages. Consulte Roteamento em controladores para obter informações adicionais.See routing in controllers for additional information.

O processo de geração de URL começa com uma chamada para LinkGenerator. GetPathByAddress ou um método semelhante.The URL generation process begins with a call to LinkGenerator.GetPathByAddress or a similar method. O método é fornecido com um endereço, um conjunto de valores de rota e, opcionalmente, informações sobre a solicitação atual do HttpContext .The method is provided with an address, a set of route values, and optionally information about the current request from HttpContext.

A primeira etapa é usar o endereço para resolver um conjunto de pontos de extremidade candidatos usando um IEndpointAddressScheme<TAddress> que corresponda ao tipo do endereço.The first step is to use the address to resolve a set of candidate endpoints using an IEndpointAddressScheme<TAddress> that matches the address's type.

Uma vez do conjunto de candidatos é encontrado pelo esquema de endereço, os pontos de extremidade são ordenados e processados iterativamente até que uma operação de geração de URL tenha sucesso.Once of set of candidates is found by the address scheme, the endpoints are ordered and processed iteratively until a URL generation operation succeeds. A geração de URL não verifica ambiguidades, o primeiro resultado retornado é o resultado final.URL generation does not check for ambiguities, the first result returned is the final result.

Solução de problemas de geração de URL com registro em logTroubleshooting URL generation with logging

A primeira etapa na solução de problemas de geração de URL é definir o nível de log de Microsoft.AspNetCore.Routing como TRACE .The first step in troubleshooting URL generation is setting the logging level of Microsoft.AspNetCore.Routing to TRACE. LinkGenerator registra muitos detalhes sobre seu processamento, o que pode ser útil para solucionar problemas.LinkGenerator logs many details about its processing which can be useful to troubleshoot problems.

Consulte referência de geração de URL para obter detalhes sobre a geração de URL.See URL generation reference for details on URL generation.

EndereçosAddresses

Os endereços são o conceito de geração de URL usado para associar uma chamada ao gerador de link a um conjunto de pontos de extremidade candidatos.Addresses are the concept in URL generation used to bind a call into the link generator to a set of candidate endpoints.

Os endereços são um conceito extensível que vem com duas implementações por padrão:Addresses are an extensible concept that come with two implementations by default:

  • Usando o nome do ponto de extremidade ( string ) como o endereço:Using endpoint name (string) as the address:
    • Fornece funcionalidade semelhante ao nome da rota do MVC.Provides similar functionality to MVC's route name.
    • Usa o IEndpointNameMetadata tipo de metadados.Uses the IEndpointNameMetadata metadata type.
    • Resolve a cadeia de caracteres fornecida em relação aos metadados de todos os pontos de extremidade registrados.Resolves the provided string against the metadata of all registered endpoints.
    • Gera uma exceção na inicialização se vários pontos de extremidade usarem o mesmo nome.Throws an exception on startup if multiple endpoints use the same name.
    • Recomendado para uso geral fora de controladores e Razor páginas.Recommended for general-purpose use outside of controllers and Razor Pages.
  • Usando valores de rota ( RouteValuesAddress ) como o endereço:Using route values (RouteValuesAddress) as the address:
    • Fornece funcionalidade semelhante à geração de Razor URL herdada de controladores e páginas.Provides similar functionality to controllers and Razor Pages legacy URL generation.
    • Muito complexo para estender e depurar.Very complex to extend and debug.
    • Fornece a implementação usada por IUrlHelper , auxiliares de marca, auxiliares HTML, resultados de ação, etc.Provides the implementation used by IUrlHelper, Tag Helpers, HTML Helpers, Action Results, etc.

A função do esquema de endereço é fazer a associação entre o endereço e os pontos de extremidade correspondentes por critérios arbitrários:The role of the address scheme is to make the association between the address and matching endpoints by arbitrary criteria:

  • O esquema de nome do ponto de extremidade executa uma pesquisa de dicionário básica.The endpoint name scheme performs a basic dictionary lookup.
  • O esquema de valores de rota tem um melhor subconjunto complexo do algoritmo de conjunto.The route values scheme has a complex best subset of set algorithm.

Valores de ambiente e valores explícitosAmbient values and explicit values

Da solicitação atual, o roteamento acessa os valores de rota da solicitação atual HttpContext.Request.RouteValues .From the current request, routing accesses the route values of the current request HttpContext.Request.RouteValues. Os valores associados à solicitação atual são chamados de valores de ambiente.The values associated with the current request are referred to as the ambient values. Para fins de clareza, a documentação refere-se aos valores de rota passados para métodos como valores explícitos.For the purpose of clarity, the documentation refers to the route values passed in to methods as explicit values.

O exemplo a seguir mostra valores de ambiente e valores explícitos.The following example shows ambient values and explicit values. Ele fornece valores de ambiente da solicitação atual e valores explícitos: { id = 17, } :It provides ambient values from the current request and explicit values: { id = 17, }:

public class WidgetController : Controller
{
    private readonly LinkGenerator _linkGenerator;

    public WidgetController(LinkGenerator linkGenerator)
    {
        _linkGenerator = linkGenerator;
    }

    public IActionResult Index()
    {
        var url = _linkGenerator.GetPathByAction(HttpContext,
                                                 null, null,
                                                 new { id = 17, });
        return Content(url);
    }

O código anterior:The preceding code:

O código a seguir não fornece valores de ambiente e valores explícitos: { controller = "Home", action = "Subscribe", id = 17, } :The following code provides no ambient values and explicit values: { controller = "Home", action = "Subscribe", id = 17, }:

public IActionResult Index2()
{
    var url = _linkGenerator.GetPathByAction("Subscribe", "Home",
                                             new { id = 17, });
    return Content(url);
}

O método anterior retorna /Home/Subscribe/17The preceding method returns /Home/Subscribe/17

O código a seguir no WidgetController retorna /Widget/Subscribe/17 :The following code in the WidgetController returns /Widget/Subscribe/17:

var url = _linkGenerator.GetPathByAction("Subscribe", null,
                                         new { id = 17, });

O código a seguir fornece o controlador de valores de ambiente na solicitação atual e valores explícitos: { action = "Edit", id = 17, } :The following code provides the controller from ambient values in the current request and explicit values: { action = "Edit", id = 17, }:

public class GadgetController : Controller
{
    public IActionResult Index()
    {
        var url = Url.Action("Edit", new { id = 17, });
        return Content(url);
    }

No código anterior:In the preceding code:

  • /Gadget/Edit/17 é retornado./Gadget/Edit/17 is returned.
  • Url Obtém o IUrlHelper .Url gets the IUrlHelper.
  • Action
    gera uma URL com um caminho absoluto para um método de ação.generates a URL with an absolute path for an action method. A URL contém o action nome e os route valores especificados.The URL contains the specified action name and route values.

O código a seguir fornece valores de ambiente da solicitação atual e dos valores explícitos: { page = "./Edit, id = 17, } :The following code provides ambient values from the current request and explicit values: { page = "./Edit, id = 17, }:

public class IndexModel : PageModel
{
    public void OnGet()
    {
        var url = Url.Page("./Edit", new { id = 17, });
        ViewData["URL"] = url;
    }
}

O código anterior define url como /Edit/17 quando a página de edição Razor contém a seguinte diretiva de página:The preceding code sets url to /Edit/17 when the Edit Razor Page contains the following page directive:

@page "{id:int}"

Se a página de edição não contiver o "{id:int}" modelo de rota, url será /Edit?id=17 .If the Edit page doesn't contain the "{id:int}" route template, url is /Edit?id=17.

O comportamento do MVC IUrlHelper adiciona uma camada de complexidade além das regras descritas aqui:The behavior of MVC's IUrlHelper adds a layer of complexity in addition to the rules described here:

  • IUrlHelper sempre fornece os valores de rota da solicitação atual como valores de ambiente.IUrlHelper always provides the route values from the current request as ambient values.
  • IUrlHelper. Action sempre copia os action valores atuais e de controller rota como valores explícitos, a menos que sejam substituídos pelo desenvolvedor.IUrlHelper.Action always copies the current action and controller route values as explicit values unless overridden by the developer.
  • IUrlHelper. Page sempre copia o page valor de rota atual como um valor explícito, a menos que seja substituído.IUrlHelper.Page always copies the current page route value as an explicit value unless overridden.
  • IUrlHelper.Page sempre substitui o handler valor de rota atual por null como valores explícitos, a menos que seja substituído.IUrlHelper.Page always overrides the current handler route value with null as an explicit values unless overridden.

Os usuários geralmente são surpresos com os detalhes comportamentais dos valores de ambiente, porque o MVC não parece seguir suas próprias regras.Users are often surprised by the behavioral details of ambient values, because MVC doesn't seem to follow its own rules. Para razões históricas e de compatibilidade, certos valores de rota, como,, action controller page e handler têm seu próprio comportamento de caso especial.For historical and compatibility reasons, certain route values such as action, controller, page, and handler have their own special-case behavior.

A funcionalidade equivalente fornecida pelo LinkGenerator.GetPathByAction e LinkGenerator.GetPathByPage duplica essas anomalias de IUrlHelper para compatibilidade.The equivalent functionality provided by LinkGenerator.GetPathByAction and LinkGenerator.GetPathByPage duplicates these anomalies of IUrlHelper for compatibility.

Processo de geração de URLURL generation process

Depois que o conjunto de pontos de extremidade candidatos for encontrado, o algoritmo de geração de URL:Once the set of candidate endpoints are found, the URL generation algorithm:

  • Processa os pontos de extremidade iterativamente.Processes the endpoints iteratively.
  • Retorna o primeiro resultado bem-sucedido.Returns the first successful result.

A primeira etapa nesse processo é chamada de invalidação de valor de rota.The first step in this process is called route value invalidation. Invalidação de valor de rota é o processo pelo qual o roteamento decide quais valores de rota dos valores de ambiente devem ser usados e quais devem ser ignorados.Route value invalidation is the process by which routing decides which route values from the ambient values should be used and which should be ignored. Cada valor de ambiente é considerado e combinado com os valores explícitos ou ignorado.Each ambient value is considered and either combined with the explicit values, or ignored.

A melhor maneira de pensar sobre a função de valores de ambiente é que eles tentam salvar os desenvolvedores de aplicativos digitando, em alguns casos comuns.The best way to think about the role of ambient values is that they attempt to save application developers typing, in some common cases. Tradicionalmente, os cenários em que os valores de ambiente são úteis estão relacionados ao MVC:Traditionally, the scenarios where ambient values are helpful are related to MVC:

  • Ao vincular a outra ação no mesmo controlador, o nome do controlador não precisa ser especificado.When linking to another action in the same controller, the controller name doesn't need to be specified.
  • Ao vincular a outro controlador na mesma área, o nome da área não precisa ser especificado.When linking to another controller in the same area, the area name doesn't need to be specified.
  • Ao vincular ao mesmo método de ação, os valores de rota não precisam ser especificados.When linking to the same action method, route values don't need to be specified.
  • Ao vincular a outra parte do aplicativo, você não deseja transportar os valores de rota que não têm significado nessa parte do aplicativo.When linking to another part of the app, you don't want to carry over route values that have no meaning in that part of the app.

Chamadas para LinkGenerator ou IUrlHelper que retornam null geralmente são causadas por não entender a invalidação do valor da rota.Calls to LinkGenerator or IUrlHelper that return null are usually caused by not understanding route value invalidation. Solucionar problemas de invalidação de valor de rota especificando explicitamente mais valores de rota para ver se isso resolve o problema.Troubleshoot route value invalidation by explicitly specifying more of the route values to see if that solves the problem.

A invalidação de valor de rota funciona na suposição de que o esquema de URL do aplicativo é hierárquico, com uma hierarquia formada da esquerda para a direita.Route value invalidation works on the assumption that the app's URL scheme is hierarchical, with a hierarchy formed from left-to-right. Considere o modelo de rota do controlador básico {controller}/{action}/{id?} para obter uma noção intuitiva de como isso funciona na prática.Consider the basic controller route template {controller}/{action}/{id?} to get an intuitive sense of how this works in practice. Uma alteração em um valor invalida todos os valores de rota que aparecem à direita.A change to a value invalidates all of the route values that appear to the right. Isso reflete a suposição sobre a hierarquia.This reflects the assumption about hierarchy. Se o aplicativo tiver um valor de ambiente para id , e a operação especificar um valor diferente para controller :If the app has an ambient value for id, and the operation specifies a different value for the controller:

  • id Não será reutilizado porque {controller} está à esquerda de {id?} .id won't be reused because {controller} is to the left of {id?}.

Alguns exemplos que demonstram esse princípio:Some examples demonstrating this principle:

  • Se os valores explícitos contiverem um valor para id , o valor de ambiente para id será ignorado.If the explicit values contain a value for id, the ambient value for id is ignored. Os valores de ambiente para controller e action podem ser usados.The ambient values for controller and action can be used.
  • Se os valores explícitos contiverem um valor para action , qualquer valor de ambiente para action será ignorado.If the explicit values contain a value for action, any ambient value for action is ignored. Os valores de ambiente para controller podem ser usados.The ambient values for controller can be used. Se o valor explícito para action for diferente do valor de ambiente para action , o id valor não será usado.If the explicit value for action is different from the ambient value for action, the id value won't be used. Se o valor explícito para action for igual ao valor de ambiente para action , o id valor poderá ser usado.If the explicit value for action is the same as the ambient value for action, the id value can be used.
  • Se os valores explícitos contiverem um valor para controller , qualquer valor de ambiente para controller será ignorado.If the explicit values contain a value for controller, any ambient value for controller is ignored. Se o valor explícito para controller for diferente do valor de ambiente para controller , os action id valores e não serão usados.If the explicit value for controller is different from the ambient value for controller, the action and id values won't be used. Se o valor explícito para controller for igual ao valor de ambiente para controller , os action valores e id poderão ser usados.If the explicit value for controller is the same as the ambient value for controller, the action and id values can be used.

Esse processo é mais complicado pela existência de rotas de atributos e rotas convencionais dedicadas.This process is further complicated by the existence of attribute routes and dedicated conventional routes. Rotas convencionais do controlador, como {controller}/{action}/{id?} especificar uma hierarquia usando parâmetros de rota.Controller conventional routes such as {controller}/{action}/{id?} specify a hierarchy using route parameters. Para rotas convencionais e rotas de atributos dedicadas para controladores e Razor páginas:For dedicated conventional routes and attribute routes to controllers and Razor Pages:

  • Há uma hierarquia de valores de rota.There is a hierarchy of route values.
  • Eles não aparecem no modelo.They don't appear in the template.

Nesses casos, a geração de URL define o conceito de valores necessários .For these cases, URL generation defines the required values concept. Os pontos de extremidade criados por controladores e Razor páginas têm valores necessários especificados que permitem a invalidação do valor de rota funcionar.Endpoints created by controllers and Razor Pages have required values specified that allow route value invalidation to work.

O algoritmo de invalidação de valor de rota em detalhes:The route value invalidation algorithm in detail:

  • Os nomes de valor necessários são combinados com os parâmetros de rota e, em seguida, processados da esquerda para a direita.The required value names are combined with the route parameters, then processed from left-to-right.
  • Para cada parâmetro, o valor de ambiente e o valor explícito são comparados:For each parameter, the ambient value and explicit value are compared:
    • Se o valor de ambiente e o valor explícito forem iguais, o processo continuará.If the ambient value and explicit value are the same, the process continues.
    • Se o valor de ambiente estiver presente e o valor explícito não for, o valor de ambiente será usado ao gerar a URL.If the ambient value is present and the explicit value isn't, the ambient value is used when generating the URL.
    • Se o valor de ambiente não estiver presente e o valor explícito for, rejeite o valor de ambiente e todos os valores de ambiente subsequentes.If the ambient value isn't present and the explicit value is, reject the ambient value and all subsequent ambient values.
    • Se o valor de ambiente e o valor explícito estiverem presentes, e os dois valores forem diferentes, rejeite o valor de ambiente e todos os valores de ambiente subsequentes.If the ambient value and the explicit value are present, and the two values are different, reject the ambient value and all subsequent ambient values.

Neste ponto, a operação de geração de URL está pronta para avaliar as restrições de rota.At this point, the URL generation operation is ready to evaluate route constraints. O conjunto de valores aceitos é combinado com os valores padrão de parâmetro, que é fornecido para restrições.The set of accepted values is combined with the parameter default values, which is provided to constraints. Se todas as restrições forem aprovadas, a operação continuará.If the constraints all pass, the operation continues.

Em seguida, os valores aceitos podem ser usados para expandir o modelo de rota.Next, the accepted values can be used to expand the route template. O modelo de rota é processado:The route template is processed:

  • Da esquerda para a direita.From left-to-right.
  • Cada parâmetro tem seu valor aceito substituído.Each parameter has its accepted value substituted.
  • Com os seguintes casos especiais:With the following special cases:
    • Se os valores aceitos não contiverem um valor e o parâmetro tiver um valor padrão, o valor padrão será usado.If the accepted values is missing a value and the parameter has a default value, the default value is used.
    • Se os valores aceitos não contiverem um valor e o parâmetro for opcional, o processamento continuará.If the accepted values is missing a value and the parameter is optional, processing continues.
    • Se qualquer parâmetro de rota à direita de um parâmetro opcional ausente tiver um valor, a operação falhará.If any route parameter to the right of a missing optional parameter has a value, the operation fails.
    • Parâmetros de valor padrão contíguos e parâmetros opcionais são recolhidos sempre que possível.Contiguous default-valued parameters and optional parameters are collapsed where possible.

Valores explicitamente fornecidos que não correspondem a um segmento da rota são adicionados à cadeia de caracteres de consulta.Values explicitly provided that don't match a segment of the route are added to the query string. A tabela a seguir mostra o resultado do uso do modelo de rota {controller}/{action}/{id?}.The following table shows the result when using the route template {controller}/{action}/{id?}.

Valores de ambienteAmbient Values Valores explícitosExplicit Values ResultResult
controlador = "Home"controller = "Home" ação = "About"action = "About" /Home/About
controlador = "Home"controller = "Home" controlador = "Order", ação = "About"controller = "Order", action = "About" /Order/About
controlador = "Home", cor = "Red"controller = "Home", color = "Red" ação = "About"action = "About" /Home/About
controlador = "Home"controller = "Home" ação = "About", cor = "Red"action = "About", color = "Red" /Home/About?color=Red

Problemas com invalidação de valor de rotaProblems with route value invalidation

A partir de ASP.NET Core 3,0, alguns esquemas de geração de URL usados nas versões anteriores do ASP.NET Core não funcionam bem com a geração de URL.As of ASP.NET Core 3.0, some URL generation schemes used in earlier ASP.NET Core versions don't work well with URL generation. A equipe de ASP.NET Core planeja adicionar recursos para atender a essas necessidades em uma versão futura.The ASP.NET Core team plans to add features to address these needs in a future release. Por enquanto, a melhor solução é usar o roteamento herdado.For now the best solution is to use legacy routing.

O código a seguir mostra um exemplo de um esquema de geração de URL que não tem suporte pelo roteamento.The following code shows an example of a URL generation scheme that's not supported by routing.

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute("default", 
                                     "{culture}/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapControllerRoute("blog", "{culture}/{**slug}", 
                                      new { controller = "Blog", action = "ReadPost", });
});

No código anterior, o culture parâmetro Route é usado para localização.In the preceding code, the culture route parameter is used for localization. O desejo é ter o culture parâmetro sempre aceito como um valor de ambiente.The desire is to have the culture parameter always accepted as an ambient value. No entanto, o culture parâmetro não é aceito como um valor de ambiente devido à maneira como os valores necessários funcionam:However, the culture parameter is not accepted as an ambient value because of the way required values work:

  • No "default" modelo de rota, o culture parâmetro de rota é à esquerda de controller , portanto, as alterações para controller não serão validadas culture .In the "default" route template, the culture route parameter is to the left of controller, so changes to controller won't invalidate culture.
  • No "blog" modelo de rota, o culture parâmetro de rota é considerado à direita de controller , que aparece nos valores necessários.In the "blog" route template, the culture route parameter is considered to be to the right of controller, which appears in the required values.

Configurando metadados de ponto de extremidadeConfiguring endpoint metadata

Os links a seguir fornecem informações sobre como configurar metadados de ponto de extremidade:The following links provide information on configuring endpoint metadata:

Correspondência de host em rotas com RequireHostHost matching in routes with RequireHost

RequireHost aplica uma restrição à rota que requer o host especificado.RequireHost applies a constraint to the route which requires the specified host. O RequireHost parâmetro ou [host] pode ser:The RequireHost or [Host] parameter can be:

  • Host: www.domain.com , corresponde www.domain.com a qualquer porta.Host: www.domain.com, matches www.domain.com with any port.
  • Host com curinga: *.domain.com , corresponde www.domain.com , subdomain.domain.com ou www.subdomain.domain.com em qualquer porta.Host with wildcard: *.domain.com, matches www.domain.com, subdomain.domain.com, or www.subdomain.domain.com on any port.
  • Porta: *:5000 , corresponde à porta 5000 com qualquer host.Port: *:5000, matches port 5000 with any host.
  • Host e porta: www.domain.com:5000 ou *.domain.com:5000 , corresponde ao host e à porta.Host and port: www.domain.com:5000 or *.domain.com:5000, matches host and port.

Vários parâmetros podem ser especificados usando RequireHost ou [Host] .Multiple parameters can be specified using RequireHost or [Host]. A restrição corresponde a hosts válidos para qualquer um dos parâmetros.The constraint matches hosts valid for any of the parameters. Por exemplo, [Host("domain.com", "*.domain.com")] corresponde a domain.com , www.domain.com e subdomain.domain.com .For example, [Host("domain.com", "*.domain.com")] matches domain.com, www.domain.com, and subdomain.domain.com.

O código a seguir usa RequireHost para exigir o host especificado na rota: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("AdventureWorks!"))
            .RequireHost("adventure-works.com");
        endpoints.MapHealthChecks("/healthz").RequireHost("*:8080");
    });
}

O código a seguir usa o [Host] atributo no controlador para exigir qualquer um dos hosts especificados:The following code uses the [Host] attribute on the controller to require any of the specified hosts:

[Host("contoso.com", "adventure-works.com")]
public class ProductController : Controller
{
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

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

Quando o [Host] atributo é aplicado ao método de controlador e de ação:When the [Host] attribute is applied to both the controller and action method:

  • O atributo na ação é usado.The attribute on the action is used.
  • O atributo do controlador é ignorado.The controller attribute is ignored.

Diretrizes de desempenho para roteamentoPerformance guidance for routing

A maior parte do roteamento foi atualizada no ASP.NET Core 3,0 para aumentar o desempenho.Most of routing was updated in ASP.NET Core 3.0 to increase performance.

Quando um aplicativo tem problemas de desempenho, o roteamento geralmente é suspeito como o problema.When an app has performance problems, routing is often suspected as the problem. O motivo pelo qual o roteamento é suspeito é que as estruturas como controladores e Razor páginas relatam a quantidade de tempo gasto dentro da estrutura em suas mensagens de registro em log.The reason routing is suspected is that frameworks like controllers and Razor Pages report the amount of time spent inside the framework in their logging messages. Quando há uma diferença significativa entre a hora relatada pelos controladores e o tempo total da solicitação:When there's a significant difference between the time reported by controllers and the total time of the request:

  • Os desenvolvedores eliminam o código do aplicativo como a origem do problema.Developers eliminate their app code as the source of the problem.
  • É comum supor que o roteamento é a causa.It's common to assume routing is the cause.

O roteamento é o desempenho testado usando milhares de pontos de extremidade.Routing is performance tested using thousands of endpoints. É improvável que um aplicativo típico encontre um problema de desempenho apenas por ser muito grande.It's unlikely that a typical app will encounter a performance problem just by being too large. A causa mais comum do desempenho de roteamento lento é geralmente um middleware personalizado com um comportamento incorreto.The most common root cause of slow routing performance is usually a badly-behaving custom middleware.

Este exemplo de código a seguir demonstra uma técnica básica para restringir a origem do atraso:This following code sample demonstrates a basic technique for narrowing down the source of delay:

public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
    app.Use(next => async context =>
    {
        var sw = Stopwatch.StartNew();
        await next(context);
        sw.Stop();

        logger.LogInformation("Time 1: {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
    });

    app.UseRouting();

    app.Use(next => async context =>
    {
        var sw = Stopwatch.StartNew();
        await next(context);
        sw.Stop();

        logger.LogInformation("Time 2: {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
    });

    app.UseAuthorization();

    app.Use(next => async context =>
    {
        var sw = Stopwatch.StartNew();
        await next(context);
        sw.Stop();

        logger.LogInformation("Time 3: {ElapsedMilliseconds}ms", sw.ElapsedMilliseconds);
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Timing test.");
        });
    });
}

Para o roteamento de tempo:To time routing:

  • Intercalar cada middleware com uma cópia do middleware de tempo mostrado no código anterior.Interleave each middleware with a copy of the timing middleware shown in the preceding code.
  • Adicione um identificador exclusivo para correlacionar os dados de tempo com o código.Add a unique identifier to correlate the timing data with the code.

Essa é uma maneira básica de restringir o atraso quando for significativo, por exemplo, mais do que 10ms .This is a basic way to narrow down the delay when it's significant, for example, more than 10ms. A subtração Time 2 de Time 1 relata o tempo gasto dentro do UseRouting middleware.Subtracting Time 2 from Time 1 reports the time spent inside the UseRouting middleware.

O código a seguir usa uma abordagem mais compacta para o código de tempo anterior:The following code uses a more compact approach to the preceding timing code:

public sealed class MyStopwatch : IDisposable
{
    ILogger<Startup> _logger;
    string _message;
    Stopwatch _sw;

    public MyStopwatch(ILogger<Startup> logger, string message)
    {
        _logger = logger;
        _message = message;
        _sw = Stopwatch.StartNew();
    }

    private bool disposed = false;


    public void Dispose()
    {
        if (!disposed)
        {
            _logger.LogInformation("{Message }: {ElapsedMilliseconds}ms",
                                    _message, _sw.ElapsedMilliseconds);

            disposed = true;
        }
    }
}
public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
    int count = 0;
    app.Use(next => async context =>
    {
        using (new MyStopwatch(logger, $"Time {++count}"))
        {
            await next(context);
        }

    });

    app.UseRouting();

    app.Use(next => async context =>
    {
        using (new MyStopwatch(logger, $"Time {++count}"))
        {
            await next(context);
        }
    });

    app.UseAuthorization();

    app.Use(next => async context =>
    {
        using (new MyStopwatch(logger, $"Time {++count}"))
        {
            await next(context);
        }
    });

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Timing test.");
        });
    });
}

Recursos de roteamento potencialmente carosPotentially expensive routing features

A lista a seguir fornece uma visão geral dos recursos de roteamento que são relativamente caros em comparação com os modelos de rota básicos:The following list provides some insight into routing features that are relatively expensive compared with basic route templates:

  • Expressões regulares: é possível escrever expressões regulares que são complexas ou ter tempo de execução demorado com uma pequena quantidade de entrada.Regular expressions: It's possible to write regular expressions that are complex, or have long running time with a small amount of input.

  • Segmentos complexos ( {x}-{y}-{z} ):Complex segments ({x}-{y}-{z}):

    • São significativamente mais caros do que analisar um segmento de caminho de URL regular.Are significantly more expensive than parsing a regular URL path segment.
    • Resulta em muitas subcadeias de caracteres que estão sendo alocadas.Result in many more substrings being allocated.
    • A lógica de segmento complexa não foi atualizada na atualização de desempenho de roteamento ASP.NET Core 3,0.The complex segment logic was not updated in ASP.NET Core 3.0 routing performance update.
  • Acesso a dados síncronos: muitos aplicativos complexos têm acesso ao banco de dado como parte de seu roteamento.Synchronous data access: Many complex apps have database access as part of their routing. ASP.NET Core 2,2 e o roteamento anterior podem não fornecer os pontos de extensibilidade corretos para dar suporte ao roteamento de acesso ao banco de dados.ASP.NET Core 2.2 and earlier routing might not provide the right extensibility points to support database access routing. Por exemplo, IRouteConstraint e IActionConstraint são síncronos.For example, IRouteConstraint, and IActionConstraint are synchronous. Pontos de extensibilidade como MatcherPolicy e EndpointSelectorContext são assíncronos.Extensibility points such as MatcherPolicy and EndpointSelectorContext are asynchronous.

Diretrizes para autores de bibliotecaGuidance for library authors

Esta seção contém diretrizes para autores de biblioteca com base no roteamento.This section contains guidance for library authors building on top of routing. Esses detalhes destinam-se a garantir que os desenvolvedores de aplicativos tenham uma boa experiência usando bibliotecas e estruturas que estendem o roteamento.These details are intended to ensure that app developers have a good experience using libraries and frameworks that extend routing.

Definir pontos de extremidadeDefine endpoints

Para criar uma estrutura que usa o roteamento para correspondência de URL, Comece definindo uma experiência de usuário que se baseia no UseEndpoints .To create a framework that uses routing for URL matching, start by defining a user experience that builds on top of UseEndpoints.

Faça a compilação acima de IEndpointRouteBuilder .DO build on top of IEndpointRouteBuilder. Isso permite que os usuários redijam sua estrutura com outros recursos de ASP.NET Core sem confusão.This allows users to compose your framework with other ASP.NET Core features without confusion. Cada modelo de ASP.NET Core inclui roteamento.Every ASP.NET Core template includes routing. Suponha que o roteamento esteja presente e familiar para os usuários.Assume routing is present and familiar for users.

app.UseEndpoints(endpoints =>
{
    // Your framework
    endpoints.MapMyFramework(...);

    endpoints.MapHealthChecks("/healthz");
});

Retorne um tipo concreto lacrado de uma chamada para MapMyFramework(...) essa implementação IEndpointConventionBuilder .DO return a sealed concrete type from a call to MapMyFramework(...) that implements IEndpointConventionBuilder. A maioria dos métodos de estrutura Map... segue esse padrão.Most framework Map... methods follow this pattern. A IEndpointConventionBuilder interface:The IEndpointConventionBuilder interface:

  • Permite a capacidade de composição de metadados.Allows composability of metadata.
  • É direcionado por uma variedade de métodos de extensão.Is targeted by a variety of extension methods.

Declarar seu próprio tipo permite que você adicione sua própria funcionalidade específica à estrutura ao construtor.Declaring your own type allows you to add your own framework-specific functionality to the builder. Está OK para encapsular um construtor declarado por estrutura e encaminhar chamadas para ele.It's ok to wrap a framework-declared builder and forward calls to it.

app.UseEndpoints(endpoints =>
{
    // Your framework
    endpoints.MapMyFramework(...).RequireAuthorization()
                                 .WithMyFrameworkFeature(awesome: true);

    endpoints.MapHealthChecks("/healthz");
});

Considere escrever o seu próprio EndpointDataSource .CONSIDER writing your own EndpointDataSource. EndpointDataSource é o primitivo de baixo nível para declarar e atualizar uma coleção de pontos de extremidade.EndpointDataSource is the low-level primitive for declaring and updating a collection of endpoints. EndpointDataSource é uma API avançada usada por controladores e Razor páginas.EndpointDataSource is a powerful API used by controllers and Razor Pages.

Os testes de roteamento têm um exemplo básico de uma fonte de dados não atualizada.The routing tests have a basic example of a non-updating data source.

Não tente registrar um EndpointDataSource por padrão.DO NOT attempt to register an EndpointDataSource by default. Exigir que os usuários registrem sua estrutura no UseEndpoints .Require users to register your framework in UseEndpoints. A filosofia do roteamento é que nada é incluído por padrão, e esse UseEndpoints é o local para registrar pontos de extremidade.The philosophy of routing is that nothing is included by default, and that UseEndpoints is the place to register endpoints.

Criando middleware integrado de roteamentoCreating routing-integrated middleware

Considere definir tipos de metadados como uma interface.CONSIDER defining metadata types as an interface.

Faça com que seja possível usar tipos de metadados como um atributo em classes e métodos.DO make it possible to use metadata types as an attribute on classes and methods.

public interface ICoolMetadata
{
    bool IsCool { get; }
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
    public bool IsCool => true;
}

Estruturas como controladores e Razor páginas dão suporte à aplicação de atributos de metadados a tipos e métodos.Frameworks like controllers and Razor Pages support applying metadata attributes to types and methods. Se você declarar tipos de metadados:If you declare metadata types:

  • Torná-los acessíveis como atributos.Make them accessible as attributes.
  • A maioria dos usuários está familiarizada com a aplicação de atributos.Most users are familiar with applying attributes.

Declarar um tipo de metadados como uma interface adiciona outra camada de flexibilidade:Declaring a metadata type as an interface adds another layer of flexibility:

  • As interfaces são combináveis.Interfaces are composable.
  • Os desenvolvedores podem declarar seus próprios tipos que combinam várias políticas.Developers can declare their own types that combine multiple policies.

Faça com que seja possível substituir os metadados, conforme mostrado no exemplo a seguir:DO make it possible to override metadata, as shown in the following example:

public interface ICoolMetadata
{
    bool IsCool { get; }
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CoolMetadataAttribute : Attribute, ICoolMetadata
{
    public bool IsCool => true;
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class SuppressCoolMetadataAttribute : Attribute, ICoolMetadata
{
    public bool IsCool => false;
}

[CoolMetadata]
public class MyController : Controller
{
    public void MyCool() { }

    [SuppressCoolMetadata]
    public void Uncool() { }
}

A melhor maneira de seguir essas diretrizes é evitar a definição de metadados de marcador :The best way to follow these guidelines is to avoid defining marker metadata :

  • Não procure apenas a presença de um tipo de metadados.Don't just look for the presence of a metadata type.
  • Defina uma propriedade nos metadados e verifique a propriedade.Define a property on the metadata and check the property.

A coleção de metadados é ordenada e dá suporte à substituição por prioridade.The metadata collection is ordered and supports overriding by priority. No caso de controladores, os metadados no método de ação são mais específicos.In the case of controllers, metadata on the action method is most specific.

Faça com que o middleware seja útil com e sem roteamento.DO make middleware useful with and without routing.

app.UseRouting();

app.UseAuthorization(new AuthorizationPolicy() { ... });

app.UseEndpoints(endpoints =>
{
    // Your framework
    endpoints.MapMyFramework(...).RequireAuthorization();
});

Como exemplo dessa diretriz, considere o UseAuthorization middleware.As an example of this guideline, consider the UseAuthorization middleware. O middleware de autorização permite que você passe uma política de fallback.The authorization middleware allows you to pass in a fallback policy. A política de fallback, se especificada, se aplica a ambos:The fallback policy, if specified, applies to both:

  • Pontos de extremidade sem uma política especificada.Endpoints without a specified policy.
  • Solicitações que não correspondem a um ponto de extremidade.Requests that don't match an endpoint.

Isso torna o middleware de autorização útil fora do contexto do roteamento.This makes the authorization middleware useful outside of the context of routing. O middleware de autorização pode ser usado para programação de middleware tradicional.The authorization middleware can be used for traditional middleware programming.

Diagnóstico de depuraçãoDebug diagnostics

Para obter uma saída de diagnóstico de roteamento detalhada, defina Logging:LogLevel:Microsoft como Debug .For detailed routing diagnostic output, set Logging:LogLevel:Microsoft to Debug. No ambiente de desenvolvimento, defina o nível de log em appsettings.Development.jsem:In the development environment, set the log level in appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

O roteamento é responsável por mapear URIs de solicitação para pontos de extremidade e expedir solicitações de entrada para esses pontos de extremidade.Routing is responsible for mapping request URIs to endpoints and dispatching incoming requests to those endpoints. As rotas são definidas no aplicativo e configuradas quando o aplicativo é iniciado.Routes are defined in the app and configured when the app starts. Uma rota pode opcionalmente extrair os valores da URL contida na solicitação e esses valores podem então ser usados para o processamento da solicitação.A route can optionally extract values from the URL contained in the request, and these values can then be used for request processing. Usando informações de rota do aplicativo, o roteamento também é capaz de gerar URLs que são mapeadas para pontos de extremidade.Using route information from the app, routing is also able to generate URLs that map to endpoints.

Para usar os últimos cenários de roteamento no ASP.NET Core 2.2, especifique a versão de compatibilidade com o registro de serviços MVC em 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);

A opção EnableEndpointRouting determina se o roteamento deve usar internamente a lógica baseada em ponto de extremidade ou a lógica baseada em IRouter do ASP.NET Core 2.1 ou anterior.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. Quando a versão de compatibilidade é definida como 2.2 ou posterior, o valor padrão é true.When the compatibility version is set to 2.2 or later, the default value is true. Defina o valor como false para usar a lógica de roteamento anterior: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);

Para obter mais informações sobre o roteamento baseado em IRouter, confira a versão do ASP.NET Core 2.1 deste tópico.For more information on IRouter-based routing, see the ASP.NET Core 2.1 version of this topic.

Importante

Este documento aborda o roteamento de nível inferior do ASP.NET Core.This document covers low-level ASP.NET Core routing. Para obter informações sobre o roteamento do ASP.NET Core MVC, confira Roteamento para ações do controlador no ASP.NET Core.For information on ASP.NET Core MVC routing, see Roteamento para ações do controlador no ASP.NET Core. Para obter informações sobre convenções de roteamento em Razor páginas, consulte Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core .For information on routing conventions in Razor Pages, see Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Conceitos básicos sobre roteamentoRouting basics

A maioria dos aplicativos deve escolher um esquema de roteamento básico e descritivo para que as URLs sejam legíveis e significativas.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. A rota convencional padrão {controller=Home}/{action=Index}/{id?}:The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Dá suporte a um esquema de roteamento básico e descritivo.Supports a basic and descriptive routing scheme.
  • É um ponto de partida útil para aplicativos baseados em interface do usuário.Is a useful starting point for UI-based apps.

Os desenvolvedores normalmente adicionam rotas rencisas adicionais a áreas de tráfego intenso de um aplicativo em situações especializadas usando Roteamento de atributos ou rotas convencionais dedicadas.Developers commonly add additional terse routes to high-traffic areas of an app in specialized situations using attribute routing or dedicated conventional routes. Exemplos de situações especializadas incluem pontos de extremidade de blog e de comércio eletrônico.Specialized situations examples include, blog and ecommerce endpoints.

As APIs da Web devem usar o roteamento de atributo para modelar a funcionalidade do aplicativo como um conjunto de recursos em que as operações são representadas por verbos 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. Isso significa que muitas operações, por exemplo, GET e POST, no mesmo recurso lógico usam a mesma URL.This means that many operations, for example, GET, and POST, on the same logical resource use the same URL. O roteamento de atributo fornece um nível de controle necessário para projetar cuidadosamente o layout de ponto de extremidade público de uma API.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Razor Os aplicativos de páginas usam roteamento convencional padrão para atender aos recursos nomeados na pasta páginas de um aplicativo.Razor Pages apps use default conventional routing to serve named resources in the Pages folder of an app. Há convenções adicionais disponíveis que permitem personalizar o Razor comportamento de roteamento de páginas.Additional conventions are available that allow you to customize Razor Pages routing behavior. Para obter mais informações, consulte Introdução às Razor páginas no ASP.NET Core e Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core.For more information, see Introdução às Razor páginas no ASP.NET Core and Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core.

O suporte à geração de URL permite que o aplicativo seja desenvolvido sem hard-coding das URLs para vincular o aplicativo.URL generation support allows the app to be developed without hard-coding URLs to link the app together. Esse suporte permite começar com uma configuração de roteamento básica e modificar as rotas, depois que o layout de recurso do aplicativo é determinado.This support allows for starting with a basic routing configuration and modifying the routes after the app's resource layout is determined.

O roteamento usa pontos de extremidade ( Endpoint ) para representar pontos de extremidade lógicos em um aplicativo.Routing uses endpoints (Endpoint) to represent logical endpoints in an app.

Um ponto de extremidade define um delegado para processar solicitações e uma coleção de metadados arbitrários.An endpoint defines a delegate to process requests and a collection of arbitrary metadata. Os metadados usados implementam interesses paralelos com base em políticas e na configuração anexada a cada ponto de extremidade.The metadata is used implement cross-cutting concerns based on policies and configuration attached to each endpoint.

O sistema de roteamento tem as seguintes características:The routing system has the following characteristics:

  • A sintaxe do modelo de rota é usada para definir rotas com os parâmetros de rota com tokens criados.Route template syntax is used to define routes with tokenized route parameters.

  • A configuração de ponto de extremidade de estilo convencional e de estilo de atributo é permitida.Conventional-style and attribute-style endpoint configuration is permitted.

  • IRouteConstraint é usado para determinar se um parâmetro de URL contém um valor válido para determinada restrição de ponto de extremidade.IRouteConstraint is used to determine whether a URL parameter contains a valid value for a given endpoint constraint.

  • Modelos de aplicativo, como MVC/ Razor páginas, registram todos os seus pontos de extremidade, que têm uma implementação previsível de cenários de roteamento.App models, such as MVC/Razor Pages, register all of their endpoints, which have a predictable implementation of routing scenarios.

  • A implementação de roteamento toma decisões de roteamento, sempre que desejado no pipeline de middleware.The routing implementation makes routing decisions wherever desired in the middleware pipeline.

  • O Middleware que aparece após um Middleware de Roteamento pode inspecionar o resultado da decisão de ponto de extremidade do Middleware de Roteamento para determinado URI de solicitação.Middleware that appears after a Routing Middleware can inspect the result of the Routing Middleware's endpoint decision for a given request URI.

  • É possível enumerar todos os pontos de extremidade no aplicativo em qualquer lugar do pipeline de middleware.It's possible to enumerate all of the endpoints in the app anywhere in the middleware pipeline.

  • Um aplicativo pode usar o roteamento para gerar URLs (por exemplo, para redirecionamento ou links) com base nas informações de ponto de extremidade e evitar URLs embutidas em código, o que ajuda na facilidade de manutenção.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.

  • A geração de URL baseia-se em endereços, que dá suporte à extensibilidade arbitrária:URL generation is based on addresses, which support arbitrary extensibility:

Observação

Com o lançamento do roteamento de ponto de extremidade no ASP.NET Core 2,2, a vinculação de ponto de extremidade é limitada a Razor páginas e ações do MVC/páginas.With the release of endpoint routing in ASP.NET Core 2.2, endpoint linking is limited to MVC/Razor Pages actions and pages. As expansões de funcionalidades de vinculação de ponto de extremidade estão planejadas para versões futuras.The expansions of endpoint-linking capabilities is planned for future releases.

O roteamento está conectado ao pipeline do middleware pela classe RouterMiddleware.Routing is connected to the middleware pipeline by the RouterMiddleware class. ASP.NET Core MVC adiciona o roteamento ao pipeline de middleware como parte de sua configuração e manipula o roteamento em aplicativos MVC e Razor páginas.ASP.NET Core MVC adds routing to the middleware pipeline as part of its configuration and handles routing in MVC and Razor Pages apps. Para saber como usar o roteamento como um componente autônomo, confira a seção Usar o Middleware de Roteamento.To learn how to use routing as a standalone component, see the Use Routing Middleware section.

Correspondência de URLURL matching

A correspondência de URL é o processo pelo qual o roteamento expede uma solicitação de entrada para um ponto de extremidade.URL matching is the process by which routing dispatches an incoming request to an endpoint. Esse processo se baseia nos dados do caminho da URL, mas pode ser estendido para considerar qualquer dado na solicitação.This process is based on data in the URL path but can be extended to consider any data in the request. A capacidade de expedir solicitações para manipuladores separados é fundamental para dimensionar o tamanho e a complexidade de um aplicativo.The ability to dispatch requests to separate handlers is key to scaling the size and complexity of an app.

O sistema de roteamento no roteamento de ponto de extremidade é responsável por todas as decisões de expedição.The routing system in endpoint routing is responsible for all dispatching decisions. Como o middleware aplica políticas com base no ponto de extremidade selecionado, é importante que qualquer decisão que possa afetar a expedição ou a aplicação de políticas de segurança seja feita dentro do sistema de roteamento.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.

Quando o delegado do ponto de extremidade é executado, as propriedades de RouteContext.RouteData são definidas com valores apropriados com base no processamento da solicitação executado até o momento.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 é um dicionário de valores de rota produzido por meio da rota.RouteData.Values is a dictionary of route values produced from the route. Esses valores geralmente são determinados pela criação de token da URL e podem ser usados para aceitar a entrada do usuário ou tomar outras decisões de expedição dentro do aplicativo.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 é um recipiente de propriedades de dados adicionais relacionados à rota correspondente.RouteData.DataTokens is a property bag of additional data related to the matched route. DataTokens são fornecidos para dar suporte à associação de dados de estado com cada rota para que o aplicativo possa tomar decisões com base em qual rota teve uma correspondência.DataTokens are provided to support associating state data with each route so that the app can make decisions based on which route matched. Esses valores são definidos pelo desenvolvedor e não afetam de forma alguma o comportamento do roteamento.These values are developer-defined and do not affect the behavior of routing in any way. Além disso, os valores em stash em RouteData.DataTokens podem ser de qualquer tipo, ao contrário de RouteData.Values, que devem ser conversíveis de/para cadeias de caracteres.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 é uma lista das rotas que participaram da correspondência bem-sucedida da solicitação.RouteData.Routers is a list of the routes that took part in successfully matching the request. As rotas podem ser aninhadas uma dentro da outra.Routes can be nested inside of one another. A propriedade Routers reflete o caminho pela árvore lógica de rotas que resultou em uma correspondência.The Routers property reflects the path through the logical tree of routes that resulted in a match. Em geral, o primeiro item em Routers é a coleção de rotas e deve ser usado para a geração de URL.Generally, the first item in Routers is the route collection and should be used for URL generation. O último item em Routers é o manipulador de rotas que teve uma correspondência.The last item in Routers is the route handler that matched.

Geração de URL com o LinkGeneratorURL generation with LinkGenerator

Geração de URL é o processo pelo qual o roteamento pode criar um caminho de URL de acordo com um conjunto de valores de rota.URL generation is the process by which routing can create a URL path based on a set of route values. Isso permite uma separação lógica entre os pontos de extremidade e as URLs que os acessam.This allows for a logical separation between your endpoints and the URLs that access them.

O roteamento de ponto de extremidade inclui a API de Gerador de Link (LinkGenerator).Endpoint routing includes the Link Generator API (LinkGenerator). LinkGenerator é um serviço singleton que pode ser recuperado de di.LinkGenerator is a singleton service that can be retrieved from DI. A API pode ser usada fora do contexto de uma solicitação em execução.The API can be used outside of the context of an executing request. IUrlHelper do MVC e cenários que dependem de IUrlHelper, como Auxiliares de Marcação, Auxiliares de HTML e Resultados da Ação, usam o gerador de link para fornecer funcionalidades de geração de link.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.

O gerador de link é respaldado pelo conceito de um endereço e esquemas de endereço.The link generator is backed by the concept of an address and address schemes. Um esquema de endereço é uma maneira de determinar os pontos de extremidade que devem ser considerados para a geração de link.An address scheme is a way of determining the endpoints that should be considered for link generation. Por exemplo, os valores de rota e de nome da rota muitos usuários estão familiarizados com o MVC/ Razor páginas são implementados como um esquema de endereço.For example, the route name and route values scenarios many users are familiar with from MVC/Razor Pages are implemented as an address scheme.

O gerador de link pode vincular as Razor ações e as páginas do MVC/páginas por meio dos seguintes métodos de extensão:The link generator can link to MVC/Razor Pages actions and pages via the following extension methods:

Uma sobrecarga desses métodos aceita argumentos que incluem o HttpContext.An overload of these methods accepts arguments that include the HttpContext. Esses métodos são funcionalmente equivalentes a Url.Action e Url.Page, mas oferecem mais flexibilidade e opções.These methods are functionally equivalent to Url.Action and Url.Page but offer additional flexibility and options.

Os métodos GetPath* são mais semelhantes a Url.Action e Url.Page, pois geram um URI que contém um caminho absoluto.The GetPath* methods are most similar to Url.Action and Url.Page in that they generate a URI containing an absolute path. Os métodos GetUri* sempre geram um URI absoluto que contém um esquema e um host.The GetUri* methods always generate an absolute URI containing a scheme and host. Os métodos que aceitam um HttpContext geram um URI no contexto da solicitação em execução.The methods that accept an HttpContext generate a URI in the context of the executing request. Os valores de rota de ambiente, o caminho base da URL, o esquema e o host da solicitação em execução são usados, a menos que sejam substituídos.The ambient route values, URL base path, scheme, and host from the executing request are used unless overridden.

LinkGenerator é chamado com um endereço.LinkGenerator is called with an address. A geração de um URI ocorre em duas etapas:Generating a URI occurs in two steps:

  1. Um endereço é associado a uma lista de pontos de extremidade que correspondem ao endereço.An address is bound to a list of endpoints that match the address.
  2. O RoutePattern de cada ponto de extremidade é avaliado até que seja encontrado um padrão de rota correspondente aos valores fornecidos.Each endpoint's RoutePattern is evaluated until a route pattern that matches the supplied values is found. A saída resultante é combinada com as outras partes de URI fornecidas ao gerador de link e é retornada.The resulting output is combined with the other URI parts supplied to the link generator and returned.

Os métodos fornecidos pelo LinkGenerator dão suporte a funcionalidades de geração de link padrão para qualquer tipo de endereço.The methods provided by LinkGenerator support standard link generation capabilities for any type of address. A maneira mais conveniente usar o gerador de link é por meio de métodos de extensão que executam operações para um tipo de endereço específico.The most convenient way to use the link generator is through extension methods that perform operations for a specific address type.

Método de extensãoExtension Method DESCRIÇÃODescription
GetPathByAddress Gera um URI com um caminho absoluto com base nos valores fornecidos.Generates a URI with an absolute path based on the provided values.
GetUriByAddress Gera um URI absoluto com base nos valores fornecidos.Generates an absolute URI based on the provided values.

Aviso

Preste atenção às seguintes implicações da chamada de métodos LinkGenerator:Pay attention to the following implications of calling LinkGenerator methods:

  • Use métodos de extensão de GetUri* com cuidado em uma configuração de aplicativo que não valide o cabeçalho Host das solicitações de entrada.Use GetUri* extension methods with caution in an app configuration that doesn't validate the Host header of incoming requests. Se o cabeçalho Host das solicitações de entrada não é validado, uma entrada de solicitação não confiável pode ser enviada novamente ao cliente em URIs em uma exibição/página.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. Recomendamos que todos os aplicativos de produção configurem seu servidor para validar o cabeçalho Host com os valores válidos conhecidos.We recommend that all production apps configure their server to validate the Host header against known valid values.

  • Use LinkGenerator com cuidado no middleware em combinação com Map ou MapWhen.Use LinkGenerator with caution in middleware in combination with Map or MapWhen. Map* altera o caminho base da solicitação em execução, o que afeta a saída da geração de link.Map* changes the base path of the executing request, which affects the output of link generation. Todas as APIs de LinkGenerator permitem a especificação de um caminho base.All of the LinkGenerator APIs allow specifying a base path. Sempre especifique um caminho base vazio para desfazer o efeito de Map* na geração de link.Always specify an empty base path to undo Map*'s affect on link generation.

Diferenças das versões anteriores de roteamentoDifferences from earlier versions of routing

Existem algumas diferenças entre o roteamento de ponto de extremidade no ASP.NET Core 2.2 ou posterior e nas versões anteriores de roteamento no 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:

  • O sistema de roteamento do ponto de extremidade não dá suporte à extensibilidade baseada em IRouter, incluindo a herança de Route.The endpoint routing system doesn't support IRouter-based extensibility, including inheriting from Route.

  • O roteamento de ponto de extremidade não dá suporte a WebApiCompatShim.Endpoint routing doesn't support WebApiCompatShim. Use a versão de compatibilidade 2,1 ( .SetCompatibilityVersion(CompatibilityVersion.Version_2_1) ) para continuar usando o Shim de compatibilidade.Use the 2.1 compatibility version (.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)) to continue using the compatibility shim.

  • O Roteamento de Ponto de Extremidade tem um comportamento diferente para o uso de maiúsculas dos URIs gerados ao usar rotas convencionais.Endpoint Routing has different behavior for the casing of generated URIs when using conventional routes.

    Considere o seguinte modelo de rota padrão:Consider the following default route template:

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

    Suponha que você gere um link para uma ação usando a seguinte rota:Suppose you generate a link to an action using the following route:

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

    Com o roteamento baseado em IRouter, esse código gera um URI igual a /blog/ReadPost/17, que respeita o uso de maiúsculas do valor de rota fornecido.With IRouter-based routing, this code generates a URI of /blog/ReadPost/17, which respects the casing of the provided route value. O roteamento de ponto de extremidade no ASP.NET Core 2.2 ou posterior produz /Blog/ReadPost/17 ("Blog" está em letras maiúsculas).Endpoint routing in ASP.NET Core 2.2 or later produces /Blog/ReadPost/17 ("Blog" is capitalized). O roteamento de ponto de extremidade fornece a interface IOutboundParameterTransformer que pode ser usada para personalizar esse comportamento globalmente ou para aplicar diferentes convenções ao mapeamento de URLs.Endpoint routing provides the IOutboundParameterTransformer interface that can be used to customize this behavior globally or to apply different conventions for mapping URLs.

    Para obter mais informações, confira a seção Referência de transformador de parâmetro.For more information, see the Parameter transformer reference section.

  • A geração de link usada por MVC/ Razor páginas com rotas convencionais se comporta de maneira diferente ao tentar vincular a um controlador/ação ou página que não existe.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.

    Considere o seguinte modelo de rota padrão:Consider the following default route template:

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

    Suponha que você gere um link para uma ação usando o modelo padrão com o seguinte:Suppose you generate a link to an action using the default template with the following:

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

    Com o roteamento baseado em IRouter, o resultado é sempre /Blog/ReadPost/17, mesmo se o BlogController não existe ou não tem um método de ação 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. Conforme esperado, o roteamento de ponto de extremidade no ASP.NET Core 2.2 ou posterior produz /Blog/ReadPost/17 se o método de ação existe.As expected, endpoint routing in ASP.NET Core 2.2 or later produces /Blog/ReadPost/17 if the action method exists. No entanto, o roteamento de ponto de extremidade produz uma cadeia de caracteres vazia se a ação não existe.However, endpoint routing produces an empty string if the action doesn't exist. Conceitualmente, o roteamento de ponto de extremidade não pressupõe a existência do ponto de extremidade, caso a ação não exista.Conceptually, endpoint routing doesn't assume that the endpoint exists if the action doesn't exist.

  • O algoritmo de invalidação de valor de ambiente da geração de link tem um comportamento diferente quando usado com o roteamento de ponto de extremidade.The link generation ambient value invalidation algorithm behaves differently when used with endpoint routing.

    A invalidação de valor de ambiente é o algoritmo que decide quais valores de rota da solicitação em execução no momento (os valores de ambiente) podem ser usados em operações de geração de link.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. O roteamento convencional sempre invalidava valores de rota extras ao estabelecer o vínculo com uma ação diferente.Conventional routing always invalidated extra route values when linking to a different action. O roteamento de atributo não tinha esse comportamento antes do lançamento do ASP.NET Core 2.2.Attribute routing didn't have this behavior prior to the release of ASP.NET Core 2.2. Em versões anteriores do ASP.NET Core, os links para outra ação que usam os mesmos nomes de parâmetro de rota resultavam em erros de geração de link.In earlier versions of ASP.NET Core, links to another action that use the same route parameter names resulted in link generation errors. No ASP.NET Core 2.2 ou posterior, as duas formas de roteamento invalidam os valores ao estabelecer o vínculo com outra ação.In ASP.NET Core 2.2 or later, both forms of routing invalidate values when linking to another action.

    Considere o exemplo a seguir no ASP.NET Core 2.1 ou anterior.Consider the following example in ASP.NET Core 2.1 or earlier. Ao estabelecer o vínculo com outra ação (ou outra página), os valores de rota podem ser reutilizados de maneiras indesejadas.When linking to another action (or another page), route values can be reused in undesirable ways.

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

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

    Em /Pages/Login.cshtml :In /Pages/Login.cshtml :

    @page "{id?}"
    

    Se o URI é /Store/Product/18 no ASP.NET Core 2.1 ou anterior, o link gerado na página Store/Info por @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. O valor de id igual a 18 é reutilizado, mesmo que o destino do link seja uma parte totalmente diferente do aplicativo.The id value of 18 is reused, even though the link destination is different part of the app entirely. O valor de rota de id no contexto da página /Login provavelmente é um valor de ID de usuário, e não um valor de ID do produto (product ID) da loja.The id route value in the context of the /Login page is probably a user ID value, not a store product ID value.

    No roteamento de ponto de extremidade com o ASP.NET Core 2.2 ou posterior, o resultado é /Login.In endpoint routing with ASP.NET Core 2.2 or later, the result is /Login. Os valores de ambiente não são reutilizados quando o destino vinculado é uma ação ou uma página diferente.Ambient values aren't reused when the linked destination is a different action or page.

  • Sintaxe do parâmetro de rota de viagem de ida e volta: as barras "/" não são codificadas ao usar uma sintaxe do parâmetro catch-all de asterisco duplo (**).Round-tripping route parameter syntax: Forward slashes aren't encoded when using a double-asterisk (**) catch-all parameter syntax.

    Durante a geração de link, o sistema de roteamento codifica o valor capturado em um parâmetro catch-all de asterisco duplo (**) (por exemplo, {**myparametername}), exceto as barras "/".During link generation, the routing system encodes the value captured in a double-asterisk (**) catch-all parameter (for example, {**myparametername}) except the forward slashes. O catch-all de asterisco duplo é compatível com o roteamento baseado em IRouter no ASP.NET Core 2.2 ou posterior.The double-asterisk catch-all is supported with IRouter-based routing in ASP.NET Core 2.2 or later.

    A sintaxe do parâmetro catch-all de asterisco único em versões anteriores do ASP.NET Core ({*myparametername}) permanece com suporte e as barras "/" são codificadas.The single asterisk catch-all parameter syntax in prior versions of ASP.NET Core ({*myparametername}) remains supported, and forward slashes are encoded.

    RotaRoute Link gerado comLink generated with
    Url.Action(new { category = "admin/products" })
    /search/{*page} /search/admin%2Fproducts (a barra "/" é codificada)/search/admin%2Fproducts (the forward slash is encoded)
    /search/{**page} /search/admin/products

Exemplo de middlewareMiddleware example

No exemplo a seguir, um middleware usa a API de LinkGenerator para criar um link para um método de ação que lista os produtos da loja.In the following example, a middleware uses the LinkGenerator API to create link to an action method that lists store products. O uso do gerador de link com sua injeção em uma classe e uma chamada a GenerateLink está disponível para qualquer classe em um aplicativo.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.");
    }
}

Criar rotasCreate routes

A maioria dos aplicativos cria rotas chamando MapRoute ou um dos métodos de extensão semelhantes definidos em IRouteBuilder.Most apps create routes by calling MapRoute or one of the similar extension methods defined on IRouteBuilder. Qualquer um dos métodos de extensão de IRouteBuilder cria uma instância de Route e a adicionam à coleção de rotas.Any of the IRouteBuilder extension methods create an instance of Route and add it to the route collection.

MapRoute não aceita um parâmetro de manipulador de rotas.MapRoute doesn't accept a route handler parameter. MapRoute apenas adiciona rotas que são manipuladas pelo DefaultHandler.MapRoute only adds routes that are handled by the DefaultHandler. Para saber mais sobre o roteamento no MVC, confira Roteamento para ações do controlador no ASP.NET Core.To learn more about routing in MVC, see Roteamento para ações do controlador no ASP.NET Core.

O exemplo de código a seguir é um exemplo de uma chamada MapRoute usada por uma definição de rota típica do 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?}");

Esse modelo corresponde a um caminho de URL e extrai os valores de rota.This template matches a URL path and extracts the route values. Por exemplo, o caminho /Products/Details/17 gera os seguintes valores de rota: { controller = Products, action = Details, id = 17 }.For example, the path /Products/Details/17 generates the following route values: { controller = Products, action = Details, id = 17 }.

Os valores de rota são determinados pela divisão do caminho da URL em segmentos e pela correspondência de cada segmento com o nome do parâmetro de rota no modelo de rota.Route values are determined by splitting the URL path into segments and matching each segment with the route parameter name in the route template. Os parâmetros de rota são nomeados.Route parameters are named. Os parâmetros são definidos com a colocação do nome do parâmetro em chaves { ... }.The parameters defined by enclosing the parameter name in braces { ... }.

O modelo anterior também pode corresponder ao caminho da URL / e produzir os valores { controller = Home, action = Index }.The preceding template could also match the URL path / and produce the values { controller = Home, action = Index }. Isso ocorre porque os parâmetros de rota {controller} e {action} têm valores padrão e o parâmetro de rota id é opcional.This occurs because the {controller} and {action} route parameters have default values and the id route parameter is optional. Um sinal de igual (=) seguido de um valor após o nome do parâmetro de rota define um valor padrão para o parâmetro.An equals sign (=) followed by a value after the route parameter name defines a default value for the parameter. Um ponto de interrogação (?) após o nome do parâmetro de rota define o parâmetro como opcional.A question mark (?) after the route parameter name defines an optional parameter.

Os parâmetros de rota com um valor padrão sempre produzem um valor de rota quando a rota corresponde.Route parameters with a default value always produce a route value when the route matches. Os parâmetros opcionais não produzem um valor de rota se não houver nenhum segmento de caminho de URL correspondente.Optional parameters don't produce a route value if there is no corresponding URL path segment. Confira a seção Referência de modelo de rota para obter uma descrição completa dos recursos e da sintaxe de modelo de rota.See the Route template reference section for a thorough description of route template scenarios and syntax.

No seguinte exemplo, a definição do parâmetro de rota {id:int} define uma restrição de rota para o parâmetro de rota 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}");

Esse modelo corresponde a um caminho de URL, como /Products/Details/17, mas não como /Products/Details/Apples.This template matches a URL path like /Products/Details/17 but not /Products/Details/Apples. As restrições de rota implementam IRouteConstraint e inspecionam valores de rota para verificá-los.Route constraints implement IRouteConstraint and inspect route values to verify them. Neste exemplo, o valor de rota id precisa ser conversível em um inteiro.In this example, the route value id must be convertible to an integer. Confira route-constraint-reference para obter uma explicação das restrições de rota fornecidas pela estrutura.See route-constraint-reference for an explanation of route constraints provided by the framework.

Sobrecargas adicionais de MapRoute aceitam valores para constraints, dataTokens e defaults.Additional overloads of MapRoute accept values for constraints, dataTokens, and defaults. O uso típico desses parâmetros é passar um objeto de tipo anônimo, no qual os nomes da propriedade do tipo anônimo correspondem aos nomes do parâmetro de rota.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.

Os seguintes exemplos de MapRoute criam rotas equivalentes: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?}");

Dica

A sintaxe embutida para a definição de restrições e padrões pode ser interessante para rotas simples.The inline syntax for defining constraints and defaults can be convenient for simple routes. No entanto, há cenários, como tokens de dados, que não dão suporte à sintaxe embutida.However, there are scenarios, such as data tokens, that aren't supported by inline syntax.

O seguinte exemplo demonstra mais alguns cenários:The following example demonstrates a few additional scenarios:

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

O modelo anterior corresponde a um caminho de URL, como /Blog/All-About-Routing/Introduction, e extrai os valores { 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 }. Os valores de rota padrão para controller e action são produzidos pela rota, mesmo que não haja nenhum parâmetro de rota correspondente no modelo.The default route values for controller and action are produced by the route even though there are no corresponding route parameters in the template. Os valores padrão podem ser especificados no modelo de rota.Default values can be specified in the route template. O parâmetro de rota article é definido como um catch-all pela aparência de um asterisco duplo (**) antes do nome do parâmetro de rota.The article route parameter is defined as a catch-all by the appearance of an double asterisk (**) before the route parameter name. Os parâmetros de rota catch-all capturam o restante do caminho de URL e também podem corresponder à cadeia de caracteres vazia.Catch-all route parameters capture the remainder of the URL path and can also match the empty string.

O seguinte exemplo adiciona restrições de rota e tokens de dados: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" });

O modelo anterior corresponde a um caminho de URL como /en-US/Products/5 e extrai os valores de { controller = Products, action = Details, id = 5 } e os tokens de dados { 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 }.

Tokens locais do Windows

Geração de URL da classe de rotaRoute class URL generation

A classe Route também pode executar a geração de URL pela combinação de um conjunto de valores de rota com seu modelo de rota.The Route class can also perform URL generation by combining a set of route values with its route template. Logicamente, este é o processo inverso de correspondência do caminho de URL.This is logically the reverse process of matching the URL path.

Dica

Para entender melhor a geração de URL, imagine qual URL você deseja gerar e, em seguida, pense em como um modelo de rota corresponderia a essa 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. Quais valores serão produzidos?What values would be produced? Este é o equivalente aproximado de como funciona a geração de URL na classe Route.This is the rough equivalent of how URL generation works in the Route class.

O seguinte exemplo usa uma rota padrão geral do 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?}");

Com os valores de rota { controller = Products, action = List }, a URL /Products/List é gerada.With the route values { controller = Products, action = List }, the URL /Products/List is generated. Os valores de rota são substituídos pelos parâmetros de rota correspondentes para formar o caminho de URL.The route values are substituted for the corresponding route parameters to form the URL path. Como id é um parâmetro de rota opcional, a URL é gerada com êxito sem um valor para id.Since id is an optional route parameter, the URL is successfully generated without a value for id.

Com os valores de rota { controller = Home, action = Index }, a URL / é gerada.With the route values { controller = Home, action = Index }, the URL / is generated. Os valores de rota fornecidos correspondem aos valores padrão, sendo que os segmentos correspondentes aos valores padrão são omitidos com segurança.The provided route values match the default values, and the segments corresponding to the default values are safely omitted.

A viagem de ida e volta gerada pelas duas URLs com a definição de rota a seguir (/Home/Index e /) produz os mesmos valores de rota que foram usados para gerar a 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.

Observação

Um aplicativo que usa o ASP.NET Core MVC deve usar UrlHelper para gerar URLs, em vez de chamar o roteamento diretamente.An app using ASP.NET Core MVC should use UrlHelper to generate URLs instead of calling into routing directly.

Para obter mais informações sobre a geração de URL, confira a seção Referência de geração de URL.For more information on URL generation, see the Url generation reference section.

Usar o middleware de roteamentoUse Routing Middleware

Referencie o metapacote Microsoft.AspNetCore.App no arquivo de projeto do aplicativo.Reference the Microsoft.AspNetCore.App metapackage in the app's project file.

Adicione o roteamento ao contêiner de serviço em Startup.ConfigureServices:Add routing to the service container in Startup.ConfigureServices:

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

As rotas precisam ser configuradas no método Startup.Configure.Routes must be configured in the Startup.Configure method. O aplicativo de exemplo usa as seguintes APIs: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);

A tabela a seguir mostra as respostas com os URIs fornecidos.The following table shows the responses with the given URIs.

URIURI RespostaResponse
/package/create/3 Olá!Hello! Valores de rota: [operation, create], [id, 3]Route values: [operation, create], [id, 3]
/package/track/-3 Olá!Hello! Valores de rota: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/-3/ Olá!Hello! Valores de rota: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/ A solicitação é ignorada; sem correspondência.The request falls through, no match.
GET /hello/Joe Olá, Joe!Hi, Joe!
POST /hello/Joe A solicitação é ignorada; corresponde apenas a HTTP GET.The request falls through, matches HTTP GET only.
GET /hello/Joe/Smith A solicitação é ignorada; sem correspondência.The request falls through, no match.

A estrutura fornece um conjunto de métodos de extensão para a criação de rotas (RequestDelegateRouteBuilderExtensions):The framework provides a set of extension methods for creating routes (RequestDelegateRouteBuilderExtensions):

Os métodos Map[Verb] usam restrições para limitar a rota ao Verbo HTTP no nome do método.The Map[Verb] methods use constraints to limit the route to the HTTP Verb in the method name. Por exemplo, veja MapGet e MapVerb.For example, see MapGet and MapVerb.

Referência de modelo de rotaRoute template reference

Os tokens entre chaves ({ ... }) definem os parâmetros de rota que serão associados se a rota for correspondida.Tokens within curly braces ({ ... }) define route parameters that are bound if the route is matched. Você pode definir mais de um parâmetro de rota em um segmento de rota, mas eles precisam ser separados por um valor literal.You can define more than one route parameter in a route segment, but they must be separated by a literal value. Por exemplo, {controller=Home}{action=Index} não é uma rota válida, já que não há nenhum valor literal entre {controller} e {action}.For example, {controller=Home}{action=Index} isn't a valid route, since there's no literal value between {controller} and {action}. Esses parâmetros de rota precisam ter um nome e podem ter atributos adicionais especificados.These route parameters must have a name and may have additional attributes specified.

Um texto literal diferente dos parâmetros de rota (por exemplo, {id}) e do separador de caminho / precisa corresponder ao texto na URL.Literal text other than route parameters (for example, {id}) and the path separator / must match the text in the URL. A correspondência de texto não diferencia maiúsculas de minúsculas e se baseia na representação decodificada do caminho de URLs.Text matching is case-insensitive and based on the decoded representation of the URLs path. Para encontrar a correspondência de um delimitador de parâmetro de rota literal ({ ou }), faça o escape do delimitador repetindo o caractere ({{ ou }}).To match a literal route parameter delimiter ({ or }), escape the delimiter by repeating the character ({{ or }}).

Padrões de URL que tentam capturar um nome de arquivo com uma extensão de arquivo opcional apresentam considerações adicionais.URL patterns that attempt to capture a file name with an optional file extension have additional considerations. Por exemplo, considere o modelo files/{filename}.{ext?}.For example, consider the template files/{filename}.{ext?}. Quando existem valores para filename e ext, ambos os valores são populados.When values for both filename and ext exist, both values are populated. Se apenas existir um valor para filename na URL, a rota encontrará uma correspondência, pois o ponto à direita (.) é opcional.If only a value for filename exists in the URL, the route matches because the trailing period (.) is optional. As URLs a seguir correspondem a essa rota:The following URLs match this route:

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

Você pode usar um asterisco (*) ou um asterisco duplo (**) como um prefixo para um parâmetro de rota para associá-lo ao restante do URI.You can use an asterisk (*) or double asterisk (**) as a prefix to a route parameter to bind to the rest of the URI. Eles são chamados de parâmetros catch-all.These are called a catch-all parameters. Por exemplo, blog/{**slug} corresponde a qualquer URI que começa com /blog e tem qualquer valor depois dele, que é atribuído ao valor de rota 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. Os parâmetros catch-all também podem corresponder à cadeia de caracteres vazia.Catch-all parameters can also match the empty string.

O parâmetro catch-all faz o escape dos caracteres corretos quando a rota é usada para gerar uma URL, incluindo os caracteres separadores de caminho (/).The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator (/) characters. Por exemplo, a rota foo/{*path} com valores de rota { path = "my/path" } gera foo/my%2Fpath.For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Observe o escape da barra invertida.Note the escaped forward slash. Para fazer a viagem de ida e volta dos caracteres separadores de caminho, use o prefixo do parâmetro da rota **.To round-trip path separator characters, use the ** route parameter prefix. A rota foo/{**path} com { path = "my/path" } gera foo/my/path.The route foo/{**path} with { path = "my/path" } generates foo/my/path.

Os parâmetros de rota podem ter valores padrão , designados pela especificação do valor padrão após o nome do parâmetro separado por um sinal de igual (=).Route parameters may have default values designated by specifying the default value after the parameter name separated by an equals sign (=). Por exemplo, {controller=Home} define Home como o valor padrão de controller.For example, {controller=Home} defines Home as the default value for controller. O valor padrão é usado se nenhum valor está presente na URL para o parâmetro.The default value is used if no value is present in the URL for the parameter. Os parâmetros de rota se tornam opcionais com o acréscimo de um ponto de interrogação (?) ao final do nome do parâmetro, como em id?.Route parameters are made optional by appending a question mark (?) to the end of the parameter name, as in id?. A diferença entre valores opcionais e parâmetros de rota padrão é que um parâmetro de rota com um valor padrão sempre produz um valor – um parâmetro opcional tem um valor somente quando um valor é fornecido pela URL de solicitação.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.

Os parâmetros de rota podem ter restrições que precisam corresponder ao valor de rota associado da URL.Route parameters may have constraints that must match the route value bound from the URL. A adição de dois-pontos (:) e do nome da restrição após o nome do parâmetro de rota especifica uma restrição embutida em um parâmetro de rota.Adding a colon (:) and constraint name after the route parameter name specifies an inline constraint on a route parameter. Se a restrição exigir argumentos, eles ficarão entre parênteses ((...)) após o nome da restrição.If the constraint requires arguments, they're enclosed in parentheses ((...)) after the constraint name. Várias restrições embutidas podem ser especificadas por meio do acréscimo de outros dois-pontos (:) e do nome da restrição.Multiple inline constraints can be specified by appending another colon (:) and constraint name.

O nome da restrição e os argumentos são passados para o serviço IInlineConstraintResolver para criar uma instância de IRouteConstraint a ser usada no processamento de URL.The constraint name and arguments are passed to the IInlineConstraintResolver service to create an instance of IRouteConstraint to use in URL processing. Por exemplo, o modelo de rota blog/{article:minlength(10)} especifica uma restrição minlength com o argumento 10.For example, the route template blog/{article:minlength(10)} specifies a minlength constraint with the argument 10. Para obter mais informações sobre as restrições de rota e uma lista das restrições fornecidas pela estrutura, confira a seção Referência de restrição de rota.For more information on route constraints and a list of the constraints provided by the framework, see the Route constraint reference section.

Os parâmetros de rota também podem ter transformadores de parâmetro, que transformam o valor de um parâmetro ao gerar links e fazer a correspondência de ações e páginas com URLs.Route parameters may also have parameter transformers, which transform a parameter's value when generating links and matching actions and pages to URLs. Assim como as restrições, os transformadores de parâmetro podem ser adicionados embutidos a um parâmetro de rota colocando dois-pontos (:) e o nome do transformador após o nome do parâmetro de rota.Like constraints, parameter transformers can be added inline to a route parameter by adding a colon (:) and transformer name after the route parameter name. Por exemplo, o modelo de rota blog/{article:slugify} especifica um transformador slugify.For example, the route template blog/{article:slugify} specifies a slugify transformer. Para obter mais informações sobre transformadores de parâmetro, confira a seção Referência de transformador de parâmetro.For more information on parameter transformers, see the Parameter transformer reference section.

A tabela a seguir demonstra modelos de rota de exemplo e seu comportamento.The following table demonstrates example route templates and their behavior.

Modelo de rotaRoute Template URI de correspondência de exemploExample Matching URI O URI de solicitação…The request URI…
hello /hello Somente corresponde ao caminho único /hello.Only matches the single path /hello.
{Page=Home} / Faz a correspondência e define Page como Home.Matches and sets Page to Home.
{Page=Home} /Contact Faz a correspondência e define Page como Contact.Matches and sets Page to Contact.
{controller}/{action}/{id?} /Products/List É mapeado para o controlador Products e a ação List.Maps to the Products controller and List action.
{controller}/{action}/{id?} /Products/Details/123 É mapeado para o controlador Products e a ação Details (id definido como 123).Maps to the Products controller and Details action (id set to 123).
{controller=Home}/{action=Index}/{id?} / É mapeado para o controlador Home e o método Index (id é ignorado).Maps to the Home controller and Index method (id is ignored).

Em geral, o uso de um modelo é a abordagem mais simples para o roteamento.Using a template is generally the simplest approach to routing. Restrições e padrões também podem ser especificados fora do modelo de rota.Constraints and defaults can also be specified outside the route template.

Dica

Habilite o Log para ver como as implementações de roteamento internas, como Route, correspondem às solicitações.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Nomes reservados de roteamentoReserved routing names

As seguintes palavras-chave são nomes reservados e não podem ser usadas como nomes de rota ou parâmetros:The following keywords are reserved names and can't be used as route names or parameters:

  • action
  • area
  • controller
  • handler
  • page

Referência de restrição de rotaRoute constraint reference

As restrições de rota são executadas quando ocorre uma correspondência com a URL de entrada e é criado um token do caminho da URL em valores de rota.Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values. Em geral, as restrições da rota inspecionam o valor de rota associado por meio do modelo de rota e tomam uma decisão do tipo "sim/não" sobre se o valor é aceitável ou não.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. Algumas restrições da rota usam dados fora do valor de rota para considerar se a solicitação pode ser encaminhada.Some route constraints use data outside the route value to consider whether the request can be routed. Por exemplo, a HttpMethodRouteConstraint pode aceitar ou rejeitar uma solicitação de acordo com o verbo HTTP.For example, the HttpMethodRouteConstraint can accept or reject a request based on its HTTP verb. As restrições são usadas em solicitações de roteamento e na geração de link.Constraints are used in routing requests and link generation.

Aviso

Não use restrições para a validação de entrada.Don't use constraints for input validation. Se as restrições forem usadas para a validação de entrada , uma entrada inválida resultará em uma resposta 404 – Não Encontrado , em vez de 400 – Solicitação Inválida com uma mensagem de erro apropriada.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. As restrições de rota são usadas para desfazer a ambiguidade entre rotas semelhantes, não para validar as entradas de uma rota específica.Route constraints are used to disambiguate similar routes, not to validate the inputs for a particular route.

A tabela a seguir demonstra restrições de rota de exemplo e seu comportamento esperado.The following table demonstrates example route constraints and their expected behavior.

ConstraintConstraint ExemploExample Correspondências de exemploExample matches ObservaçõesNotes
int {id:int} 123456789, -123456789123456789, -123456789 Corresponde a qualquer inteiro.Matches any integer.
bool {active:bool} true, FALSEtrue, FALSE Corresponde a true ou false .Matches true or false. Não diferencia maiúsculas de minúsculas.Case-insensitive.
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Corresponde a um DateTime valor válido na cultura invariável.Matches a valid DateTime value in the invariant culture. Consulte o aviso anterior.See preceding warning.
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Corresponde a um decimal valor válido na cultura invariável.Matches a valid decimal value in the invariant culture. Consulte o aviso anterior.See preceding warning.
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Corresponde a um double valor válido na cultura invariável.Matches a valid double value in the invariant culture. Consulte o aviso anterior.See preceding warning.
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Corresponde a um float valor válido na cultura invariável.Matches a valid float value in the invariant culture. Consulte o aviso anterior.See preceding warning.
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} Corresponde a um Guid valor válido.Matches a valid Guid value.
long {ticks:long} 123456789, -123456789123456789, -123456789 Corresponde a um long valor válido.Matches a valid long value.
minlength(value) {username:minlength(4)} Rick A cadeia de caracteres deve ter pelo menos 4 caracteres.String must be at least 4 characters.
maxlength(value) {filename:maxlength(8)} MyFile A cadeia de caracteres tem no máximo 8 caracteres.String has maximum of 8 characters.
length(length) {filename:length(12)} somefile.txt A cadeia de caracteres deve ter exatamente 12 caracteres.String must be exactly 12 characters long.
length(min,max) {filename:length(8,16)} somefile.txt A cadeia de caracteres deve ser pelo menos 8 e ter no máximo 16 caracteres.String must be at least 8 and has maximum of 16 characters.
min(value) {age:min(18)} 19 O valor inteiro deve ser pelo menos 18.Integer value must be at least 18.
max(value) {age:max(120)} 91 Valor inteiro máximo de 120.Integer value maximum of 120.
range(min,max) {age:range(18,120)} 91 O valor inteiro deve ser pelo menos 18 e o máximo de 120.Integer value must be at least 18 and maximum of 120.
alpha {name:alpha} Rick A cadeia de caracteres deve consistir em um ou mais caracteres alfabéticos a - z .String must consist of one or more alphabetical characters a-z. Não diferencia maiúsculas de minúsculas.Case-insensitive.
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 A cadeia de caracteres deve corresponder à expressão regular.String must match the regular expression. Confira dicas sobre como definir uma expressão regular.See tips about defining a regular expression.
required {name:required} Rick Usado para impor que um valor não parâmetro esteja presente durante a geração de URL.Used to enforce that a non-parameter value is present during URL generation.

Várias restrições delimitadas por vírgula podem ser aplicadas a um único parâmetro.Multiple, colon-delimited constraints can be applied to a single parameter. Por exemplo, a restrição a seguir restringe um parâmetro para um valor inteiro de 1 ou maior: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) { }

Aviso

As restrições de rota que verificam a URL e são convertidas em um tipo CLR (como int ou DateTime) sempre usam a cultura invariável.Route constraints that verify the URL and are converted to a CLR type (such as int or DateTime) always use the invariant culture. Essas restrições consideram que a URL não é localizável.These constraints assume that the URL is non-localizable. As restrições de rota fornecidas pela estrutura não modificam os valores armazenados nos valores de rota.The framework-provided route constraints don't modify the values stored in route values. Todos os valores de rota analisados com base na URL são armazenados como cadeias de caracteres.All route values parsed from the URL are stored as strings. Por exemplo, a restrição float tenta converter o valor de rota em um float, mas o valor convertido é usado somente para verificar se ele pode ser convertido em um 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.

Expressões regularesRegular expressions

A estrutura do ASP.NET Core adiciona RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant ao construtor de expressão regular.The ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant to the regular expression constructor. Confira RegexOptions para obter uma descrição desses membros.See RegexOptions for a description of these members.

As expressões regulares usam delimitadores e tokens semelhantes aos usados pelo roteamento e pela linguagem C#.Regular expressions use delimiters and tokens similar to those used by routing and the C# language. Os tokens de expressão regular precisam ter escape.Regular expression tokens must be escaped. Para usar a expressão regular ^\d{3}-\d{2}-\d{4}$ no roteamento:To use the regular expression ^\d{3}-\d{2}-\d{4}$ in routing:

  • A expressão deve ter os caracteres de barra invertida única \ fornecidos na cadeia de caracteres como caractere de barra invertida dupla \\ no código-fonte.The expression must have the single backslash \ characters provided in the string as double backslash \\ characters in the source code.
  • A expressão regular deve \\ ser para escapar do caractere de \ escape da cadeia de caracteres.The regular expression must us \\ in order to escape the \ string escape character.
  • A expressão regular não requer \\ ao usar literais de cadeia de caracteres textuais.The regular expression doesn't require \\ when using verbatim string literals.

Para escapar os caracteres delimitadores de parâmetro de roteamento { ,,,, } [ ] duplos os caracteres na expressão {{ , } , [[ ]] ,,.To escape routing parameter delimiter characters {, }, [, ], double the characters in the expression {{, }, [[, ]]. A tabela a seguir mostra uma expressão regular e a versão de escape:The following table shows a regular expression and the escaped version:

Expressão regularRegular Expression Expressão regular com escapeEscaped Regular Expression
^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$ ^[[a-z]]{{2}}$

As expressões regulares usadas no roteamento geralmente começam com o ^ caractere de cursor e correspondem à posição inicial da cadeia de caracteres.Regular expressions used in routing often start with the caret ^ character and match starting position of the string. As expressões geralmente terminam com o caractere de sinal de dólar $ e correspondem ao final da cadeia de caracteres.The expressions often end with the dollar sign $ character and match end of the string. Os caracteres ^ e $ garantem que a expressão regular corresponde a todo o valor do parâmetro de rota.The ^ and $ characters ensure that the regular expression match the entire route parameter value. Sem os caracteres ^ e $, a expressão regular corresponde a qualquer subcadeia de caracteres na cadeia de caracteres, o que geralmente não é o desejado.Without the ^ and $ characters, the regular expression match any substring within the string, which is often undesirable. A tabela a seguir fornece exemplos e explica por que eles encontram ou não uma correspondência.The following table provides examples and explains why they match or fail to match.

ExpressionExpression StringString Corresponder aMatch ComentárioComment
[a-z]{2} hellohello SimYes A subcadeia de caracteres correspondeSubstring matches
[a-z]{2} 123abc456123abc456 SimYes A subcadeia de caracteres correspondeSubstring matches
[a-z]{2} mzmz SimYes Corresponde à expressãoMatches expression
[a-z]{2} MZMZ SimYes Não diferencia maiúsculas de minúsculasNot case sensitive
^[a-z]{2}$ hellohello NãoNo Confira ^ e $ acimaSee ^ and $ above
^[a-z]{2}$ 123abc456123abc456 NãoNo Confira ^ e $ acimaSee ^ and $ above

Para saber mais sobre a sintaxe de expressões regulares, confira Expressões regulares do .NET Framework.For more information on regular expression syntax, see .NET Framework Regular Expressions.

Para restringir um parâmetro a um conjunto conhecido de valores possíveis, use uma expressão regular.To constrain a parameter to a known set of possible values, use a regular expression. Por exemplo, {action:regex(^(list|get|create)$)} apenas corresponde o valor da rota action a list, get ou create.For example, {action:regex(^(list|get|create)$)} only matches the action route value to list, get, or create. Se passada para o dicionário de restrições, a cadeia de caracteres ^(list|get|create)$ é equivalente.If passed into the constraints dictionary, the string ^(list|get|create)$ is equivalent. As restrições passadas para o dicionário de restrições (não embutidas em um modelo) que não correspondem a uma das restrições conhecidas também são tratadas como expressões regulares.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.

Restrições de rotas personalizadasCustom route constraints

Além das restrições de rota internas, é possível criar restrições de rota personalizadas com a implementação da interface do IRouteConstraint.In addition to the built-in route constraints, custom route constraints can be created by implementing the IRouteConstraint interface. A interface do IRouteConstraint contém um único método, Match, que retorna true quando a restrição é satisfeita. Caso contrário, retorna false.The IRouteConstraint interface contains a single method, Match, which returns true if the constraint is satisfied and false otherwise.

Para usar uma IRouteConstraint personalizada, o tipo de restrição de rota deve ser registrado com o ConstraintMap do aplicativo, no contêiner de serviço do aplicativo.To use a custom IRouteConstraint, the route constraint type must be registered with the app's ConstraintMap in the app's service container. O ConstraintMap é um dicionário que mapeia as chaves de restrição de rota para implementações de IRouteConstraint que validam essas restrições.A ConstraintMap is a dictionary that maps route constraint keys to IRouteConstraint implementations that validate those constraints. É possível atualizar o ConstraintMap do aplicativo no Startup.ConfigureServices como parte de uma chamada services.AddRouting ou configurando RouteOptions diretamente com 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>. Por exemplo:For example:

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

a restrição pode então ser aplicada às rotas da maneira usual, usando o nome especificado ao registrar o tipo de restrição.The constraint can then be applied to routes in the usual manner, using the name specified when registering the constraint type. Por exemplo:For example:

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

Referência de parâmetro de transformadorParameter transformer reference

Transformadores de parâmetro:Parameter transformers:

  • Executar ao gerar um link para um Route.Execute when generating a link for a Route.
  • Implementar Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.Implement Microsoft.AspNetCore.Routing.IOutboundParameterTransformer.
  • São configurados usando ConstraintMap.Are configured using ConstraintMap.
  • Usam o valor de rota do parâmetro e o transformam em um novo valor de cadeia de caracteres.Take the parameter's route value and transform it to a new string value.
  • Resultam no uso do valor transformado no link gerado.Result in using the transformed value in the generated link.

Por exemplo, um transformador de parâmetro slugify personalizado em padrão de rota blog\{article:slugify} com Url.Action(new { article = "MyTestArticle" }) gera 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.

Para usar um transformador de parâmetro em um padrão de rota, configure-o primeiro usando ConstraintMap em 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);
});

Os transformadores de parâmetro são usados pela estrutura para transformar o URI no qual um ponto de extremidade é resolvido.Parameter transformers are used by the framework to transform the URI where an endpoint resolves. Por exemplo, o ASP.NET Core MVC usa os transformadores de parâmetro para transformar o valor de rota usado para corresponder a um area, controller, action e 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?}");

Com a rota anterior, a ação SubscriptionManagementController.GetAll é combinada com o URI /subscription-management/get-all.With the preceding route, the action SubscriptionManagementController.GetAll is matched with the URI /subscription-management/get-all. Um transformador de parâmetro não altera os valores de rota usados para gerar um link.A parameter transformer doesn't change the route values used to generate a link. Por exemplo, Url.Action("GetAll", "SubscriptionManagement") gera /subscription-management/get-all.For example, Url.Action("GetAll", "SubscriptionManagement") outputs /subscription-management/get-all.

ASP.NET Core fornece convenções de API para usar transformadores de parâmetro com as rotas geradas:ASP.NET Core provides API conventions for using a parameter transformers with generated routes:

  • ASP.NET Core MVC tem a convenção de API Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention.ASP.NET Core MVC has the Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention API convention. Essa convenção aplica um transformador de parâmetro especificado a todas as rotas de atributo no aplicativo.This convention applies a specified parameter transformer to all attribute routes in the app. O transformador de parâmetro transforma os tokens de rota do atributo conforme elas são substituídas.The parameter transformer transforms attribute route tokens as they are replaced. Para obter mais informações, confira Usar um transformador de parâmetro para personalizar a substituição de token.For more information, see Use a parameter transformer to customize token replacement.
  • Razor As páginas têm a Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention Convenção de API.Razor Pages has the Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention API convention. Essa Convenção aplica um transformador de parâmetro especificado a todas as Razor páginas descobertas automaticamente.This convention applies a specified parameter transformer to all automatically discovered Razor Pages. O transformador de parâmetro transforma os segmentos do nome de arquivo e pasta das Razor rotas de páginas.The parameter transformer transforms the folder and file name segments of Razor Pages routes. Para obter mais informações, confira Usar um transformador de parâmetros para personalizar rotas de página.For more information, see Use a parameter transformer to customize page routes.

Referência de geração de URLURL generation reference

O exemplo a seguir mostra como gerar um link para uma rota com base em um dicionário de valores de rota e em um 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/>");
});

O VirtualPath gerado no final do exemplo anterior é /package/create/123.The VirtualPath generated at the end of the preceding sample is /package/create/123. O dicionário fornece os valores de rota operation e id do modelo "Rastrear rota do pacote", package/{operation}/{id}.The dictionary supplies the operation and id route values of the "Track Package Route" template, package/{operation}/{id}. Para obter detalhes, consulte o código de exemplo na seção Usar o middleware de roteamento ou no aplicativo de exemplo.For details, see the sample code in the Use Routing Middleware section or the sample app.

O segundo parâmetro para o construtor VirtualPathContext é uma coleção de valores de ambiente.The second parameter to the VirtualPathContext constructor is a collection of ambient values. Os valores de ambiente são convenientes de serem usados porque limitam o número de valores que um desenvolvedor precisa especificar em um contexto de solicitação.Ambient values are convenient to use because they limit the number of values a developer must specify within a request context. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link.The current route values of the current request are considered ambient values for link generation. Na ação About de um aplicativo ASP.NET Core MVC do HomeController, não é necessário especificar o valor de rota do controlador a ser vinculado à ação Index – o valor de ambiente Home é usado.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.

Os valores de ambiente que não correspondem a um parâmetro são ignorados.Ambient values that don't match a parameter are ignored. Os valores de ambiente também são ignorados quando um valor fornecido explicitamente substitui o valor de ambiente.Ambient values are also ignored when an explicitly provided value overrides the ambient value. A correspondência ocorre da esquerda para a direita na URL.Matching occurs from left to right in the URL.

Valores fornecidos explicitamente, mas que não correspondem a um segmento da rota, são adicionados à cadeia de consulta.Values explicitly provided but that don't match a segment of the route are added to the query string. A tabela a seguir mostra o resultado do uso do modelo de rota {controller}/{action}/{id?}.The following table shows the result when using the route template {controller}/{action}/{id?}.

Valores de ambienteAmbient Values Valores explícitosExplicit Values ResultResult
controlador = "Home"controller = "Home" ação = "About"action = "About" /Home/About
controlador = "Home"controller = "Home" controlador = "Order", ação = "About"controller = "Order", action = "About" /Order/About
controlador = "Home", cor = "Red"controller = "Home", color = "Red" ação = "About"action = "About" /Home/About
controlador = "Home"controller = "Home" ação = "About", cor = "Red"action = "About", color = "Red" /Home/About?color=Red

Se uma rota tem um valor padrão que não corresponde a um parâmetro e esse valor é fornecido de forma explícita, ele precisa corresponder ao valor padrão: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" });

A geração de link somente gera um link para essa rota quando os valores correspondentes de controller e action são fornecidos.Link generation only generates a link for this route when the matching values for controller and action are provided.

Segmentos complexosComplex segments

Segmentos complexos (por exemplo, [Route("/x{token}y")]) são processados por meio da combinação de literais da direita para a esquerda, de uma maneira diferente de Greedy.Complex segments (for example [Route("/x{token}y")]) are processed by matching up literals from right to left in a non-greedy way. Confira este código para ver uma explicação detalhada de como os segmentos complexos são combinados.See this code for a detailed explanation of how complex segments are matched. O exemplo de código não é usado pelo ASP.NET Core, mas fornece uma explicação adequada sobre segmentos complexos.The code sample is not used by ASP.NET Core, but it provides a good explanation of complex segments.

O roteamento é responsável por mapear URIs de solicitação para manipuladores de rotas e expedir as solicitações de entrada.Routing is responsible for mapping request URIs to route handlers and dispatching an incoming requests. As rotas são definidas no aplicativo e configuradas quando o aplicativo é iniciado.Routes are defined in the app and configured when the app starts. Uma rota pode opcionalmente extrair os valores da URL contida na solicitação e esses valores podem então ser usados para o processamento da solicitação.A route can optionally extract values from the URL contained in the request, and these values can then be used for request processing. Usando rotas configuradas no aplicativo, o roteamento pode gerar URLs que são mapeadas para manipuladores de rotas.Using configured routes from the app, routing is able to generate URLs that map to route handlers.

Para usar os últimos cenários de roteamento no ASP.NET Core 2.1, especifique a versão de compatibilidade com o registro de serviços MVC em 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);

Importante

Este documento aborda o roteamento de nível inferior do ASP.NET Core.This document covers low-level ASP.NET Core routing. Para obter informações sobre o roteamento do ASP.NET Core MVC, confira Roteamento para ações do controlador no ASP.NET Core.For information on ASP.NET Core MVC routing, see Roteamento para ações do controlador no ASP.NET Core. Para obter informações sobre convenções de roteamento em Razor páginas, consulte Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core .For information on routing conventions in Razor Pages, see Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core.

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

Conceitos básicos sobre roteamentoRouting basics

A maioria dos aplicativos deve escolher um esquema de roteamento básico e descritivo para que as URLs sejam legíveis e significativas.Most apps should choose a basic and descriptive routing scheme so that URLs are readable and meaningful. A rota convencional padrão {controller=Home}/{action=Index}/{id?}:The default conventional route {controller=Home}/{action=Index}/{id?}:

  • Dá suporte a um esquema de roteamento básico e descritivo.Supports a basic and descriptive routing scheme.
  • É um ponto de partida útil para aplicativos baseados em interface do usuário.Is a useful starting point for UI-based apps.

Os desenvolvedores geralmente adicionam outras rotas concisas às áreas de alto tráfego de um aplicativo em situações especiais (por exemplo, pontos de extremidade de blog e comércio eletrônico) usando o roteamento de atributo ou rotas convencionais dedicadas.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.

As APIs da Web devem usar o roteamento de atributo para modelar a funcionalidade do aplicativo como um conjunto de recursos em que as operações são representadas por verbos 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. Isso significa que muitas operações (por exemplo, GET, POST) no mesmo recurso lógico usarão a mesma URL.This means that many operations (for example, GET, POST) on the same logical resource will use the same URL. O roteamento de atributo fornece um nível de controle necessário para projetar cuidadosamente o layout de ponto de extremidade público de uma API.Attribute routing provides a level of control that's needed to carefully design an API's public endpoint layout.

Razor Os aplicativos de páginas usam roteamento convencional padrão para atender aos recursos nomeados na pasta páginas de um aplicativo.Razor Pages apps use default conventional routing to serve named resources in the Pages folder of an app. Há convenções adicionais disponíveis que permitem personalizar o Razor comportamento de roteamento de páginas.Additional conventions are available that allow you to customize Razor Pages routing behavior. Para obter mais informações, consulte Introdução às Razor páginas no ASP.NET Core e Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core.For more information, see Introdução às Razor páginas no ASP.NET Core and Razor Direcionamento de páginas e convenções de aplicativo no ASP.NET Core.

O suporte à geração de URL permite que o aplicativo seja desenvolvido sem hard-coding das URLs para vincular o aplicativo.URL generation support allows the app to be developed without hard-coding URLs to link the app together. Esse suporte permite começar com uma configuração de roteamento básica e modificar as rotas, depois que o layout de recurso do aplicativo é determinado.This support allows for starting with a basic routing configuration and modifying the routes after the app's resource layout is determined.

O roteamento usa implementações de rotas do IRouter para:Routing uses routes implementations of IRouter to:

  • Mapear solicitações de entrada para manipuladores de rotas.Map incoming requests to route handlers.
  • Gerar as URLs usadas nas respostas.Generate the URLs used in responses.

Por padrão, um aplicativo tem uma única coleção de rotas.By default, an app has a single collection of routes. Quando uma solicitação é recebida, as rotas na coleção são processadas na ordem em que existem na coleção.When a request arrives, the routes in the collection are processed in the order that they exist in the collection. A estrutura tenta corresponder uma URL de solicitação de entrada a uma rota na coleção chamando o método RouteAsync em cada rota da coleção.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. Uma resposta pode usar o roteamento para gerar URLs (por exemplo, para redirecionamento ou links) com base nas informações de rotas e evitar URLs embutidas em código, o que ajuda na facilidade de manutenção.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.

O sistema de roteamento tem as seguintes características:The routing system has the following characteristics:

  • A sintaxe do modelo de rota é usada para definir rotas com os parâmetros de rota com tokens criados.Route template syntax is used to define routes with tokenized route parameters.
  • A configuração de ponto de extremidade de estilo convencional e de estilo de atributo é permitida.Conventional-style and attribute-style endpoint configuration is permitted.
  • IRouteConstraint é usado para determinar se um parâmetro de URL contém um valor válido para determinada restrição de ponto de extremidade.IRouteConstraint is used to determine whether a URL parameter contains a valid value for a given endpoint constraint.
  • Modelos de aplicativo, como MVC/ Razor páginas, registram todas as suas rotas, que têm uma implementação previsível de cenários de roteamento.App models, such as MVC/Razor Pages, register all of their routes, which have a predictable implementation of routing scenarios.
  • Uma resposta pode usar o roteamento para gerar URLs (por exemplo, para redirecionamento ou links) com base nas informações de rotas e evitar URLs embutidas em código, o que ajuda na facilidade de manutenção.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.
  • A geração de URL baseia-se em rotas, que dá suporte à extensibilidade arbitrária.URL generation is based on routes, which support arbitrary extensibility. IUrlHelper oferece métodos para criar URLs.IUrlHelper offers methods to build URLs.

O roteamento está conectado ao pipeline do middleware pela classe RouterMiddleware.Routing is connected to the middleware pipeline by the RouterMiddleware class. ASP.NET Core MVC adiciona o roteamento ao pipeline de middleware como parte de sua configuração e manipula o roteamento em aplicativos MVC e Razor páginas.ASP.NET Core MVC adds routing to the middleware pipeline as part of its configuration and handles routing in MVC and Razor Pages apps. Para saber como usar o roteamento como um componente autônomo, confira a seção Usar o Middleware de Roteamento.To learn how to use routing as a standalone component, see the Use Routing Middleware section.

Correspondência de URLURL matching

Correspondência de URL é o processo pelo qual o roteamento expede uma solicitação de entrada para um manipulador.URL matching is the process by which routing dispatches an incoming request to a handler. Esse processo se baseia nos dados do caminho da URL, mas pode ser estendido para considerar qualquer dado na solicitação.This process is based on data in the URL path but can be extended to consider any data in the request. A capacidade de expedir solicitações para manipuladores separados é fundamental para dimensionar o tamanho e a complexidade de um aplicativo.The ability to dispatch requests to separate handlers is key to scaling the size and complexity of an app.

As solicitações de entrada entram no RouterMiddleware, que chama o método RouteAsync em cada rota na sequência.Incoming requests enter the RouterMiddleware, which calls the RouteAsync method on each route in sequence. A instância IRouter escolhe se deseja manipular a solicitação definindo o RouteContext.Handler como um RequestDelegate não nulo.The IRouter instance chooses whether to handle the request by setting the RouteContext.Handler to a non-null RequestDelegate. Se uma rota definir um manipulador para a solicitação, o processamento de rotas será interrompido e o manipulador será invocado para processar a solicitação.If a route sets a handler for the request, route processing stops, and the handler is invoked to process the request. Se nenhum manipulador de rotas é encontrado para processar a solicitação, o middleware transmite a solicitação para o próximo middleware no pipeline de solicitação.If no route handler is found to process the request, the middleware hands the request off to the next middleware in the request pipeline.

A entrada primária para RouteAsync é o RouteContext.HttpContext associado à solicitação atual.The primary input to RouteAsync is the RouteContext.HttpContext associated with the current request. RouteContext.Handler e RouteContext.RouteData são saídas definidas depois que é encontrada uma correspondência de uma rota.The RouteContext.Handler and RouteContext.RouteData are outputs set after a route is matched.

Uma correspondência que chama RouteAsync também define as propriedades do RouteContext.RouteData com valores apropriados com base no processamento da solicitação executado até o momento.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 é um dicionário de valores de rota produzido por meio da rota.RouteData.Values is a dictionary of route values produced from the route. Esses valores geralmente são determinados pela criação de token da URL e podem ser usados para aceitar a entrada do usuário ou tomar outras decisões de expedição dentro do aplicativo.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 é um recipiente de propriedades de dados adicionais relacionados à rota correspondente.RouteData.DataTokens is a property bag of additional data related to the matched route. DataTokens são fornecidos para dar suporte à associação de dados de estado com cada rota para que o aplicativo possa tomar decisões com base em qual rota teve uma correspondência.DataTokens are provided to support associating state data with each route so that the app can make decisions based on which route matched. Esses valores são definidos pelo desenvolvedor e não afetam de forma alguma o comportamento do roteamento.These values are developer-defined and do not affect the behavior of routing in any way. Além disso, os valores em stash em RouteData.DataTokens podem ser de qualquer tipo, ao contrário de RouteData.Values, que devem ser conversíveis de/para cadeias de caracteres.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 é uma lista das rotas que participaram da correspondência bem-sucedida da solicitação.RouteData.Routers is a list of the routes that took part in successfully matching the request. As rotas podem ser aninhadas uma dentro da outra.Routes can be nested inside of one another. A propriedade Routers reflete o caminho pela árvore lógica de rotas que resultou em uma correspondência.The Routers property reflects the path through the logical tree of routes that resulted in a match. Em geral, o primeiro item em Routers é a coleção de rotas e deve ser usado para a geração de URL.Generally, the first item in Routers is the route collection and should be used for URL generation. O último item em Routers é o manipulador de rotas que teve uma correspondência.The last item in Routers is the route handler that matched.

Geração de URLURL generation

Geração de URL é o processo pelo qual o roteamento pode criar um caminho de URL de acordo com um conjunto de valores de rota.URL generation is the process by which routing can create a URL path based on a set of route values. Isso permite uma separação lógica entre os manipuladores de rotas e as URLs que os acessam.This allows for a logical separation between route handlers and the URLs that access them.

A geração de URL segue um processo iterativo semelhante, mas começa com o código da estrutura ou do usuário chamando o método GetVirtualPath da coleção de rotas.URL generation follows a similar iterative process, but it starts with user or framework code calling into the GetVirtualPath method of the route collection. Cada rota tem seu método GetVirtualPath chamado em sequência, até que um VirtualPathData não nulo seja retornado.Each route has its GetVirtualPath method called in sequence until a non-null VirtualPathData is returned.

As entradas primárias para GetVirtualPath são:The primary inputs to GetVirtualPath are:

As rotas usam principalmente os valores de rota fornecidos por Values e AmbientValues para decidir se é possível gerar uma URL e quais valores serão incluídos.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. Os AmbientValues são o conjunto de valores de rota produzidos pela correspondência da solicitação atual.The AmbientValues are the set of route values that were produced from matching the current request. Por outro lado, Values são os valores de rota que especificam como gerar a URL desejada para a operação atual.In contrast, Values are the route values that specify how to generate the desired URL for the current operation. O HttpContext é fornecido para o caso de uma rota precisar obter serviços ou dados adicionais associados ao contexto atual.The HttpContext is provided in case a route should obtain services or additional data associated with the current context.

Dica

Considere VirtualPathContext.Values como um conjunto de substituições de VirtualPathContext.AmbientValues.Think of VirtualPathContext.Values as a set of overrides for the VirtualPathContext.AmbientValues. A geração de URL tenta reutilizar os valores de rota da solicitação atual para gerar URLs para links usando a mesma rota ou os mesmos valores de rota.URL generation attempts to reuse route values from the current request to generate URLs for links using the same route or route values.

A saída de GetVirtualPath é um VirtualPathData.The output of GetVirtualPath is a VirtualPathData. VirtualPathData é um paralelo de RouteData.VirtualPathData is a parallel of RouteData. VirtualPathData contém o VirtualPath da URL de saída e algumas propriedades adicionais que devem ser definidas pela rota.VirtualPathData contains the VirtualPath for the output URL and some additional properties that should be set by the route.

A propriedade VirtualPathData.VirtualPath contém o caminho virtual produzido pela rota.The VirtualPathData.VirtualPath property contains the virtual path produced by the route. Dependendo das suas necessidades, talvez você precise processar ainda mais o caminho.Depending on your needs, you may need to process the path further. Se você desejar renderizar a URL gerada em HTML, preceda o caminho base do aplicativo.If you want to render the generated URL in HTML, prepend the base path of the app.

O VirtualPathData.Router é uma referência à rota que gerou a URL com êxito.The VirtualPathData.Router is a reference to the route that successfully generated the URL.

As propriedades de VirtualPathData.DataTokens são um dicionário de dados adicionais relacionados à rota que gerou a URL.The VirtualPathData.DataTokens properties is a dictionary of additional data related to the route that generated the URL. Isso é o paralelo de RouteData.DataTokens.This is the parallel of RouteData.DataTokens.

Criar rotasCreate routes

O roteamento fornece a classe Route como a implementação padrão de IRouter.Routing provides the Route class as the standard implementation of IRouter. Route usa a sintaxe de modelo de rota para definir padrões que corresponderão ao caminho da URL quando RouteAsync for chamado.Route uses the route template syntax to define patterns to match against the URL path when RouteAsync is called. Route usa o mesmo modelo de rota para gerar uma URL quando GetVirtualPath é chamado.Route uses the same route template to generate a URL when GetVirtualPath is called.

A maioria dos aplicativos cria rotas chamando MapRoute ou um dos métodos de extensão semelhantes definidos em IRouteBuilder.Most apps create routes by calling MapRoute or one of the similar extension methods defined on IRouteBuilder. Qualquer um dos métodos de extensão de IRouteBuilder cria uma instância de Route e a adicionam à coleção de rotas.Any of the IRouteBuilder extension methods create an instance of Route and add it to the route collection.

MapRoute não aceita um parâmetro de manipulador de rotas.MapRoute doesn't accept a route handler parameter. MapRoute apenas adiciona rotas que são manipuladas pelo DefaultHandler.MapRoute only adds routes that are handled by the DefaultHandler. O manipulador padrão é um IRouter, e o manipulador não pode manipular a solicitação.The default handler is an IRouter, and the handler might not handle the request. Por exemplo, o ASP.NET Core MVC normalmente é configurado como um manipulador padrão que só manipula as solicitações que correspondem a um controlador e a uma ação disponíveis.For example, ASP.NET Core MVC is typically configured as a default handler that only handles requests that match an available controller and action. Para saber mais sobre o roteamento no MVC, confira Roteamento para ações do controlador no ASP.NET Core.To learn more about routing in MVC, see Roteamento para ações do controlador no ASP.NET Core.

O exemplo de código a seguir é um exemplo de uma chamada MapRoute usada por uma definição de rota típica do 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?}");

Esse modelo corresponde a um caminho de URL e extrai os valores de rota.This template matches a URL path and extracts the route values. Por exemplo, o caminho /Products/Details/17 gera os seguintes valores de rota: { controller = Products, action = Details, id = 17 }.For example, the path /Products/Details/17 generates the following route values: { controller = Products, action = Details, id = 17 }.

Os valores de rota são determinados pela divisão do caminho da URL em segmentos e pela correspondência de cada segmento com o nome do parâmetro de rota no modelo de rota.Route values are determined by splitting the URL path into segments and matching each segment with the route parameter name in the route template. Os parâmetros de rota são nomeados.Route parameters are named. Os parâmetros são definidos com a colocação do nome do parâmetro em chaves { ... }.The parameters defined by enclosing the parameter name in braces { ... }.

O modelo anterior também pode corresponder ao caminho da URL / e produzir os valores { controller = Home, action = Index }.The preceding template could also match the URL path / and produce the values { controller = Home, action = Index }. Isso ocorre porque os parâmetros de rota {controller} e {action} têm valores padrão e o parâmetro de rota id é opcional.This occurs because the {controller} and {action} route parameters have default values and the id route parameter is optional. Um sinal de igual (=) seguido de um valor após o nome do parâmetro de rota define um valor padrão para o parâmetro.An equals sign (=) followed by a value after the route parameter name defines a default value for the parameter. Um ponto de interrogação (?) após o nome do parâmetro de rota define o parâmetro como opcional.A question mark (?) after the route parameter name defines an optional parameter.

Os parâmetros de rota com um valor padrão sempre produzem um valor de rota quando a rota corresponde.Route parameters with a default value always produce a route value when the route matches. Os parâmetros opcionais não produzem um valor de rota se não houver nenhum segmento de caminho de URL correspondente.Optional parameters don't produce a route value if there is no corresponding URL path segment. Confira a seção Referência de modelo de rota para obter uma descrição completa dos recursos e da sintaxe de modelo de rota.See the Route template reference section for a thorough description of route template scenarios and syntax.

No seguinte exemplo, a definição do parâmetro de rota {id:int} define uma restrição de rota para o parâmetro de rota 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}");

Esse modelo corresponde a um caminho de URL, como /Products/Details/17, mas não como /Products/Details/Apples.This template matches a URL path like /Products/Details/17 but not /Products/Details/Apples. As restrições de rota implementam IRouteConstraint e inspecionam valores de rota para verificá-los.Route constraints implement IRouteConstraint and inspect route values to verify them. Neste exemplo, o valor de rota id precisa ser conversível em um inteiro.In this example, the route value id must be convertible to an integer. Confira route-constraint-reference para obter uma explicação das restrições de rota fornecidas pela estrutura.See route-constraint-reference for an explanation of route constraints provided by the framework.

Sobrecargas adicionais de MapRoute aceitam valores para constraints, dataTokens e defaults.Additional overloads of MapRoute accept values for constraints, dataTokens, and defaults. O uso típico desses parâmetros é passar um objeto de tipo anônimo, no qual os nomes da propriedade do tipo anônimo correspondem aos nomes do parâmetro de rota.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.

Os seguintes exemplos de MapRoute criam rotas equivalentes: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?}");

Dica

A sintaxe embutida para a definição de restrições e padrões pode ser interessante para rotas simples.The inline syntax for defining constraints and defaults can be convenient for simple routes. No entanto, há cenários, como tokens de dados, que não dão suporte à sintaxe embutida.However, there are scenarios, such as data tokens, that aren't supported by inline syntax.

O seguinte exemplo demonstra mais alguns cenários:The following example demonstrates a few additional scenarios:

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

O modelo anterior corresponde a um caminho de URL, como /Blog/All-About-Routing/Introduction, e extrai os valores { 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 }. Os valores de rota padrão para controller e action são produzidos pela rota, mesmo que não haja nenhum parâmetro de rota correspondente no modelo.The default route values for controller and action are produced by the route even though there are no corresponding route parameters in the template. Os valores padrão podem ser especificados no modelo de rota.Default values can be specified in the route template. O parâmetro de rota article é definido como um catch-all pela aparência de um asterisco (*) antes do nome do parâmetro de rota.The article route parameter is defined as a catch-all by the appearance of an asterisk (*) before the route parameter name. Os parâmetros de rota catch-all capturam o restante do caminho de URL e também podem corresponder à cadeia de caracteres vazia.Catch-all route parameters capture the remainder of the URL path and can also match the empty string.

O seguinte exemplo adiciona restrições de rota e tokens de dados: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" });

O modelo anterior corresponde a um caminho de URL como /en-US/Products/5 e extrai os valores de { controller = Products, action = Details, id = 5 } e os tokens de dados { 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 }.

Tokens locais do Windows

Geração de URL da classe de rotaRoute class URL generation

A classe Route também pode executar a geração de URL pela combinação de um conjunto de valores de rota com seu modelo de rota.The Route class can also perform URL generation by combining a set of route values with its route template. Logicamente, este é o processo inverso de correspondência do caminho de URL.This is logically the reverse process of matching the URL path.

Dica

Para entender melhor a geração de URL, imagine qual URL você deseja gerar e, em seguida, pense em como um modelo de rota corresponderia a essa 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. Quais valores serão produzidos?What values would be produced? Este é o equivalente aproximado de como funciona a geração de URL na classe Route.This is the rough equivalent of how URL generation works in the Route class.

O seguinte exemplo usa uma rota padrão geral do 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?}");

Com os valores de rota { controller = Products, action = List }, a URL /Products/List é gerada.With the route values { controller = Products, action = List }, the URL /Products/List is generated. Os valores de rota são substituídos pelos parâmetros de rota correspondentes para formar o caminho de URL.The route values are substituted for the corresponding route parameters to form the URL path. Como id é um parâmetro de rota opcional, a URL é gerada com êxito sem um valor para id.Since id is an optional route parameter, the URL is successfully generated without a value for id.

Com os valores de rota { controller = Home, action = Index }, a URL / é gerada.With the route values { controller = Home, action = Index }, the URL / is generated. Os valores de rota fornecidos correspondem aos valores padrão, sendo que os segmentos correspondentes aos valores padrão são omitidos com segurança.The provided route values match the default values, and the segments corresponding to the default values are safely omitted.

A viagem de ida e volta gerada pelas duas URLs com a definição de rota a seguir (/Home/Index e /) produz os mesmos valores de rota que foram usados para gerar a 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.

Observação

Um aplicativo que usa o ASP.NET Core MVC deve usar UrlHelper para gerar URLs, em vez de chamar o roteamento diretamente.An app using ASP.NET Core MVC should use UrlHelper to generate URLs instead of calling into routing directly.

Para obter mais informações sobre a geração de URL, confira a seção Referência de geração de URL.For more information on URL generation, see the Url generation reference section.

Usar middleware de roteamentoUse routing middleware

Referencie o metapacote Microsoft.AspNetCore.App no arquivo de projeto do aplicativo.Reference the Microsoft.AspNetCore.App metapackage in the app's project file.

Adicione o roteamento ao contêiner de serviço em Startup.ConfigureServices:Add routing to the service container in Startup.ConfigureServices:

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

As rotas precisam ser configuradas no método Startup.Configure.Routes must be configured in the Startup.Configure method. O aplicativo de exemplo usa as seguintes APIs: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);

A tabela a seguir mostra as respostas com os URIs fornecidos.The following table shows the responses with the given URIs.

URIURI RespostaResponse
/package/create/3 Olá!Hello! Valores de rota: [operation, create], [id, 3]Route values: [operation, create], [id, 3]
/package/track/-3 Olá!Hello! Valores de rota: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/-3/ Olá!Hello! Valores de rota: [operation, track], [id, -3]Route values: [operation, track], [id, -3]
/package/track/ A solicitação é ignorada; sem correspondência.The request falls through, no match.
GET /hello/Joe Olá, Joe!Hi, Joe!
POST /hello/Joe A solicitação é ignorada; corresponde apenas a HTTP GET.The request falls through, matches HTTP GET only.
GET /hello/Joe/Smith A solicitação é ignorada; sem correspondência.The request falls through, no match.

Se você estiver configurando uma única rota, chame UseRouter passando uma instância de IRouter.If you're configuring a single route, call UseRouter passing in an IRouter instance. Você não precisa usar RouteBuilder.You won't need to use RouteBuilder.

A estrutura fornece um conjunto de métodos de extensão para a criação de rotas (RequestDelegateRouteBuilderExtensions):The framework provides a set of extension methods for creating routes (RequestDelegateRouteBuilderExtensions):

Alguns dos métodos listados, como MapGet, exigem um RequestDelegate.Some of listed methods, such as MapGet, require a RequestDelegate. O RequestDelegate é usado como o manipulador de rotas quando a rota corresponde.The RequestDelegate is used as the route handler when the route matches. Outros métodos nesta família permitem configurar um pipeline de middleware a ser usado como o manipulador de rotas.Other methods in this family allow configuring a middleware pipeline for use as the route handler. Se o método Map* não aceitar um manipulador, como MapRoute, ele usará o DefaultHandler.If the Map* method doesn't accept a handler, such as MapRoute, it uses the DefaultHandler.

Os métodos Map[Verb] usam restrições para limitar a rota ao Verbo HTTP no nome do método.The Map[Verb] methods use constraints to limit the route to the HTTP Verb in the method name. Por exemplo, veja MapGet e MapVerb.For example, see MapGet and MapVerb.

Referência de modelo de rotaRoute template reference

Os tokens entre chaves ({ ... }) definem os parâmetros de rota que serão associados se a rota for correspondida.Tokens within curly braces ({ ... }) define route parameters that are bound if the route is matched. Você pode definir mais de um parâmetro de rota em um segmento de rota, mas eles precisam ser separados por um valor literal.You can define more than one route parameter in a route segment, but they must be separated by a literal value. Por exemplo, {controller=Home}{action=Index} não é uma rota válida, já que não há nenhum valor literal entre {controller} e {action}.For example, {controller=Home}{action=Index} isn't a valid route, since there's no literal value between {controller} and {action}. Esses parâmetros de rota precisam ter um nome e podem ter atributos adicionais especificados.These route parameters must have a name and may have additional attributes specified.

Um texto literal diferente dos parâmetros de rota (por exemplo, {id}) e do separador de caminho / precisa corresponder ao texto na URL.Literal text other than route parameters (for example, {id}) and the path separator / must match the text in the URL. A correspondência de texto não diferencia maiúsculas de minúsculas e se baseia na representação decodificada do caminho de URLs.Text matching is case-insensitive and based on the decoded representation of the URLs path. Para encontrar a correspondência de um delimitador de parâmetro de rota literal ({ ou }), faça o escape do delimitador repetindo o caractere ({{ ou }}).To match a literal route parameter delimiter ({ or }), escape the delimiter by repeating the character ({{ or }}).

Padrões de URL que tentam capturar um nome de arquivo com uma extensão de arquivo opcional apresentam considerações adicionais.URL patterns that attempt to capture a file name with an optional file extension have additional considerations. Por exemplo, considere o modelo files/{filename}.{ext?}.For example, consider the template files/{filename}.{ext?}. Quando existem valores para filename e ext, ambos os valores são populados.When values for both filename and ext exist, both values are populated. Se apenas existir um valor para filename na URL, a rota encontrará uma correspondência, pois o ponto à direita (.) é opcional.If only a value for filename exists in the URL, the route matches because the trailing period (.) is optional. As URLs a seguir correspondem a essa rota:The following URLs match this route:

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

Você pode usar o asterisco (*) como um prefixo para um parâmetro de rota a ser associado ao restante do URI.You can use the asterisk (*) as a prefix to a route parameter to bind to the rest of the URI. Isso é chamado de parâmetro catch-all.This is called a catch-all parameter. Por exemplo, blog/{*slug} corresponde a qualquer URI que começa com /blog e tem qualquer valor depois dele, que é atribuído ao valor de rota 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. Os parâmetros catch-all também podem corresponder à cadeia de caracteres vazia.Catch-all parameters can also match the empty string.

O parâmetro catch-all faz o escape dos caracteres corretos quando a rota é usada para gerar uma URL, incluindo os caracteres separadores de caminho (/).The catch-all parameter escapes the appropriate characters when the route is used to generate a URL, including path separator (/) characters. Por exemplo, a rota foo/{*path} com valores de rota { path = "my/path" } gera foo/my%2Fpath.For example, the route foo/{*path} with route values { path = "my/path" } generates foo/my%2Fpath. Observe o escape da barra invertida.Note the escaped forward slash.

Os parâmetros de rota podem ter valores padrão , designados pela especificação do valor padrão após o nome do parâmetro separado por um sinal de igual (=).Route parameters may have default values designated by specifying the default value after the parameter name separated by an equals sign (=). Por exemplo, {controller=Home} define Home como o valor padrão de controller.For example, {controller=Home} defines Home as the default value for controller. O valor padrão é usado se nenhum valor está presente na URL para o parâmetro.The default value is used if no value is present in the URL for the parameter. Os parâmetros de rota se tornam opcionais com o acréscimo de um ponto de interrogação (?) ao final do nome do parâmetro, como em id?.Route parameters are made optional by appending a question mark (?) to the end of the parameter name, as in id?. A diferença entre valores opcionais e parâmetros de rota padrão é que um parâmetro de rota com um valor padrão sempre produz um valor – um parâmetro opcional tem um valor somente quando um valor é fornecido pela URL de solicitação.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.

Os parâmetros de rota podem ter restrições que precisam corresponder ao valor de rota associado da URL.Route parameters may have constraints that must match the route value bound from the URL. A adição de dois-pontos (:) e do nome da restrição após o nome do parâmetro de rota especifica uma restrição embutida em um parâmetro de rota.Adding a colon (:) and constraint name after the route parameter name specifies an inline constraint on a route parameter. Se a restrição exigir argumentos, eles ficarão entre parênteses ((...)) após o nome da restrição.If the constraint requires arguments, they're enclosed in parentheses ((...)) after the constraint name. Várias restrições embutidas podem ser especificadas por meio do acréscimo de outros dois-pontos (:) e do nome da restrição.Multiple inline constraints can be specified by appending another colon (:) and constraint name.

O nome da restrição e os argumentos são passados para o serviço IInlineConstraintResolver para criar uma instância de IRouteConstraint a ser usada no processamento de URL.The constraint name and arguments are passed to the IInlineConstraintResolver service to create an instance of IRouteConstraint to use in URL processing. Por exemplo, o modelo de rota blog/{article:minlength(10)} especifica uma restrição minlength com o argumento 10.For example, the route template blog/{article:minlength(10)} specifies a minlength constraint with the argument 10. Para obter mais informações sobre as restrições de rota e uma lista das restrições fornecidas pela estrutura, confira a seção Referência de restrição de rota.For more information on route constraints and a list of the constraints provided by the framework, see the Route constraint reference section.

A tabela a seguir demonstra modelos de rota de exemplo e seu comportamento.The following table demonstrates example route templates and their behavior.

Modelo de rotaRoute Template URI de correspondência de exemploExample Matching URI O URI de solicitação…The request URI…
hello /hello Somente corresponde ao caminho único /hello.Only matches the single path /hello.
{Page=Home} / Faz a correspondência e define Page como Home.Matches and sets Page to Home.
{Page=Home} /Contact Faz a correspondência e define Page como Contact.Matches and sets Page to Contact.
{controller}/{action}/{id?} /Products/List É mapeado para o controlador Products e a ação List.Maps to the Products controller and List action.
{controller}/{action}/{id?} /Products/Details/123 É mapeado para o controlador Products e a ação Details (id definido como 123).Maps to the Products controller and Details action (id set to 123).
{controller=Home}/{action=Index}/{id?} / É mapeado para o controlador Home e o método Index (id é ignorado).Maps to the Home controller and Index method (id is ignored).

Em geral, o uso de um modelo é a abordagem mais simples para o roteamento.Using a template is generally the simplest approach to routing. Restrições e padrões também podem ser especificados fora do modelo de rota.Constraints and defaults can also be specified outside the route template.

Dica

Habilite o Log para ver como as implementações de roteamento internas, como Route, correspondem às solicitações.Enable Logging to see how the built-in routing implementations, such as Route, match requests.

Referência de restrição de rotaRoute constraint reference

As restrições de rota são executadas quando ocorre uma correspondência com a URL de entrada e é criado um token do caminho da URL em valores de rota.Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values. Em geral, as restrições da rota inspecionam o valor de rota associado por meio do modelo de rota e tomam uma decisão do tipo "sim/não" sobre se o valor é aceitável ou não.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. Algumas restrições da rota usam dados fora do valor de rota para considerar se a solicitação pode ser encaminhada.Some route constraints use data outside the route value to consider whether the request can be routed. Por exemplo, a HttpMethodRouteConstraint pode aceitar ou rejeitar uma solicitação de acordo com o verbo HTTP.For example, the HttpMethodRouteConstraint can accept or reject a request based on its HTTP verb. As restrições são usadas em solicitações de roteamento e na geração de link.Constraints are used in routing requests and link generation.

Aviso

Não use restrições para a validação de entrada.Don't use constraints for input validation. Se as restrições forem usadas para a validação de entrada , uma entrada inválida resultará em uma resposta 404 – Não Encontrado , em vez de 400 – Solicitação Inválida com uma mensagem de erro apropriada.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. As restrições de rota são usadas para desfazer a ambiguidade entre rotas semelhantes, não para validar as entradas de uma rota específica.Route constraints are used to disambiguate similar routes, not to validate the inputs for a particular route.

A tabela a seguir demonstra restrições de rota de exemplo e seu comportamento esperado.The following table demonstrates example route constraints and their expected behavior.

restriçãoconstraint ExemploExample Correspondências de exemploExample Matches ObservaçõesNotes
int {id:int} 123456789, -123456789123456789, -123456789 Corresponde a qualquer inteiroMatches any integer
bool {active:bool} true, FALSEtrue, FALSE Corresponde a true ou false (não diferencia maiúsculas de minúsculas)Matches true or false (case-insensitive)
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm2016-12-31, 2016-12-31 7:32pm Corresponde a um DateTime valor válido na cultura invariável.Matches a valid DateTime value in the invariant culture. Consulte o aviso anterior.See preceding warning.
decimal {price:decimal} 49.99, -1,000.0149.99, -1,000.01 Corresponde a um decimal valor válido na cultura invariável.Matches a valid decimal value in the invariant culture. Consulte o aviso anterior.See preceding warning.
double {weight:double} 1.234, -1,001.01e81.234, -1,001.01e8 Corresponde a um double valor válido na cultura invariável.Matches a valid double value in the invariant culture. Consulte o aviso anterior.See preceding warning.
float {weight:float} 1.234, -1,001.01e81.234, -1,001.01e8 Corresponde a um float valor válido na cultura invariável.Matches a valid float value in the invariant culture. Consulte o aviso anterior.See preceding warning.
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638}CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} Corresponde a um valor Guid válidoMatches a valid Guid value
long {ticks:long} 123456789, -123456789123456789, -123456789 Corresponde a um valor long válidoMatches a valid long value
minlength(value) {username:minlength(4)} Rick A cadeia de caracteres deve ter, no mínimo, 4 caracteresString must be at least 4 characters
maxlength(value) {filename:maxlength(8)} Richard A cadeia de caracteres não pode ser maior que 8 caracteresString must be no more than 8 characters
length(length) {filename:length(12)} somefile.txt A cadeia de caracteres deve ter exatamente 12 caracteresString must be exactly 12 characters long
length(min,max) {filename:length(8,16)} somefile.txt A cadeia de caracteres deve ter, pelo menos, 8 e não mais de 16 caracteresString must be at least 8 and no more than 16 characters long
min(value) {age:min(18)} 19 O valor inteiro deve ser, pelo menos, 18Integer value must be at least 18
max(value) {age:max(120)} 91 O valor inteiro não deve ser maior que 120Integer value must be no more than 120
range(min,max) {age:range(18,120)} 91 O valor inteiro deve ser, pelo menos, 18, mas não maior que 120Integer value must be at least 18 but no more than 120
alpha {name:alpha} Rick A cadeia de caracteres deve consistir em um ou mais caracteres alfabéticos (a-z, não diferencia maiúsculas de minúsculas)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 A cadeia de caracteres deve corresponder à expressão regular (veja as dicas sobre como definir uma expressão regular)String must match the regular expression (see tips about defining a regular expression)
required {name:required} Rick Usado para impor que um valor não parâmetro está presente durante a geração de URLUsed to enforce that a non-parameter value is present during URL generation

Várias restrições delimitadas por vírgula podem ser aplicadas a um único parâmetro.Multiple, colon-delimited constraints can be applied to a single parameter. Por exemplo, a restrição a seguir restringe um parâmetro para um valor inteiro de 1 ou maior: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) { }

Aviso

As restrições de rota que verificam a URL e são convertidas em um tipo CLR (como int ou DateTime) sempre usam a cultura invariável.Route constraints that verify the URL and are converted to a CLR type (such as int or DateTime) always use the invariant culture. Essas restrições consideram que a URL não é localizável.These constraints assume that the URL is non-localizable. As restrições de rota fornecidas pela estrutura não modificam os valores armazenados nos valores de rota.The framework-provided route constraints don't modify the values stored in route values. Todos os valores de rota analisados com base na URL são armazenados como cadeias de caracteres.All route values parsed from the URL are stored as strings. Por exemplo, a restrição float tenta converter o valor de rota em um float, mas o valor convertido é usado somente para verificar se ele pode ser convertido em um 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.

Expressões regularesRegular expressions

A estrutura do ASP.NET Core adiciona RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant ao construtor de expressão regular.The ASP.NET Core framework adds RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant to the regular expression constructor. Confira RegexOptions para obter uma descrição desses membros.See RegexOptions for a description of these members.

As expressões regulares usam delimitadores e tokens semelhantes aos usados pelo Roteamento e pela linguagem C#.Regular expressions use delimiters and tokens similar to those used by Routing and the C# language. Os tokens de expressão regular precisam ter escape.Regular expression tokens must be escaped. Para usar a expressão regular ^\d{3}-\d{2}-\d{4}$ no roteamento, a expressão precisa ter os caracteres \ (barra invertida) fornecidos na cadeia de caracteres como caracteres \\ (barra invertida dupla) no arquivo de origem C# para fazer o escape do caractere de escape da cadeia de caracteres \ (a menos que estejam sendo usados literais de cadeia de caracteres textuais).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). Para fazer o escape dos caracteres de delimitador de parâmetro de roteamento ({, }, [, ]), duplique os caracteres na expressão ({{, }, [[, ]]).To escape routing parameter delimiter characters ({, }, [, ]), double the characters in the expression ({{, }, [[, ]]). A tabela a seguir mostra uma expressão regular e a versão com escape.The following table shows a regular expression and the escaped version.

Expressão regularRegular Expression Expressão regular com escapeEscaped Regular Expression
^\d{3}-\d{2}-\d{4}$ ^\\d{{3}}-\\d{{2}}-\\d{{4}}$
^[a-z]{2}$ ^[[a-z]]{{2}}$

As expressões regulares usadas no roteamento geralmente começam com o caractere de acento circunflexo (^) e correspondem à posição inicial da cadeia de caracteres.Regular expressions used in routing often start with the caret (^) character and match starting position of the string. As expressões geralmente terminam com o caractere de cifrão ($) e correspondem ao final da cadeia de caracteres.The expressions often end with the dollar sign ($) character and match end of the string. Os caracteres ^ e $ garantem que a expressão regular corresponde a todo o valor do parâmetro de rota.The ^ and $ characters ensure that the regular expression match the entire route parameter value. Sem os caracteres ^ e $, a expressão regular corresponde a qualquer subcadeia de caracteres na cadeia de caracteres, o que geralmente não é o desejado.Without the ^ and $ characters, the regular expression match any substring within the string, which is often undesirable. A tabela a seguir fornece exemplos e explica por que eles encontram ou não uma correspondência.The following table provides examples and explains why they match or fail to match.

ExpressionExpression StringString Corresponder aMatch ComentárioComment
[a-z]{2} hellohello SimYes A subcadeia de caracteres correspondeSubstring matches
[a-z]{2} 123abc456123abc456 SimYes A subcadeia de caracteres correspondeSubstring matches
[a-z]{2} mzmz SimYes Corresponde à expressãoMatches expression
[a-z]{2} MZMZ SimYes Não diferencia maiúsculas de minúsculasNot case sensitive
^[a-z]{2}$ hellohello NãoNo Confira ^ e $ acimaSee ^ and $ above
^[a-z]{2}$ 123abc456123abc456 NãoNo Confira ^ e $ acimaSee ^ and $ above

Para saber mais sobre a sintaxe de expressões regulares, confira Expressões regulares do .NET Framework.For more information on regular expression syntax, see .NET Framework Regular Expressions.

Para restringir um parâmetro a um conjunto conhecido de valores possíveis, use uma expressão regular.To constrain a parameter to a known set of possible values, use a regular expression. Por exemplo, {action:regex(^(list|get|create)$)} apenas corresponde o valor da rota action a list, get ou create.For example, {action:regex(^(list|get|create)$)} only matches the action route value to list, get, or create. Se passada para o dicionário de restrições, a cadeia de caracteres ^(list|get|create)$ é equivalente.If passed into the constraints dictionary, the string ^(list|get|create)$ is equivalent. As restrições passadas para o dicionário de restrições (não embutidas em um modelo) que não correspondem a uma das restrições conhecidas também são tratadas como expressões regulares.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.

Restrições de rota personalizadasCustom Route Constraints

Além das restrições de rota internas, é possível criar restrições de rota personalizadas com a implementação da interface do IRouteConstraint.In addition to the built-in route constraints, custom route constraints can be created by implementing the IRouteConstraint interface. A interface do IRouteConstraint contém um único método, Match, que retorna true quando a restrição é satisfeita. Caso contrário, retorna false.The IRouteConstraint interface contains a single method, Match, which returns true if the constraint is satisfied and false otherwise.

Para usar uma IRouteConstraint personalizada, o tipo de restrição de rota deve ser registrado com o ConstraintMap do aplicativo, no contêiner de serviço do aplicativo.To use a custom IRouteConstraint, the route constraint type must be registered with the app's ConstraintMap in the app's service container. O ConstraintMap é um dicionário que mapeia as chaves de restrição de rota para implementações de IRouteConstraint que validam essas restrições.A ConstraintMap is a dictionary that maps route constraint keys to IRouteConstraint implementations that validate those constraints. É possível atualizar o ConstraintMap do aplicativo no Startup.ConfigureServices como parte de uma chamada services.AddRouting ou configurando RouteOptions diretamente com 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>. Por exemplo:For example:

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

a restrição pode então ser aplicada às rotas da maneira usual, usando o nome especificado ao registrar o tipo de restrição.The constraint can then be applied to routes in the usual manner, using the name specified when registering the constraint type. Por exemplo:For example:

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

Referência de geração de URLURL generation reference

O exemplo a seguir mostra como gerar um link para uma rota com base em um dicionário de valores de rota e em um 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/>");
});

O VirtualPath gerado no final do exemplo anterior é /package/create/123.The VirtualPath generated at the end of the preceding sample is /package/create/123. O dicionário fornece os valores de rota operation e id do modelo "Rastrear rota do pacote", package/{operation}/{id}.The dictionary supplies the operation and id route values of the "Track Package Route" template, package/{operation}/{id}. Para obter detalhes, consulte o código de exemplo na seção Usar o middleware de roteamento ou no aplicativo de exemplo.For details, see the sample code in the Use Routing Middleware section or the sample app.

O segundo parâmetro para o construtor VirtualPathContext é uma coleção de valores de ambiente.The second parameter to the VirtualPathContext constructor is a collection of ambient values. Os valores de ambiente são convenientes de serem usados porque limitam o número de valores que um desenvolvedor precisa especificar em um contexto de solicitação.Ambient values are convenient to use because they limit the number of values a developer must specify within a request context. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link.The current route values of the current request are considered ambient values for link generation. Na ação About de um aplicativo ASP.NET Core MVC do HomeController, não é necessário especificar o valor de rota do controlador a ser vinculado à ação Index – o valor de ambiente Home é usado.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.

Os valores de ambiente que não correspondem a um parâmetro são ignorados.Ambient values that don't match a parameter are ignored. Os valores de ambiente também são ignorados quando um valor fornecido explicitamente substitui o valor de ambiente.Ambient values are also ignored when an explicitly provided value overrides the ambient value. A correspondência ocorre da esquerda para a direita na URL.Matching occurs from left to right in the URL.

Valores fornecidos explicitamente, mas que não correspondem a um segmento da rota, são adicionados à cadeia de consulta.Values explicitly provided but that don't match a segment of the route are added to the query string. A tabela a seguir mostra o resultado do uso do modelo de rota {controller}/{action}/{id?}.The following table shows the result when using the route template {controller}/{action}/{id?}.

Valores de ambienteAmbient Values Valores explícitosExplicit Values ResultResult
controlador = "Home"controller = "Home" ação = "About"action = "About" /Home/About
controlador = "Home"controller = "Home" controlador = "Order", ação = "About"controller = "Order", action = "About" /Order/About
controlador = "Home", cor = "Red"controller = "Home", color = "Red" ação = "About"action = "About" /Home/About
controlador = "Home"controller = "Home" ação = "About", cor = "Red"action = "About", color = "Red" /Home/About?color=Red

Se uma rota tem um valor padrão que não corresponde a um parâmetro e esse valor é fornecido de forma explícita, ele precisa corresponder ao valor padrão: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" });

A geração de link somente gera um link para essa rota quando os valores correspondentes de controller e action são fornecidos.Link generation only generates a link for this route when the matching values for controller and action are provided.

Segmentos complexosComplex segments

Segmentos complexos (por exemplo, [Route("/x{token}y")]) são processados por meio da combinação de literais da direita para a esquerda, de uma maneira diferente de Greedy.Complex segments (for example [Route("/x{token}y")]) are processed by matching up literals from right to left in a non-greedy way. Confira este código para ver uma explicação detalhada de como os segmentos complexos são combinados.See this code for a detailed explanation of how complex segments are matched. O exemplo de código não é usado pelo ASP.NET Core, mas fornece uma explicação adequada sobre segmentos complexos.The code sample is not used by ASP.NET Core, but it provides a good explanation of complex segments.