Partilhar via


Convenções de rota e aplicativo do Razor Pages no ASP.NET Core

Saiba como usar a página convenções do provedor de modelo de rota e aplicativo para controlar o roteamento, a descoberta e o processamento de páginas nos aplicativos Razor Pages.

Para especificar uma rota de página, adicionar segmentos de rota ou adicionar parâmetros a uma rota, use a diretiva @page da página. Para obter mais informações, confira Rotas personalizadas.

Há palavras reservadas que não podem ser usadas como segmentos de rota ou nomes de parâmetros. Para obter mais informações, confira Roteamento: nomes de roteamento reservados.

Exibir ou baixar código de exemplo (como baixar)

Cenário O exemplo demonstra
Convenções de modelo

Conventions.Add
Adicione um cabeçalho e um modelo de rota às páginas de um aplicativo.
Convenções de ação da rota de página Adicione um modelo de rota às páginas em uma pasta e a uma única página.
Convenções de ação do modelo de página Adicione um cabeçalho às páginas em uma pasta, adicione um cabeçalho a uma única página e configure um alocador de filtro para adicionar um cabeçalho às páginas de um aplicativo.

As convenções do Razor Pages são configuradas usando uma sobrecarga AddRazorPages que configura RazorPagesOptions. Os exemplos de convenção a seguir estão descritos mais adiante neste tópico:


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages(options =>
    {
        options.Conventions.Add( ... );
        options.Conventions.AddFolderRouteModelConvention(
            "/OtherPages", model => { ... });
        options.Conventions.AddPageRouteModelConvention(
            "/About", model => { ... });
        options.Conventions.AddPageRoute(
            "/Contact", "TheContactPage/{text?}");
        options.Conventions.AddFolderApplicationModelConvention(
            "/OtherPages", model => { ... });
        options.Conventions.AddPageApplicationModelConvention(
            "/About", model => { ... });
        options.Conventions.ConfigureFilter(model => { ... });
        options.Conventions.ConfigureFilter( ... );
    });
}

Ordem de rota

As rotas especificam um Order para processamento (correspondência de rotas).

Ordem de rota Comportamento
-1 A rota é processada antes que outras rotas sejam processadas.
0 A ordem não é especificada (valor padrão). A não atribuição Order (Order = null) define a rota Order como 0 (zero) por padrão para processamento.
1, 2, … n Especifica a ordem de processamento de rota.

O processamento de rotas é estabelecido por convenção:

  • As rotas são processadas em ordem sequencial (-1, 0, 1, 2, ... n).
  • Quando as rotas têm o mesmo Order, a rota mais específica é correspondida primeiro, seguida por rotas menos específicas.
  • Quando as rotas com o mesmo Order e o mesmo número de parâmetros correspondem a uma URL de solicitação, as rotas são processadas na ordem em que são adicionadas a PageConventionCollection.

Se possível, evite depender de uma ordem de processamento de rota estabelecida. Em geral, o roteamento seleciona a rota correta com correspondência de URL. Se você precisar definir propriedades Order de rota para rotear solicitações corretamente, o esquema de roteamento do aplicativo provavelmente será confuso para os clientes e de frágil manutenção. Procure simplificar o esquema de roteamento do aplicativo. O aplicativo de exemplo requer uma ordem de processamento de rota explícita para demonstrar vários cenários de roteamento usando um único aplicativo. No entanto, você deve tentar evitar a prática de definir a rota Order em aplicativos de produção.

O roteamento do Razor Pages e o roteamento de controlador do MVC compartilham uma implementação. As informações sobre a ordem de rota nos tópicos do MVC estão disponíveis em Roteamento para ações do controlador: ordenando as rotas de atributo.

Convenções de modelo

Adicione um representante para IPageConvention a fim de adicionar convenções de modelo que se aplicam ao Razor Pages.

Adicionar uma convenção de modelo de rota a todas as páginas

Use Conventions para criar e adicionar um IPageRouteModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo de rota de página.

O aplicativo de exemplo contém a classe GlobalTemplatePageRouteModelConvention para adicionar um modelo de rota {globalTemplate?} a todas as páginas do aplicativo:

using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace SampleApp.Conventions;

public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        var selectorCount = model.Selectors.Count;
        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];
            model.Selectors.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Order = 1,
                    Template = AttributeRouteModel.CombineTemplates(
                        selector.AttributeRouteModel!.Template, 
                        "{globalTemplate?}"),
                }
            });
        }
    }
}

No código anterior:

As opções do Razor Pages, como adicionar Conventions, são adicionadas quando o Razor Pages é adicionado à coleção de serviços. Para obter um exemplo, confira o aplicativo de exemplo.

using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.EntityFrameworkCore;
using SampleApp.Conventions;
using SampleApp.Data;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<AppDbContext>(options =>
                                   options.UseInMemoryDatabase("InMemoryDb"));

builder.Services.AddRazorPages(options =>
   {
       options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

       options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
       {
           var selectorCount = model.Selectors.Count;
           for (var i = 0; i < selectorCount; i++)
           {
               var selector = model.Selectors[i];
               model.Selectors.Add(new SelectorModel
               {
                   AttributeRouteModel = new AttributeRouteModel
                   {
                       Order = 2,
                       Template = AttributeRouteModel.CombineTemplates(
                           selector.AttributeRouteModel!.Template,
                           "{otherPagesTemplate?}"),
                   }
               });
           }
       });

       options.Conventions.AddPageRouteModelConvention("/About", model =>
       {
           var selectorCount = model.Selectors.Count;
           for (var i = 0; i < selectorCount; i++)
           {
               var selector = model.Selectors[i];
               model.Selectors.Add(new SelectorModel
               {
                   AttributeRouteModel = new AttributeRouteModel
                   {
                       Order = 2,
                       Template = AttributeRouteModel.CombineTemplates(
                           selector.AttributeRouteModel!.Template,
                           "{aboutTemplate?}"),
                   }
               });
           }
       });

   });

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();

Considere a classe GlobalTemplatePageRouteModelConvention:

using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace SampleApp.Conventions;

public class GlobalTemplatePageRouteModelConvention : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        var selectorCount = model.Selectors.Count;
        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];
            model.Selectors.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Order = 1,
                    Template = AttributeRouteModel.CombineTemplates(
                        selector.AttributeRouteModel!.Template, 
                        "{globalTemplate?}"),
                }
            });
        }
    }
}

A propriedade Order do AttributeRouteModel é definida como 1. Isso garante o seguinte comportamento de correspondência de rotas no aplicativo de exemplo:

  • Um modelo de rota para TheContactPage/{text?} é adicionado posteriormente nesse tópico. A rota Contact Page tem uma ordem padrão de null (Order = 0), portanto, corresponde antes do modelo de rota {globalTemplate?}, que tem Order = 1.

  • O modelo de rota {aboutTemplate?} é mostrado no código anterior. O modelo {aboutTemplate?} recebe uma Order de 2. Quando a página About é solicitada no /About/RouteDataValue, "RouteDataValue" é carregado no RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["aboutTemplate"] (Order = 2) devido à configuração da propriedade Order.

  • O modelo de rota {otherPagesTemplate?} é mostrado no código anterior. O modelo {otherPagesTemplate?} recebe uma Order de 2. Quando qualquer página na pasta Pages/OtherPages é solicitada com um parâmetro de rota:

  • Por exemplo, /OtherPages/Page1/xyz

  • O valor dos dados de rota "xyz" é carregado em RouteData.Values["globalTemplate"] (Order = 1).

  • RouteData.Values["otherPagesTemplate"] com (Order = 2) não é carregado devido à propriedade Order2 ter um valor mais alto.

Quando possível, não defina Order. Quando Order não está definida, o padrão será Order = 0. Conte com o roteamento para selecionar a rota correta em vez da propriedade Order.

Solicite a página About do exemplo em localhost:{port}/About/GlobalRouteValue e inspecione o resultado:

The About page is requested with a route segment of GlobalRouteValue. The rendered page shows that the route data value is captured in the OnGet method of the page.

O aplicativo de exemplo usa o pacote NuGet Rick.Docs.Samples.RouteInfo para exibir informações de roteamento na saída de registro em log. Utilizando localhost:{port}/About/GlobalRouteValue, o agente exibe a solicitação, o Order e o modelo usados:

info: SampleApp.Pages.AboutModel[0]
       /About/GlobalRouteValue   Order = 1 Template = About/{globalTemplate?}

Adicionar uma convenção de modelo de aplicativo a todas as páginas

Use Conventions para criar e adicionar um IPageApplicationModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo de aplicativo de página.

Para demonstrar isso e outras convenções mais adiante no tópico, o aplicativo de exemplo inclui uma classe AddHeaderAttribute. O construtor de classe aceita uma cadeia de caracteres name e uma matriz de cadeia de caracteres values. Esses valores são usados em seu método OnResultExecuting para definir um cabeçalho de resposta. A classe completa é mostrada na seção Convenções de ação do modelo de página mais adiante no tópico.

O aplicativo de exemplo usa a classe AddHeaderAttribute para adicionar um cabeçalho, GlobalHeader, a todas as páginas no aplicativo:

public class GlobalHeaderPageApplicationModelConvention 
    : IPageApplicationModelConvention
{
    public void Apply(PageApplicationModel model)
    {
        model.Filters.Add(new AddHeaderAttribute(
            "GlobalHeader", new string[] { "Global Header Value" }));
    }
}

Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseInMemoryDatabase("InMemoryDb"));

builder.Services.AddRazorPages(options =>
   {
       options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

       options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());

Solicite a página About da amostra em localhost:{port}/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that the GlobalHeader has been added.

Adicionar uma convenção de modelo de manipulador a todas as páginas

Use Conventions para criar e adicionar um IPageHandlerModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo do manipulador de página.

public class GlobalPageHandlerModelConvention
    : IPageHandlerModelConvention
{
    public void Apply(PageHandlerModel model)
    {
        // Access the PageHandlerModel
    }
}

Convenções de ação da rota de página

O provedor de modelo de rota padrão derivado de IPageRouteModelProvider invoca convenções que foram projetadas para fornecer pontos de extensibilidade para configuração de rotas de página.

Convenção de modelo de rota de pasta

Use AddFolderRouteModelConvention para criar e adicionar um IPageRouteModelConvention que invoca uma ação no PageRouteModel para todas as páginas na pasta especificada.

O aplicativo de exemplo usa AddFolderRouteModelConvention para adicionar um modelo de rota {otherPagesTemplate?} às páginas da pasta OtherPages:

options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
    var selectorCount = model.Selectors.Count;
    for (var i = 0; i < selectorCount; i++)
    {
        var selector = model.Selectors[i];
        model.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel
            {
                Order = 2,
                Template = AttributeRouteModel.CombineTemplates(
                    selector.AttributeRouteModel!.Template,
                    "{otherPagesTemplate?}"),
            }
        });
    }
});

A propriedade Order do AttributeRouteModel é definida como 2. Isso garante que o modelo para {globalTemplate?} (definido anteriormente no tópico como 1) tenha prioridade para a primeira posição de valor de dados de rota quando um único valor de rota é fornecido. Se uma página na pasta Pages/OtherPages for solicitada com um valor de parâmetro de rota (por exemplo, /OtherPages/Page1/RouteDataValue), "RouteDataValue" será carregado em RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["otherPagesTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

Solicite a página Page1 da amostra em localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue e inspecione o resultado:

Page1 in the OtherPages folder is requested with a route segment of GlobalRouteValue and OtherPagesRouteValue. The rendered page shows that the route data values are captured in the OnGet method of the page.

Convenção de modelo de rota de página

Use AddPageRouteModelConvention para criar e adicionar um IPageRouteModelConvention que invoca uma ação no PageRouteModel para a página no nome especificado.

O aplicativo de exemplo usa AddPageRouteModelConvention para adicionar um modelo de rota {aboutTemplate?} à página About:

options.Conventions.AddPageRouteModelConvention("/About", model =>
{
    var selectorCount = model.Selectors.Count;
    for (var i = 0; i < selectorCount; i++)
    {
        var selector = model.Selectors[i];
        model.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel
            {
                Order = 2,
                Template = AttributeRouteModel.CombineTemplates(
                    selector.AttributeRouteModel!.Template,
                    "{aboutTemplate?}"),
            }
        });
    }
});

A propriedade Order do AttributeRouteModel é definida como 2. Isso garante que o modelo para {globalTemplate?} (definido anteriormente no tópico como 1) tenha prioridade para a primeira posição de valor de dados de rota quando um único valor de rota é fornecido. Se a página About for solicitada com um valor de parâmetro de rota no /About/RouteDataValue, "RouteDataValue" será carregado no RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["aboutTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

Solicite a página About da amostra em localhost:{port}/About/GlobalRouteValue/AboutRouteValue e inspecione o resultado:

About page is requested with route segments for GlobalRouteValue and AboutRouteValue. The rendered page shows that the route data values are captured in the OnGet method of the page.

A saída do agente mostra:

info: SampleApp.Pages.AboutModel[0]
       /About/GlobalRouteValue/AboutRouteValue   Order = 2 Template = About/{globalTemplate?}/{aboutTemplate?}

Usar um transformador de parâmetro para personalizar rotas de página

Confira Transformadores de parâmetro.

Configurar uma rota de página

Use AddPageRoute para configurar uma rota para uma página no caminho de página especificado. Os links gerados para a página usam a rota especificada. AddPageRoute usa AddPageRouteModelConvention para estabelecer a rota.

O aplicativo de exemplo cria uma rota para /TheContactPage para o ContactRazor Pages:

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

A página Contact também pode ser acessada em /Contact1` via rota padrão.

A rota personalizada do aplicativo de exemplo para a página Contact permite um segmento de rota text opcional ({text?}). A página também inclui esse segmento opcional em sua diretiva @page, caso o visitante acesse a página em sua rota /Contact:

@page "{text?}"
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}

<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>

<address>
    One Microsoft Way<br>
    Redmond, WA 98052-6399<br>
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

<p>@Model.RouteDataTextTemplateValue</p>

Observe que a URL gerada para o link Contato na página renderizada reflete a rota atualizada:

Sample app Contact link in the navigation bar

Inspecting the Contact link in the rendered HTML indicates that the href is set to '/TheContactPage'

Visite a página Contact na rota ordinária /Contact ou na rota personalizada /TheContactPage. Se você fornecer um segmento de rota text adicional, a página mostrará o segmento codificado em HTML fornecido:

Edge browser example of supplying an optional 'text' route segment of 'TextValue' in the URL. The rendered page shows the 'text' segment value.

Convenções de ação do modelo de página

O provedor de modelo de página padrão que implementa IPageApplicationModelProvider invoca convenções que foram projetadas para fornecer pontos de extensibilidade para configuração de modelos de página. Essas convenções são úteis ao criar e modificar cenários de descoberta e processamento de página.

Para os exemplos desta seção, o aplicativo de exemplo usa uma classe AddHeaderAttribute, que é um ResultFilterAttribute, aplicável a um cabeçalho de resposta:

public class AddHeaderAttribute : ResultFilterAttribute
{
    private readonly string _name;
    private readonly string[] _values;

    public AddHeaderAttribute(string name, string[] values)
    {
        _name = name;
        _values = values;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add(_name, _values);
        base.OnResultExecuting(context);
    }
}

Usando convenções, a amostra explica como aplicar o atributo a todas as páginas de uma pasta e a uma única página.

Convenção de modelo de aplicativo de pasta

Use AddFolderApplicationModelConvention para criar e adicionar um IPageApplicationModelConvention que invoca uma ação em instâncias PageApplicationModel para todas as páginas na pasta especificada.

A amostra explica o uso de AddFolderApplicationModelConvention adicionando um cabeçalho, OtherPagesHeader, às páginas dentro da pasta OtherPages do aplicativo:

options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});

Solicite a página Page1 da amostra em localhost:5000/OtherPages/Page1 e inspecione os cabeçalhos para exibir o resultado:

Response headers of the OtherPages/Page1 page show that the OtherPagesHeader has been added.

Convenção de modelo de aplicativo de página

Use AddPageApplicationModelConvention para criar e adicionar um IPageApplicationModelConvention que invoca uma ação no PageApplicationModel para a página no nome especificado.

A amostra explica o uso de AddPageApplicationModelConvention adicionando um cabeçalho, AboutHeader, à página About:

options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "AboutHeader", new string[] { "About Header Value" }));
});

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that the AboutHeader has been added.

Configurar um filtro

ConfigureFilter configura o filtro especificado a ser aplicado. É possível implementar uma classe de filtro, mas o aplicativo de exemplo mostra como implementar um filtro em uma expressão lambda, que é implementado em segundo plano como um alocador que retorna um filtro:

options.Conventions.ConfigureFilter(model =>
{
    if (model.RelativePath.Contains("OtherPages/Page2"))
    {
        return new AddHeaderAttribute(
            "OtherPagesPage2Header",
            new string[] { "OtherPages/Page2 Header Value" });
    }
    return new EmptyFilter();
});

O modelo de aplicativo de página é usado para verificar o caminho relativo para segmentos que levam à página Page2 na pasta OtherPages. Se a condição é aprovada, um cabeçalho é adicionado. Caso contrário, o EmptyFilter é aplicado.

EmptyFilter é um filtro de Ação. Como os filtros de ação são ignorados por páginas Razor , o EmptyFilter não terá o efeito pretendido se o caminho não contiver OtherPages/Page2.

Solicite a página Page2 da amostra em localhost:5000/OtherPages/Page2 e inspecione os cabeçalhos para exibir o resultado:

The OtherPagesPage2Header is added to the response for Page2.

Configurar um alocador de filtro

ConfigureFilter configura o alocador especificado para aplicar filtros a todas as Páginas Razor.

O aplicativo de exemplo fornece um exemplo de como usar um alocador de filtro adicionando um cabeçalho, FilterFactoryHeader, com dois valores para as páginas do aplicativo:

options.Conventions.ConfigureFilter(new AddHeaderWithFactory());

AddHeaderWithFactory.cs:

public class AddHeaderWithFactory : IFilterFactory
{
    // Implement IFilterFactory
    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return new AddHeaderFilter();
    }

    private class AddHeaderFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(
                "FilterFactoryHeader", 
                new string[] 
                { 
                    "Filter Factory Header Value 1",
                    "Filter Factory Header Value 2"
                });
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that two FilterFactoryHeader headers have been added.

Filtros MVC e o filtro de Página (IPageFilter)

Os filtros de Ação MVC são ignorados pelas Páginas Razor, pois as páginas Razor usam métodos de manipulador. Outros tipos de filtros MVC estão disponíveis para uso: Autorização, Exceção, Recurso e Resultado. Para obter mais informações, consulte o tópico Filtros.

O filtro de Página (IPageFilter) é um filtro que se aplica às Páginas do Razor. Para obter mais informações, confira Métodos de filtragem para Páginas do Razor.

Recursos adicionais

Saiba como usar a página convenções do provedor de modelo de rota e aplicativo para controlar o roteamento, a descoberta e o processamento de páginas nos aplicativos Razor Pages.

Quando precisar configurar rotas de página personalizadas para páginas individuais, configure o roteamento para páginas com a convenção AddPageRoute descrita mais adiante neste tópico.

Para especificar uma rota de página, adicionar segmentos de rota ou adicionar parâmetros a uma rota, use a diretiva @page da página. Para obter mais informações, confira Rotas personalizadas.

Há palavras reservadas que não podem ser usadas como segmentos de rota ou nomes de parâmetros. Para obter mais informações, confira Roteamento: nomes de roteamento reservados.

Exibir ou baixar código de exemplo (como baixar)

Cenário A amostra explica...
Convenções de modelo

Conventions.Add
  • IPageRouteModelConvention
  • IPageApplicationModelConvention
  • IPageHandlerModelConvention
Adicione um cabeçalho e um modelo de rota às páginas de um aplicativo.
Convenções de ação da rota de página
  • AddFolderRouteModelConvention
  • AddPageRouteModelConvention
  • AddPageRoute
Adicione um modelo de rota às páginas em uma pasta e a uma única página.
Convenções de ação do modelo de página
  • AddFolderApplicationModelConvention
  • AddPageApplicationModelConvention
  • ConfigureFilter (classe de filtro, expressão lambda ou alocador de filtro)
Adicione um cabeçalho às páginas em uma pasta, adicione um cabeçalho a uma única página e configure um alocador de filtro para adicionar um cabeçalho às páginas de um aplicativo.

As convenções de páginas do Razor são configuradas usando uma sobrecarga AddRazorPages que configura RazorPagesOptions em Startup.ConfigureServices. Os exemplos de convenção a seguir estão descritos mais adiante neste tópico:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages(options =>
    {
        options.Conventions.Add( ... );
        options.Conventions.AddFolderRouteModelConvention(
            "/OtherPages", model => { ... });
        options.Conventions.AddPageRouteModelConvention(
            "/About", model => { ... });
        options.Conventions.AddPageRoute(
            "/Contact", "TheContactPage/{text?}");
        options.Conventions.AddFolderApplicationModelConvention(
            "/OtherPages", model => { ... });
        options.Conventions.AddPageApplicationModelConvention(
            "/About", model => { ... });
        options.Conventions.ConfigureFilter(model => { ... });
        options.Conventions.ConfigureFilter( ... );
    });
}

Ordem de rota

As rotas especificam um Order para processamento (correspondência de rotas).

Order Comportamento
-1 A rota é processada antes que outras rotas sejam processadas.
0 A ordem não é especificada (valor padrão). A não atribuição Order (Order = null) define a rota Order como 0 (zero) por padrão para processamento.
1, 2, … n Especifica a ordem de processamento de rota.

O processamento de rotas é estabelecido por convenção:

  • As rotas são processadas em ordem sequencial (-1, 0, 1, 2, ... n).
  • Quando as rotas têm o mesmo Order, a rota mais específica é correspondida primeiro, seguida por rotas menos específicas.
  • Quando as rotas com o mesmo Order e o mesmo número de parâmetros correspondem a uma URL de solicitação, as rotas são processadas na ordem em que são adicionadas a PageConventionCollection.

Se possível, evite depender de uma ordem de processamento de rota estabelecida. Em geral, o roteamento seleciona a rota correta com correspondência de URL. Se você precisar definir propriedades Order de rota para rotear solicitações corretamente, o esquema de roteamento do aplicativo provavelmente será confuso para os clientes e de frágil manutenção. Procure simplificar o esquema de roteamento do aplicativo. O aplicativo de exemplo requer uma ordem de processamento de rota explícita para demonstrar vários cenários de roteamento usando um único aplicativo. No entanto, você deve tentar evitar a prática de definir a rota Order em aplicativos de produção.

O roteamento do Razor Pages e o roteamento de controlador do MVC compartilham uma implementação. As informações sobre a ordem de rota nos tópicos do MVC estão disponíveis em Roteamento para ações do controlador: ordenando as rotas de atributo.

Convenções de modelo

Adicione um representante para IPageConvention a fim de adicionar convenções de modelo que se aplicam ao Razor Pages.

Adicionar uma convenção de modelo de rota a todas as páginas

Use Conventions para criar e adicionar um IPageRouteModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo de rota de página.

O aplicativo de exemplo adiciona um modelo de rota {globalTemplate?} a todas as páginas no aplicativo:

public class GlobalTemplatePageRouteModelConvention 
    : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        var selectorCount = model.Selectors.Count;
        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];
            model.Selectors.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Order = 1,
                    Template = AttributeRouteModel.CombineTemplates(
                        selector.AttributeRouteModel.Template, 
                        "{globalTemplate?}"),
                }
            });
        }
    }
}

A propriedade Order do AttributeRouteModel é definida como 1. Isso garante o seguinte comportamento de correspondência de rotas no aplicativo de exemplo:

  • Um modelo de rota para TheContactPage/{text?} é adicionado posteriormente no tópico. A rota Página de Contato tem uma ordem padrão de null (Order = 0), portanto, corresponde antes do modelo de rota {globalTemplate?}.
  • Um modelo de rota {aboutTemplate?} é adicionado posteriormente no tópico. O modelo {aboutTemplate?} recebe uma Order de 2. Quando a página About é solicitada no /About/RouteDataValue, "RouteDataValue" é carregado no RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["aboutTemplate"] (Order = 2) devido à configuração da propriedade Order.
  • Um modelo de rota {otherPagesTemplate?} é adicionado posteriormente no tópico. O modelo {otherPagesTemplate?} recebe uma Order de 2. Quando qualquer página na pasta Pages/OtherPages é solicitada com um parâmetro de rota (por exemplo, /OtherPages/Page1/RouteDataValue), "RouteDataValue" é carregado em RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["otherPagesTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

As opções do Razor Pages, como adicionar Conventions, são adicionadas quando o Razor Pages é adicionado à coleção de serviços no Startup.ConfigureServices. Para obter um exemplo, confira o aplicativo de exemplo.

options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

Solicite a página About da amostra em localhost:5000/About/GlobalRouteValue e inspecione o resultado:

The About page is requested with a route segment of GlobalRouteValue. The rendered page shows that the route data value is captured in the OnGet method of the page.

Adicionar uma convenção de modelo de aplicativo a todas as páginas

Use Conventions para criar e adicionar um IPageApplicationModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo de aplicativo de página.

Para demonstrar isso e outras convenções mais adiante no tópico, o aplicativo de exemplo inclui uma classe AddHeaderAttribute. O construtor de classe aceita uma cadeia de caracteres name e uma matriz de cadeia de caracteres values. Esses valores são usados em seu método OnResultExecuting para definir um cabeçalho de resposta. A classe completa é mostrada na seção Convenções de ação do modelo de página mais adiante no tópico.

O aplicativo de exemplo usa a classe AddHeaderAttribute para adicionar um cabeçalho, GlobalHeader, a todas as páginas no aplicativo:

public class GlobalHeaderPageApplicationModelConvention 
    : IPageApplicationModelConvention
{
    public void Apply(PageApplicationModel model)
    {
        model.Filters.Add(new AddHeaderAttribute(
            "GlobalHeader", new string[] { "Global Header Value" }));
    }
}

Startup.cs:

options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that the GlobalHeader has been added.

Adicionar uma convenção de modelo de manipulador a todas as páginas

Use Conventions para criar e adicionar um IPageHandlerModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo do manipulador de página.

public class GlobalPageHandlerModelConvention
    : IPageHandlerModelConvention
{
    public void Apply(PageHandlerModel model)
    {
        // Access the PageHandlerModel
    }
}

Startup.cs:

options.Conventions.Add(new GlobalPageHandlerModelConvention());

Convenções de ação da rota de página

O provedor de modelo de rota padrão derivado de IPageRouteModelProvider invoca convenções que foram projetadas para fornecer pontos de extensibilidade para configuração de rotas de página.

Convenção de modelo de rota de pasta

Use AddFolderRouteModelConvention para criar e adicionar um IPageRouteModelConvention que invoca uma ação no PageRouteModel para todas as páginas na pasta especificada.

O aplicativo de exemplo usa AddFolderRouteModelConvention para adicionar um modelo de rota {otherPagesTemplate?} às páginas da pasta OtherPages:

options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
    var selectorCount = model.Selectors.Count;
    for (var i = 0; i < selectorCount; i++)
    {
        var selector = model.Selectors[i];
        model.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel
            {
                Order = 2,
                Template = AttributeRouteModel.CombineTemplates(
                    selector.AttributeRouteModel.Template, 
                    "{otherPagesTemplate?}"),
            }
        });
    }
});

A propriedade Order do AttributeRouteModel é definida como 2. Isso garante que o modelo para {globalTemplate?} (definido anteriormente no tópico como 1) tenha prioridade para a primeira posição de valor de dados de rota quando um único valor de rota é fornecido. Se uma página na pasta Pages/OtherPages for solicitada com um valor de parâmetro de rota (por exemplo, /OtherPages/Page1/RouteDataValue), "RouteDataValue" será carregado em RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["otherPagesTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

Solicite a página Page1 da amostra em localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue e inspecione o resultado:

Page1 in the OtherPages folder is requested with a route segment of GlobalRouteValue and OtherPagesRouteValue. The rendered page shows that the route data values are captured in the OnGet method of the page.

Convenção de modelo de rota de página

Use AddPageRouteModelConvention para criar e adicionar um IPageRouteModelConvention que invoca uma ação no PageRouteModel para a página no nome especificado.

O aplicativo de exemplo usa AddPageRouteModelConvention para adicionar um modelo de rota {aboutTemplate?} à página About:

options.Conventions.AddPageRouteModelConvention("/About", model =>
{
    var selectorCount = model.Selectors.Count;
    for (var i = 0; i < selectorCount; i++)
    {
        var selector = model.Selectors[i];
        model.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel
            {
                Order = 2,
                Template = AttributeRouteModel.CombineTemplates(
                    selector.AttributeRouteModel.Template, 
                    "{aboutTemplate?}"),
            }
        });
    }
});

A propriedade Order do AttributeRouteModel é definida como 2. Isso garante que o modelo para {globalTemplate?} (definido anteriormente no tópico como 1) tenha prioridade para a primeira posição de valor de dados de rota quando um único valor de rota é fornecido. Se a página About for solicitada com um valor de parâmetro de rota no /About/RouteDataValue, "RouteDataValue" será carregado no RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["aboutTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

Solicite a página About da amostra em localhost:5000/About/GlobalRouteValue/AboutRouteValue e inspecione o resultado:

About page is requested with route segments for GlobalRouteValue and AboutRouteValue. The rendered page shows that the route data values are captured in the OnGet method of the page.

Usar um transformador de parâmetro para personalizar rotas de página

As rotas de página geradas pelo ASP.NET Core podem ser personalizadas usando um transformador de parâmetro. Um transformador de parâmetro implementa IOutboundParameterTransformer e transforma o valor dos parâmetros. Por exemplo, um transformador de parâmetro SlugifyParameterTransformer personalizado muda o valor de rota SubscriptionManagement para subscription-management.

A convenção de modelo de rota de página PageRouteTransformerConvention aplica um transformador de parâmetro aos segmentos de nome de arquivo e pasta de rotas de página geradas automaticamente em um aplicativo. Por exemplo, o arquivo de Páginas do Razor em /Pages/SubscriptionManagement/ViewAll.cshtml teria sua rota reescrita de /SubscriptionManagement/ViewAll para /subscription-management/view-all.

PageRouteTransformerConvention transforma apenas os segmentos gerados automaticamente de uma rota de página proveniente do nome de arquivo e pasta das Páginas do Razor. Ele não transforma segmentos de rota adicionados com a diretiva @page. A convenção também não transforma rotas adicionadas por AddPageRoute.

O PageRouteTransformerConvention está registrado como uma opção em Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages(options =>
    {
        options.Conventions.Add(
            new PageRouteTransformerConvention(
                new SlugifyParameterTransformer()));
    });
}
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();
    }
}

Aviso

Ao usar System.Text.RegularExpressions para processar entradas não confiáveis, passe um tempo limite. Um usuário mal-intencionado pode fornecer entrada para RegularExpressions, causando um ataque de negação de serviço. APIs ASP.NET Core Framework que usam RegularExpressions passam um tempo limite.

Configurar uma rota de página

Use AddPageRoute para configurar uma rota para uma página no caminho de página especificado. Os links gerados para a página usam a rota especificada. AddPageRoute usa AddPageRouteModelConvention para estabelecer a rota.

O aplicativo de exemplo cria uma rota para /TheContactPage para Contact.cshtml:

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

A página Contact também pode ser acessada em /Contact por meio de sua rota padrão.

A rota personalizada do aplicativo de exemplo para a página Contact permite um segmento de rota text opcional ({text?}). A página também inclui esse segmento opcional em sua diretiva @page, caso o visitante acesse a página em sua rota /Contact:

@page "{text?}"
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}

<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>

<address>
    One Microsoft Way<br>
    Redmond, WA 98052-6399<br>
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

<p>@Model.RouteDataTextTemplateValue</p>

Observe que a URL gerada para o link Contato na página renderizada reflete a rota atualizada:

Sample app Contact link in the navigation bar

Inspecting the Contact link in the rendered HTML indicates that the href is set to '/TheContactPage'

Visite a página Contact em sua rota comum, /Contact, ou na rota personalizada, /TheContactPage. Se você fornecer um segmento de rota text adicional, a página mostrará o segmento codificado em HTML fornecido:

Edge browser example of supplying an optional 'text' route segment of 'TextValue' in the URL. The rendered page shows the 'text' segment value.

Convenções de ação do modelo de página

O provedor de modelo de página padrão que implementa IPageApplicationModelProvider invoca convenções que foram projetadas para fornecer pontos de extensibilidade para configuração de modelos de página. Essas convenções são úteis ao criar e modificar cenários de descoberta e processamento de página.

Para os exemplos desta seção, o aplicativo de exemplo usa uma classe AddHeaderAttribute, que é um ResultFilterAttribute, aplicável a um cabeçalho de resposta:

public class AddHeaderAttribute : ResultFilterAttribute
{
    private readonly string _name;
    private readonly string[] _values;

    public AddHeaderAttribute(string name, string[] values)
    {
        _name = name;
        _values = values;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add(_name, _values);
        base.OnResultExecuting(context);
    }
}

Usando convenções, a amostra explica como aplicar o atributo a todas as páginas de uma pasta e a uma única página.

Convenção de modelo de aplicativo de pasta

Use AddFolderApplicationModelConvention para criar e adicionar um IPageApplicationModelConvention que invoca uma ação em instâncias PageApplicationModel para todas as páginas na pasta especificada.

A amostra explica o uso de AddFolderApplicationModelConvention adicionando um cabeçalho, OtherPagesHeader, às páginas dentro da pasta OtherPages do aplicativo:

options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});

Solicite a página Page1 da amostra em localhost:5000/OtherPages/Page1 e inspecione os cabeçalhos para exibir o resultado:

Response headers of the OtherPages/Page1 page show that the OtherPagesHeader has been added.

Convenção de modelo de aplicativo de página

Use AddPageApplicationModelConvention para criar e adicionar um IPageApplicationModelConvention que invoca uma ação no PageApplicationModel para a página no nome especificado.

A amostra explica o uso de AddPageApplicationModelConvention adicionando um cabeçalho, AboutHeader, à página About:

options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "AboutHeader", new string[] { "About Header Value" }));
});

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that the AboutHeader has been added.

Configurar um filtro

ConfigureFilter configura o filtro especificado a ser aplicado. É possível implementar uma classe de filtro, mas o aplicativo de exemplo mostra como implementar um filtro em uma expressão lambda, que é implementado em segundo plano como um alocador que retorna um filtro:

options.Conventions.ConfigureFilter(model =>
{
    if (model.RelativePath.Contains("OtherPages/Page2"))
    {
        return new AddHeaderAttribute(
            "OtherPagesPage2Header", 
            new string[] { "OtherPages/Page2 Header Value" });
    }
    return new EmptyFilter();
});

O modelo de aplicativo de página é usado para verificar o caminho relativo para segmentos que levam à página Page2 na pasta OtherPages. Se a condição é aprovada, um cabeçalho é adicionado. Caso contrário, o EmptyFilter é aplicado.

EmptyFilter é um filtro de Ação. Como os filtros de ação são ignorados por páginas Razor , o EmptyFilter não terá o efeito pretendido se o caminho não contiver OtherPages/Page2.

Solicite a página Page2 da amostra em localhost:5000/OtherPages/Page2 e inspecione os cabeçalhos para exibir o resultado:

The OtherPagesPage2Header is added to the response for Page2.

Configurar um alocador de filtro

ConfigureFilter configura o alocador especificado para aplicar filtros a todas as Páginas Razor.

O aplicativo de exemplo fornece um exemplo de como usar um alocador de filtro adicionando um cabeçalho, FilterFactoryHeader, com dois valores para as páginas do aplicativo:

options.Conventions.ConfigureFilter(new AddHeaderWithFactory());

AddHeaderWithFactory.cs:

public class AddHeaderWithFactory : IFilterFactory
{
    // Implement IFilterFactory
    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return new AddHeaderFilter();
    }

    private class AddHeaderFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(
                "FilterFactoryHeader", 
                new string[] 
                { 
                    "Filter Factory Header Value 1",
                    "Filter Factory Header Value 2"
                });
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that two FilterFactoryHeader headers have been added.

Filtros MVC e o filtro de Página (IPageFilter)

Os filtros de Ação MVC são ignorados pelas Páginas Razor, pois as páginas Razor usam métodos de manipulador. Outros tipos de filtros MVC estão disponíveis para uso: Autorização, Exceção, Recurso e Resultado. Para obter mais informações, consulte o tópico Filtros.

O filtro de Página (IPageFilter) é um filtro que se aplica às Páginas do Razor. Para obter mais informações, confira Métodos de filtragem para Páginas do Razor.

Recursos adicionais

Saiba como usar a página convenções do provedor de modelo de rota e aplicativo para controlar o roteamento, a descoberta e o processamento de páginas nos aplicativos Razor Pages.

Quando precisar configurar rotas de página personalizadas para páginas individuais, configure o roteamento para páginas com a convenção AddPageRoute descrita mais adiante neste tópico.

Para especificar uma rota de página, adicionar segmentos de rota ou adicionar parâmetros a uma rota, use a diretiva @page da página. Para obter mais informações, confira Rotas personalizadas.

Há palavras reservadas que não podem ser usadas como segmentos de rota ou nomes de parâmetros. Para obter mais informações, confira Roteamento: nomes de roteamento reservados.

Exibir ou baixar código de exemplo (como baixar)

Cenário A amostra explica...
Convenções de modelo

Conventions.Add
  • IPageRouteModelConvention
  • IPageApplicationModelConvention
  • IPageHandlerModelConvention
Adicione um cabeçalho e um modelo de rota às páginas de um aplicativo.
Convenções de ação da rota de página
  • AddFolderRouteModelConvention
  • AddPageRouteModelConvention
  • AddPageRoute
Adicione um modelo de rota às páginas em uma pasta e a uma única página.
Convenções de ação do modelo de página
  • AddFolderApplicationModelConvention
  • AddPageApplicationModelConvention
  • ConfigureFilter (classe de filtro, expressão lambda ou alocador de filtro)
Adicione um cabeçalho às páginas em uma pasta, adicione um cabeçalho a uma única página e configure um alocador de filtro para adicionar um cabeçalho às páginas de um aplicativo.

As convenções do Razor Pages são adicionadas e configuradas usando o método de extensão AddRazorPagesOptions para AddMvc na coleção de serviços na classe Startup. Os exemplos de convenção a seguir estão descritos mais adiante neste tópico:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.Add( ... );
            options.Conventions.AddFolderRouteModelConvention(
                "/OtherPages", model => { ... });
            options.Conventions.AddPageRouteModelConvention(
                "/About", model => { ... });
            options.Conventions.AddPageRoute(
                "/Contact", "TheContactPage/{text?}");
            options.Conventions.AddFolderApplicationModelConvention(
                "/OtherPages", model => { ... });
            options.Conventions.AddPageApplicationModelConvention(
                "/About", model => { ... });
            options.Conventions.ConfigureFilter(model => { ... });
            options.Conventions.ConfigureFilter( ... );
        });
}

Ordem de rota

As rotas especificam um Order para processamento (correspondência de rotas).

Order Comportamento
-1 A rota é processada antes que outras rotas sejam processadas.
0 A ordem não é especificada (valor padrão). A não atribuição Order (Order = null) define a rota Order como 0 (zero) por padrão para processamento.
1, 2, … n Especifica a ordem de processamento de rota.

O processamento de rotas é estabelecido por convenção:

  • As rotas são processadas em ordem sequencial (-1, 0, 1, 2, ... n).
  • Quando as rotas têm o mesmo Order, a rota mais específica é correspondida primeiro, seguida por rotas menos específicas.
  • Quando as rotas com o mesmo Order e o mesmo número de parâmetros correspondem a uma URL de solicitação, as rotas são processadas na ordem em que são adicionadas a PageConventionCollection.

Se possível, evite depender de uma ordem de processamento de rota estabelecida. Em geral, o roteamento seleciona a rota correta com correspondência de URL. Se você precisar definir propriedades Order de rota para rotear solicitações corretamente, o esquema de roteamento do aplicativo provavelmente será confuso para os clientes e de frágil manutenção. Procure simplificar o esquema de roteamento do aplicativo. O aplicativo de exemplo requer uma ordem de processamento de rota explícita para demonstrar vários cenários de roteamento usando um único aplicativo. No entanto, você deve tentar evitar a prática de definir a rota Order em aplicativos de produção.

O roteamento do Razor Pages e o roteamento de controlador do MVC compartilham uma implementação. As informações sobre a ordem de rota nos tópicos do MVC estão disponíveis em Roteamento para ações do controlador: ordenando as rotas de atributo.

Convenções de modelo

Adicione um representante para IPageConvention a fim de adicionar convenções de modelo que se aplicam ao Razor Pages.

Adicionar uma convenção de modelo de rota a todas as páginas

Use Conventions para criar e adicionar um IPageRouteModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo de rota de página.

O aplicativo de exemplo adiciona um modelo de rota {globalTemplate?} a todas as páginas no aplicativo:

public class GlobalTemplatePageRouteModelConvention 
    : IPageRouteModelConvention
{
    public void Apply(PageRouteModel model)
    {
        var selectorCount = model.Selectors.Count;
        for (var i = 0; i < selectorCount; i++)
        {
            var selector = model.Selectors[i];
            model.Selectors.Add(new SelectorModel
            {
                AttributeRouteModel = new AttributeRouteModel
                {
                    Order = 1,
                    Template = AttributeRouteModel.CombineTemplates(
                        selector.AttributeRouteModel.Template, 
                        "{globalTemplate?}"),
                }
            });
        }
    }
}

A propriedade Order do AttributeRouteModel é definida como 1. Isso garante o seguinte comportamento de correspondência de rotas no aplicativo de exemplo:

  • Um modelo de rota para TheContactPage/{text?} é adicionado posteriormente no tópico. A rota Página de Contato tem uma ordem padrão de null (Order = 0), portanto, corresponde antes do modelo de rota {globalTemplate?}.
  • Um modelo de rota {aboutTemplate?} é adicionado posteriormente no tópico. O modelo {aboutTemplate?} recebe uma Order de 2. Quando a página About é solicitada no /About/RouteDataValue, "RouteDataValue" é carregado no RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["aboutTemplate"] (Order = 2) devido à configuração da propriedade Order.
  • Um modelo de rota {otherPagesTemplate?} é adicionado posteriormente no tópico. O modelo {otherPagesTemplate?} recebe uma Order de 2. Quando qualquer página na pasta Pages/OtherPages é solicitada com um parâmetro de rota (por exemplo, /OtherPages/Page1/RouteDataValue), "RouteDataValue" é carregado em RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["otherPagesTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

As opções das Páginas do Razor, como adicionar Conventions, são adicionadas quando o MVC é adicionado à coleção de serviços em Startup.ConfigureServices. Para obter um exemplo, confira o aplicativo de exemplo.

options.Conventions.Add(new GlobalTemplatePageRouteModelConvention());

Solicite a página About da amostra em localhost:5000/About/GlobalRouteValue e inspecione o resultado:

The About page is requested with a route segment of GlobalRouteValue. The rendered page shows that the route data value is captured in the OnGet method of the page.

Adicionar uma convenção de modelo de aplicativo a todas as páginas

Use Conventions para criar e adicionar um IPageApplicationModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo de aplicativo de página.

Para demonstrar isso e outras convenções mais adiante no tópico, o aplicativo de exemplo inclui uma classe AddHeaderAttribute. O construtor de classe aceita uma cadeia de caracteres name e uma matriz de cadeia de caracteres values. Esses valores são usados em seu método OnResultExecuting para definir um cabeçalho de resposta. A classe completa é mostrada na seção Convenções de ação do modelo de página mais adiante no tópico.

O aplicativo de exemplo usa a classe AddHeaderAttribute para adicionar um cabeçalho, GlobalHeader, a todas as páginas no aplicativo:

public class GlobalHeaderPageApplicationModelConvention 
    : IPageApplicationModelConvention
{
    public void Apply(PageApplicationModel model)
    {
        model.Filters.Add(new AddHeaderAttribute(
            "GlobalHeader", new string[] { "Global Header Value" }));
    }
}

Startup.cs:

options.Conventions.Add(new GlobalHeaderPageApplicationModelConvention());

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that the GlobalHeader has been added.

Adicionar uma convenção de modelo de manipulador a todas as páginas

Use Conventions para criar e adicionar um IPageHandlerModelConvention à coleção de instâncias IPageConvention que são aplicadas durante a construção do modelo do manipulador de página.

public class GlobalPageHandlerModelConvention
    : IPageHandlerModelConvention
{
    public void Apply(PageHandlerModel model)
    {
        // Access the PageHandlerModel
    }
}

Startup.cs:

options.Conventions.Add(new GlobalPageHandlerModelConvention());

Convenções de ação da rota de página

O provedor de modelo de rota padrão derivado de IPageRouteModelProvider invoca convenções que foram projetadas para fornecer pontos de extensibilidade para configuração de rotas de página.

Convenção de modelo de rota de pasta

Use AddFolderRouteModelConvention para criar e adicionar um IPageRouteModelConvention que invoca uma ação no PageRouteModel para todas as páginas na pasta especificada.

O aplicativo de exemplo usa AddFolderRouteModelConvention para adicionar um modelo de rota {otherPagesTemplate?} às páginas da pasta OtherPages:

options.Conventions.AddFolderRouteModelConvention("/OtherPages", model =>
{
    var selectorCount = model.Selectors.Count;
    for (var i = 0; i < selectorCount; i++)
    {
        var selector = model.Selectors[i];
        model.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel
            {
                Order = 2,
                Template = AttributeRouteModel.CombineTemplates(
                    selector.AttributeRouteModel.Template, 
                    "{otherPagesTemplate?}"),
            }
        });
    }
});

A propriedade Order do AttributeRouteModel é definida como 2. Isso garante que o modelo para {globalTemplate?} (definido anteriormente no tópico como 1) tenha prioridade para a primeira posição de valor de dados de rota quando um único valor de rota é fornecido. Se uma página na pasta Pages/OtherPages for solicitada com um valor de parâmetro de rota (por exemplo, /OtherPages/Page1/RouteDataValue), "RouteDataValue" será carregado em RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["otherPagesTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

Solicite a página Page1 da amostra em localhost:5000/OtherPages/Page1/GlobalRouteValue/OtherPagesRouteValue e inspecione o resultado:

Page1 in the OtherPages folder is requested with a route segment of GlobalRouteValue and OtherPagesRouteValue. The rendered page shows that the route data values are captured in the OnGet method of the page.

Convenção de modelo de rota de página

Use AddPageRouteModelConvention para criar e adicionar um IPageRouteModelConvention que invoca uma ação no PageRouteModel para a página no nome especificado.

O aplicativo de exemplo usa AddPageRouteModelConvention para adicionar um modelo de rota {aboutTemplate?} à página About:

options.Conventions.AddPageRouteModelConvention("/About", model =>
{
    var selectorCount = model.Selectors.Count;
    for (var i = 0; i < selectorCount; i++)
    {
        var selector = model.Selectors[i];
        model.Selectors.Add(new SelectorModel
        {
            AttributeRouteModel = new AttributeRouteModel
            {
                Order = 2,
                Template = AttributeRouteModel.CombineTemplates(
                    selector.AttributeRouteModel.Template, 
                    "{aboutTemplate?}"),
            }
        });
    }
});

A propriedade Order do AttributeRouteModel é definida como 2. Isso garante que o modelo para {globalTemplate?} (definido anteriormente no tópico como 1) tenha prioridade para a primeira posição de valor de dados de rota quando um único valor de rota é fornecido. Se a página About for solicitada com um valor de parâmetro de rota no /About/RouteDataValue, "RouteDataValue" será carregado no RouteData.Values["globalTemplate"] (Order = 1) e não RouteData.Values["aboutTemplate"] (Order = 2) devido à configuração da propriedade Order.

Sempre que possível, não defina o Order, que resulta em Order = 0. Conte com o roteamento para selecionar a rota correta.

Solicite a página About da amostra em localhost:5000/About/GlobalRouteValue/AboutRouteValue e inspecione o resultado:

About page is requested with route segments for GlobalRouteValue and AboutRouteValue. The rendered page shows that the route data values are captured in the OnGet method of the page.

Configurar uma rota de página

Use AddPageRoute para configurar uma rota para uma página no caminho de página especificado. Os links gerados para a página usam a rota especificada. AddPageRoute usa AddPageRouteModelConvention para estabelecer a rota.

O aplicativo de exemplo cria uma rota para /TheContactPage para Contact.cshtml:

options.Conventions.AddPageRoute("/Contact", "TheContactPage/{text?}");

A página Contact também pode ser acessada em /Contact por meio de sua rota padrão.

A rota personalizada do aplicativo de exemplo para a página Contact permite um segmento de rota text opcional ({text?}). A página também inclui esse segmento opcional em sua diretiva @page, caso o visitante acesse a página em sua rota /Contact:

@page "{text?}"
@model ContactModel
@{
    ViewData["Title"] = "Contact";
}

<h1>@ViewData["Title"]</h1>
<h2>@Model.Message</h2>

<address>
    One Microsoft Way<br>
    Redmond, WA 98052-6399<br>
    <abbr title="Phone">P:</abbr>
    425.555.0100
</address>

<address>
    <strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br>
    <strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a>
</address>

<p>@Model.RouteDataTextTemplateValue</p>

Observe que a URL gerada para o link Contato na página renderizada reflete a rota atualizada:

Sample app Contact link in the navigation bar

Inspecting the Contact link in the rendered HTML indicates that the href is set to '/TheContactPage'

Visite a página Contact em sua rota comum, /Contact, ou na rota personalizada, /TheContactPage. Se você fornecer um segmento de rota text adicional, a página mostrará o segmento codificado em HTML fornecido:

Edge browser example of supplying an optional 'text' route segment of 'TextValue' in the URL. The rendered page shows the 'text' segment value.

Convenções de ação do modelo de página

O provedor de modelo de página padrão que implementa IPageApplicationModelProvider invoca convenções que foram projetadas para fornecer pontos de extensibilidade para configuração de modelos de página. Essas convenções são úteis ao criar e modificar cenários de descoberta e processamento de página.

Para os exemplos desta seção, o aplicativo de exemplo usa uma classe AddHeaderAttribute, que é um ResultFilterAttribute, aplicável a um cabeçalho de resposta:

public class AddHeaderAttribute : ResultFilterAttribute
{
    private readonly string _name;
    private readonly string[] _values;

    public AddHeaderAttribute(string name, string[] values)
    {
        _name = name;
        _values = values;
    }

    public override void OnResultExecuting(ResultExecutingContext context)
    {
        context.HttpContext.Response.Headers.Add(_name, _values);
        base.OnResultExecuting(context);
    }
}

Usando convenções, a amostra explica como aplicar o atributo a todas as páginas de uma pasta e a uma única página.

Convenção de modelo de aplicativo de pasta

Use AddFolderApplicationModelConvention para criar e adicionar um IPageApplicationModelConvention que invoca uma ação em instâncias PageApplicationModel para todas as páginas na pasta especificada.

A amostra explica o uso de AddFolderApplicationModelConvention adicionando um cabeçalho, OtherPagesHeader, às páginas dentro da pasta OtherPages do aplicativo:

options.Conventions.AddFolderApplicationModelConvention("/OtherPages", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "OtherPagesHeader", new string[] { "OtherPages Header Value" }));
});

Solicite a página Page1 da amostra em localhost:5000/OtherPages/Page1 e inspecione os cabeçalhos para exibir o resultado:

Response headers of the OtherPages/Page1 page show that the OtherPagesHeader has been added.

Convenção de modelo de aplicativo de página

Use AddPageApplicationModelConvention para criar e adicionar um IPageApplicationModelConvention que invoca uma ação no PageApplicationModel para a página no nome especificado.

A amostra explica o uso de AddPageApplicationModelConvention adicionando um cabeçalho, AboutHeader, à página About:

options.Conventions.AddPageApplicationModelConvention("/About", model =>
{
    model.Filters.Add(new AddHeaderAttribute(
        "AboutHeader", new string[] { "About Header Value" }));
});

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that the AboutHeader has been added.

Configurar um filtro

ConfigureFilter configura o filtro especificado a ser aplicado. É possível implementar uma classe de filtro, mas o aplicativo de exemplo mostra como implementar um filtro em uma expressão lambda, que é implementado em segundo plano como um alocador que retorna um filtro:

options.Conventions.ConfigureFilter(model =>
{
    if (model.RelativePath.Contains("OtherPages/Page2"))
    {
        return new AddHeaderAttribute(
            "OtherPagesPage2Header", 
            new string[] { "OtherPages/Page2 Header Value" });
    }
    return new EmptyFilter();
});

O modelo de aplicativo de página é usado para verificar o caminho relativo para segmentos que levam à página Page2 na pasta OtherPages. Se a condição é aprovada, um cabeçalho é adicionado. Caso contrário, o EmptyFilter é aplicado.

EmptyFilter é um filtro de Ação. Como os filtros de ação são ignorados por páginas Razor , o EmptyFilter não terá o efeito pretendido se o caminho não contiver OtherPages/Page2.

Solicite a página Page2 da amostra em localhost:5000/OtherPages/Page2 e inspecione os cabeçalhos para exibir o resultado:

The OtherPagesPage2Header is added to the response for Page2.

Configurar um alocador de filtro

ConfigureFilter configura o alocador especificado para aplicar filtros a todas as Páginas Razor.

O aplicativo de exemplo fornece um exemplo de como usar um alocador de filtro adicionando um cabeçalho, FilterFactoryHeader, com dois valores para as páginas do aplicativo:

options.Conventions.ConfigureFilter(new AddHeaderWithFactory());

AddHeaderWithFactory.cs:

public class AddHeaderWithFactory : IFilterFactory
{
    // Implement IFilterFactory
    public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
    {
        return new AddHeaderFilter();
    }

    private class AddHeaderFilter : IResultFilter
    {
        public void OnResultExecuting(ResultExecutingContext context)
        {
            context.HttpContext.Response.Headers.Add(
                "FilterFactoryHeader", 
                new string[] 
                { 
                    "Filter Factory Header Value 1",
                    "Filter Factory Header Value 2"
                });
        }

        public void OnResultExecuted(ResultExecutedContext context)
        {
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Solicite a página About da amostra em localhost:5000/About e inspecione os cabeçalhos para exibir o resultado:

Response headers of the About page show that two FilterFactoryHeader headers have been added.

Filtros MVC e o filtro de Página (IPageFilter)

Os filtros de Ação MVC são ignorados pelas Páginas Razor, pois as páginas Razor usam métodos de manipulador. Outros tipos de filtros MVC estão disponíveis para uso: Autorização, Exceção, Recurso e Resultado. Para obter mais informações, consulte o tópico Filtros.

O filtro de Página (IPageFilter) é um filtro que se aplica às Páginas do Razor. Para obter mais informações, confira Métodos de filtragem para Páginas do Razor.

Recursos adicionais