Partilhar via


Encaminhamento ASP.NET Core Blazor

Observação

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 10 deste artigo.

Advertência

Esta versão do ASP.NET Core não é mais suportada. Para obter mais informações, consulte a Política de suporte do .NET e .NET Core. Para a versão atual, consulte a versão .NET 10 deste artigo.

Este artigo explica Blazor o encaminhamento de pedidos de aplicações com orientações sobre o roteamento estático versus interativo, a integração do encaminhamento de endpoints do ASP.NET Core, eventos de navegação, e modelos e restrições de rota para componentes Razor.

O roteamento em Blazor é obtido fornecendo um modelo de rota para cada componente acessível no aplicativo com uma diretiva @page. Quando um arquivo Razor com uma diretiva @page é compilado, a classe gerada recebe um RouteAttribute especificando o modelo de rota. No tempo de execução, o roteador procura classes de componentes com um RouteAttribute e renderiza qualquer componente que tenha um modelo de rota que corresponda à URL solicitada.

O componente HelloWorld a seguir usa um modelo de rota de /hello-worlde a página da Web renderizada para o componente é alcançada na URL relativa /hello-world.

HelloWorld.razor:

@page "/hello-world"

<h1>Hello World!</h1>

O componente anterior carrega no navegador /hello-world independentemente de adicionar ou não o componente à navegação da interface da aplicação como um link.

Roteamento estático versus interativo

Esta seção aplica-se a Blazor Web Apps.

Se a pré-renderização estiver ativada, o roteador Blazor (componenteRouter, <Router> no Routes.razor) realiza roteamento estático para os componentes durante a renderização do lado do servidor estática (SSR). Esse tipo de roteamento é chamado roteamento estático.

Quando um modo de renderização interativo é atribuído ao componente Routes, o roteador Blazor torna-se interativo após SSR estático com roteamento estático no servidor. Esse tipo de roteamento é chamado de roteamento interativo .

Os roteadores estáticos usam o roteamento de ponto de extremidade e o caminho de solicitação HTTP para determinar qual componente renderizar. Quando o roteador se torna interativo, ele usa a URL do documento (a URL na barra de endereço do navegador) para determinar qual componente renderizar. Isso significa que o roteador interativo pode alterar dinamicamente qual componente é renderizado se a URL do documento mudar dinamicamente para outra URL interna válida, e pode fazer isso sem executar uma solicitação HTTP para buscar novo conteúdo de página.

O roteamento interativo também impede a pré-renderização porque o novo conteúdo da página não é solicitado ao servidor com uma solicitação de página normal. Para obter mais informações, consulte Persistência de estado pré-renderizado do núcleo ASP.NETBlazor.

Integração de roteamento de endpoint do ASP.NET Core

Esta secção aplica-se aos Blazor Web Appque operam num circuito.

Um Blazor Web App é integrado ao ASP.NET Core Endpoint Routing. Uma aplicação ASP.NET Core está configurada com endpoints para componentes roteáveis e o componente raiz para renderizar esses endpoints MapRazorComponents no Program ficheiro. O componente raiz padrão (primeiro componente carregado) é o componente App (App.razor):

app.MapRazorComponents<App>();

Esta secção aplica-se a Blazor Server aplicações que operam num circuito.

Blazor Server está integrado no ASP.NET Core Endpoint Routing. Um aplicativo ASP.NET Core está configurado para aceitar conexões de entrada para componentes interativos com MapBlazorHub no arquivo Program:

app.UseRouting();

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

Esta secção aplica-se a Blazor Server aplicações que operam num circuito.

Blazor Server está integrado no ASP.NET Core Endpoint Routing. Um aplicativo ASP.NET Core está configurado para aceitar conexões de entrada para componentes interativos com MapBlazorHub no Startup.Configure.

A configuração típica é rotear todas as solicitações para uma página de Razor, que atua como o host para a parte do lado do servidor do aplicativo Blazor Server. Por convenção, a página host geralmente é nomeada _Host.cshtml na pasta Pages do aplicativo.

A rota especificada no ficheiro de anfitrião é chamada de rota de recurso porque opera com baixa prioridade na correspondência de rotas. A rota de fallback é usada quando outras rotas não correspondem. Isso permite que o aplicativo use outros controladores e páginas sem interferir com o roteamento de componentes no aplicativo Blazor Server.

Para obter informações sobre como configurar MapFallbackToPage para hospedagem de servidor com URL não raiz, consulte caminho base de aplicativos ASP.NET CoreBlazor.

Modelos de rotas

O componente Router permite o encaminhamento para componentes Razor e está localizado no componente Routes da aplicação (Components/Routes.razor).

O componente Router permite o roteamento para componentes Razor. O componente Router é usado no componente App (App.razor).

Quando um componente Razor (.razor) com uma diretiva @page é compilado, a classe do componente gerada recebe uma RouteAttribute especificando o modelo de rota do componente.

Quando a aplicação é iniciada, o assembly especificado como AppAssembly do Router é analisado para recolher informações de rota para os componentes da aplicação que têm um RouteAttribute.

Durante a execução, o componente RouteView:

  • Recebe o RouteData do Router juntamente com quaisquer parâmetros de rota.
  • Renderiza o componente especificado com o seu layout , incluindo quaisquer layouts aninhados adicionais.

Opcionalmente, especifique um parâmetro DefaultLayout com uma classe de layout para componentes que não especificam um layout com a diretiva @layout. Os modelos de projeto Blazor do framework especificam o componente MainLayout (MainLayout.razor) como a estrutura padrão da aplicação. Para obter mais informações sobre layouts, consulte layouts do ASP.NET CoreBlazor.

Os componentes suportam vários modelos de rota usando várias diretivas @page. O componente de exemplo a seguir é carregado em solicitações de /blazor-route e /different-blazor-route.

BlazorRoute.razor:

@page "/blazor-route"
@page "/different-blazor-route"

<h1>Routing Example</h1>

<p>
    This page is reached at either <code>/blazor-route</code> or 
    <code>/different-blazor-route</code>.
</p>

Importante

Para que as URLs sejam resolvidas corretamente, a aplicação deve incluir uma marca <base> (localização de <head> conteúdo) com o caminho base da aplicação especificado no atributo href. Para obter mais informações, consulte ASP.NET Core caminho base da aplicaçãoBlazor.

O Router não interage com valores de cadeia de caracteres de consulta. Para trabalhar com cadeias de consulta, veja Sequências de consulta.

Como alternativa à especificação do modelo de rota como uma cadeia de caracteres literal com a diretiva @page, modelos de rota baseados em constantes podem ser especificados com a diretiva @attribute.

No exemplo a seguir, a diretiva @page em um componente é substituída pela diretiva @attribute e pelo modelo de rota baseado em constante no Constants.CounterRoute, que é definido em outro lugar do aplicativo como "/counter":

- @page "/counter"
+ @attribute [Route(Constants.CounterRoute)]

Observação

Com o lançamento do .NET 5.0.1 e para quaisquer versões adicionais do 5.x, o Router componente inclui o PreferExactMatches parâmetro definido como @true. Para obter mais informações, consulte Migrar do ASP.NET Core 3.1 para o .NET 5.

Colocar o foco em um elemento na navegação

O componente FocusOnNavigate define o foco da interface do usuário como um elemento baseado em um seletor CSS depois de navegar de uma página para outra.

<FocusOnNavigate RouteData="routeData" Selector="h1" />

Quando o componente Router navega para uma nova página, o componente FocusOnNavigate define o foco para o cabeçalho de nível superior da página (<h1>). Esta é uma estratégia comum para garantir que uma navegação de página seja anunciada ao usar um leitor de tela.

Fornecer conteúdo personalizado quando o conteúdo não for encontrado

Para pedidos onde o conteúdo não é encontrado, um componente Razor pode ser atribuído ao parâmetro NotFoundPage do componente Router. O parâmetro funciona em conjunto com NavigationManager.NotFound, um método chamado no código de desenvolvimento que desencadeia uma resposta Não Encontrado. é descrito no artigo seguinte, navegação do ASP.NET Core.

O modelo de projeto Blazor inclui uma página NotFound.razor. Esta página é automaticamente renderizada sempre que NavigationManager.NotFound é chamada, tornando possível gerir rotas em falta com uma experiência de utilizador consistente.

NotFound.razor:

@page "/not-found"
@layout MainLayout

<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>

O componente NotFound é atribuído ao parâmetro NotFoundPage do router. NotFoundPage suporta o roteamento que pode ser usado no middleware de reexecução para páginas de códigos de status, incluindo opções além do middleware padrão.

No exemplo a seguir, o componente anterior NotFound está presente na pasta do Pages aplicativo e é passado para o NotFoundPage parâmetro:

<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>

Para mais informações, consulte o próximo artigo sobre navegação no ASP.NET CoreBlazor.

O componente Router permite que o aplicativo especifique conteúdo personalizado se o conteúdo não for encontrado para a rota solicitada.

Defina conteúdo personalizado para o parâmetro Router do componente NotFound:

<Router ...>
    ...
    <NotFound>
        ...
    </NotFound>
</Router>

Itens arbitrários são suportados como conteúdo do parâmetro NotFound, como outros componentes interativos. Para aplicar um layout padrão ao NotFound conteúdo, consulte layouts do ASP.NET CoreBlazor.

Blazor Web Apps não usa o parâmetro NotFound (<NotFound>...</NotFound> markup), mas é suportado† para compatibilidade retroativa no .NET 8/9, evitando assim uma alteração disruptiva no framework. O pipeline de middleware ASP.NET Core do lado do servidor processa solicitações no servidor. Use técnicas do lado do servidor para lidar com solicitações incorretas.

suportado neste contexto significa que colocar a marcação <NotFound>...</NotFound> não resulta em excepção, mas usar a marcação também não é eficaz.

Para obter mais informações, consulte os seguintes recursos:

Caminho para componentes de várias montagens

Esta seção aplica-se a Blazor Web Apps.

Use o parâmetro Router do componente AdditionalAssemblies e o construtor de convenções do ponto de extremidade AddAdditionalAssemblies para descobrir componentes enrutáveis em assemblies adicionais. As subseções a seguir explicam quando e como usar cada API.

Roteamento estático

Para descobrir componentes roteáveis a partir de conjuntos adicionais para renderização estática no lado do servidor (SSR estático), mesmo que o roteador posteriormente se torne interativo para renderização interativa, os conjuntos devem ser tornados acessíveis à estrutura Blazor. Chame o método AddAdditionalAssemblies com os assemblies adicionais encadeados a MapRazorComponents no ficheiro Program do projeto de servidor.

O exemplo a seguir inclui os componentes roteáveis no assembly do projeto BlazorSample.Client usando o arquivo _Imports.razor do projeto:

app.MapRazorComponents<App>()
    .AddAdditionalAssemblies(typeof(BlazorSample.Client._Imports).Assembly);

Observação

A orientação anterior também se aplica em cenários da biblioteca de classes de componentes . Orientações adicionais importantes para bibliotecas de classes e SSR estático são encontradas em bibliotecas de classes do ASP.NET Core Razor (RCLs) com SSR estático (renderização estática do lado do servidor).

Roteamento interativo

Um modo de renderização interativo pode ser atribuído ao componente Routes (Routes.razor) que faz com que o roteador Blazor se torne interativo após SSR estático e roteamento estático no servidor. Por exemplo, <Routes @rendermode="InteractiveServer" /> atribui renderização interativa do lado do servidor (SSR interativo) ao componente Routes. O componente Router herda a renderização interativa do lado do servidor (SSR interativo) do componente Routes. O roteador torna-se interativo após o roteamento estático no servidor.

A navegação interna para roteamento interativo não envolve a solicitação de novo conteúdo de página do servidor. Portanto, a pré-renderização não ocorre para solicitações de página internas. Para obter mais informações, consulte Persistência de estado pré-renderizado do núcleo ASP.NETBlazor.

Se o componente Routes for definido no projeto de servidor, o parâmetro AdditionalAssemblies do componente Router deverá incluir o assembly do projeto .Client. Isso permite que o roteador funcione corretamente quando processado interativamente.

No exemplo a seguir, o componente Routes está no projeto de servidor e o arquivo de _Imports.razor do projeto BlazorSample.Client indica o assembly para procurar componentes roteáveis:

<Router
    AppAssembly="..."
    AdditionalAssemblies="[ typeof(BlazorSample.Client._Imports).Assembly ]">
    ...
</Router>

Conjuntos adicionais são analisados além do conjunto especificado para AppAssembly.

Observação

A orientação anterior também se aplica em cenários da biblioteca de classes de componentes .

Como alternativa, os componentes roteáveis só existem no projeto .Client com WebAssembly interativo global ou renderização automática aplicada, e o componente Routes é definido no projeto .Client, não no projeto de servidor. Nesse caso, não há assemblies externos com componentes roteáveis, portanto, não é necessário especificar um valor para AdditionalAssemblies.

Esta secção aplica-se a aplicações Blazor Server.

Use o parâmetro Router do componente AdditionalAssemblies e o construtor de convenções do ponto de extremidade AddAdditionalAssemblies para descobrir componentes enrutáveis em assemblies adicionais.

No exemplo a seguir, Component1 é um componente roteável definido em uma biblioteca de classes de componente referenciada chamada ComponentLibrary:

<Router
    AppAssembly="..."
    AdditionalAssemblies="new[] { typeof(ComponentLibrary.Component1).Assembly }">
    ...
</Router>

Conjuntos adicionais são analisados além do conjunto especificado para AppAssembly.

Parâmetros de rota

O roteador usa parâmetros de rota para preencher os parâmetros dos componentes correspondentes com o mesmo nome. Os nomes dos parâmetros de rota são insensíveis a maiúsculas e minúsculas. No exemplo a seguir, o parâmetro text atribui o valor do segmento de rota à propriedade Text do componente. Quando uma solicitação é feita para /route-parameter-1/amazing, o conteúdo é processado como Blazor is amazing!.

RouteParameter1.razor:

@page "/route-parameter-1/{text}"

<h1>Route Parameter Example 1</h1>

<p>Blazor is @Text!</p>

@code {
    [Parameter]
    public string? Text { get; set; }
}

Parâmetros opcionais são suportados. No exemplo a seguir, o parâmetro opcional text atribui o valor do segmento de rota à propriedade Text do componente. Se o segmento não estiver presente, o valor de Text será definido como fantastic.

Não há suporte para parâmetros opcionais. No exemplo a seguir, duas diretivas @page são aplicadas. A primeira diretiva permite a navegação para o componente sem um parâmetro. A segunda diretiva atribui o valor do parâmetro de rota {text} à propriedade Text do componente.

RouteParameter2.razor:

@page "/route-parameter-2/{text?}"

<h1>Route Parameter Example 2</h1>

<p>Blazor is @Text!</p>

@code {
    [Parameter]
    public string? Text { get; set; }

    protected override void OnParametersSet() => Text = Text ?? "fantastic";
}

Quando o método de ciclo de vida OnInitialized{Async} é usado em vez do método de ciclo de vida OnParametersSet{Async}, a atribuição padrão da propriedade Text a fantastic não ocorre se o usuário navegar dentro do mesmo componente. Por exemplo, essa situação surge quando o usuário navega de /route-parameter-2/amazing para /route-parameter-2. Como a instância do componente persiste e aceita novos parâmetros, o método OnInitialized não é invocado novamente.

Observação

Os parâmetros de rota não funcionam com valores de cadeia de caracteres de consulta. Para trabalhar com cadeias de consulta, veja Sequências de consulta.

Restrições de rota

Uma restrição de rota impõe a correspondência de tipos num segmento de rota para um componente.

No exemplo a seguir, a rota para o componente User só corresponde se:

  • Um segmento de rota Id está presente na URL da solicitação.
  • O segmento Id é um tipo inteiro (int).

User.razor:

@page "/user/{Id:int}"

<h1>User Example</h1>

<p>User Id: @Id</p>

@code {
    [Parameter]
    public int Id { get; set; }
}

Observação

As restrições de rota não funcionam com valores de cadeia de caracteres de consulta. Para trabalhar com cadeias de consulta, veja Sequências de consulta.

As restrições de rota mostradas na tabela a seguir estão disponíveis. Para as restrições de rota que correspondem à cultura invariante, consulte o aviso abaixo da tabela para obter mais informações.

Restrição Exemplo Exemplos de combinações Invariante
cultura
emparelhamento
bool {active:bool} true, FALSE Não
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm Sim
decimal {price:decimal} 49.99, -1,000.01 Sim
double {weight:double} 1.234, -1,001.01e8 Sim
float {weight:float} 1.234, -1,001.01e8 Sim
guid {id:guid} 00001111-aaaa-2222-bbbb-3333cccc4444, {00001111-aaaa-2222-bbbb-3333cccc4444} Não
int {id:int} 123456789, -123456789 Sim
long {ticks:long} 123456789, -123456789 Sim
nonfile {parameter:nonfile} Nem BlazorSample.styles.css, nem favicon.ico Sim

Advertência

As restrições de rota que verificam a URL e são convertidas num tipo CLR (como int ou DateTime) utilizam sempre a cultura invariável. Essas restrições pressupõem que a URL não é localizável.

As restrições de rota também funcionam com parâmetros opcionais. No exemplo a seguir, Id é necessário, mas Option é um parâmetro de rota booleano opcional.

User.razor:

@page "/user/{id:int}/{option:bool?}"

<p>
    Id: @Id
</p>

<p>
    Option: @Option
</p>

@code {
    [Parameter]
    public int Id { get; set; }

    [Parameter]
    public bool Option { get; set; }
}

Evite a captura de arquivos num parâmetro de rota

O modelo de rota a seguir captura inadvertidamente caminhos de ativos estáticos em seu parâmetro de rota opcional (Optional). Por exemplo, a folha de estilo do aplicativo (.styles.css) é capturada, o que quebra os estilos do aplicativo:

@page "/{optional?}"

...

@code {
    [Parameter]
    public string? Optional { get; set; }
}

Para restringir um parâmetro de rota à captura de caminhos que não sejam de arquivo, use a restrição :nonfile no modelo de rota.

@page "/{optional:nonfile?}"

Roteamento com URLs que contêm pontos

Um modelo de rota padrão do lado do servidor pressupõe que, se o último segmento de uma URL de solicitação contiver um ponto (.) que um arquivo é solicitado. Por exemplo, a URL relativa /example/some.thing é interpretada pelo roteador como uma solicitação para um arquivo chamado some.thing. Sem configuração adicional, uma aplicação retorna uma resposta 404 - Não Encontrado se some.thing estiver direcionado para um componente com uma diretiva @page e some.thing for um valor atribuído ao parâmetro de rota. Para usar uma rota com um ou mais parâmetros que contêm um ponto, o aplicativo deve configurar a rota com um modelo personalizado.

Considere o seguinte componente Example que pode receber um parâmetro route do último segmento da URL.

Example.razor:

@page "/example/{param?}"

<p>
    Param: @Param
</p>

@code {
    [Parameter]
    public string? Param { get; set; }
}

Para permitir que a aplicação Server de uma Blazor WebAssemblysolução hospedada processe pedidos que contenham um ponto no parâmetro da rota param, adicione um modelo de rota de ficheiro de fallback com o parâmetro opcional no ficheiro Program.

app.MapFallbackToFile("/example/{param?}", "index.html");

Para configurar uma aplicação Blazor Server para encaminhar a solicitação com um ponto no parâmetro de rota param, adicione um modelo de rota de página alternativa com o parâmetro opcional no ficheiro Program.

app.MapFallbackToPage("/example/{param?}", "/_Host");

Para obter mais informações, consulte Roteamento no ASP.NET Core.

Para permitir que a aplicação Server de uma Blazor WebAssemblysolução hospedada processe a solicitação com um ponto no parâmetro de rota param, acrescente um modelo de rota de ficheiro de contingência com o parâmetro opcional em Startup.Configure.

Startup.cs:

endpoints.MapFallbackToFile("/example/{param?}", "index.html");

Para configurar um aplicativo Blazor Server para redirecionar uma solicitação que contenha um ponto no parâmetro de rota param, adicione um modelo de rota alternativa para páginas, incluindo o parâmetro opcional em Startup.Configure.

Startup.cs:

endpoints.MapFallbackToPage("/example/{param?}", "/_Host");

Para obter mais informações, consulte Roteamento no ASP.NET Core.

Parâmetros de rota gerais

Os parâmetros de rota abrangentes, que capturam caminhos através de vários limites de pasta, são suportados nos componentes.

Os parâmetros de rota genéricos são:

  • Nomeado para corresponder ao nome do segmento de rota. A nomeação não faz distinção entre maiúsculas e minúsculas.
  • Um tipo string. A estrutura não fornece conversão automática.
  • No final da URL.

CatchAll.razor:

@page "/catch-all/{*pageRoute}"

<h1>Catch All Parameters Example</h1>

<p>Add some URI segments to the route and request the page again.</p>

<p>
    PageRoute: @PageRoute
</p>

@code {
    [Parameter]
    public string? PageRoute { get; set; }
}

Para o URL /catch-all/this/is/a/test com o modelo de rota /catch-all/{*pageRoute}, o valor de PageRoute é definido para this/is/a/test.

As barras (slashes) e segmentos do caminho capturado são decodificados. Para um modelo de rota de /catch-all/{*pageRoute}, a URL /catch-all/this/is/a%2Ftest%2A gera this/is/a/test*.

Manipular eventos de navegação assíncrona com OnNavigateAsync

O componente Router suporta um recurso OnNavigateAsync. O manipulador de OnNavigateAsync é invocado quando o usuário:

<Router AppAssembly="typeof(App).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        ...
    }
}
<Router AppAssembly="typeof(Program).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext args)
    {
        ...
    }
}

Para obter um exemplo que usa OnNavigateAsync, consulte Conjuntos de carga lentos em ASP.NET Core Blazor WebAssembly.

Ao pré-renderizar no servidor, OnNavigateAsync é executado duas vezes:

  • Uma vez quando o componente de ponto de acesso solicitado é inicialmente renderizado de forma estática.
  • Quando o navegador renderiza o componente endpoint pela segunda vez.

Para evitar que o código do desenvolvedor no OnNavigateAsync seja executado duas vezes, o componente Routes pode armazenar o NavigationContext para uso no método de ciclo de vida OnAfterRender{Async}, onde firstRender pode ser verificado. Para obter mais informações, consulte Pré-renderização com JavaScript Interop.

Para evitar que o código do desenvolvedor no OnNavigateAsync seja executado duas vezes, o componente App pode armazenar o NavigationContext para uso no OnAfterRender{Async}, onde firstRender pode ser verificado. Para obter mais informações, consulte Pré-renderização com JavaScript Interop.

Lidar com cancelamentos em OnNavigateAsync

O objeto NavigationContext passado para o callback OnNavigateAsync contém um CancellationToken que se define quando ocorre um novo evento de navegação. O callback OnNavigateAsync deve ser acionado quando este token de cancelamento for ativado para evitar a execução do callback OnNavigateAsync em uma navegação obsoleta.

Se um usuário navega para um ponto de extremidade, mas navega imediatamente para um novo ponto de extremidade, o aplicativo não deve continuar executando o retorno de chamada OnNavigateAsync para o primeiro ponto de extremidade.

No exemplo a seguir:

  • O token de cancelamento é passado na chamada para PostAsJsonAsync, o que é capaz de cancelar o POST se o utilizador se afastar do endpoint /about.
  • O token de cancelamento é definido durante uma operação de pré-busca do produto se o usuário se afastar do endpoint /store.
@inject HttpClient Http
@inject ProductCatalog Products

<Router AppAssembly="typeof(App).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext context)
    {
        if (context.Path == "/about") 
        {
            var stats = new Stats { Page = "/about" };
            await Http.PostAsJsonAsync("api/visited", stats, 
                context.CancellationToken);
        }
        else if (context.Path == "/store")
        {
            var productIds = new[] { 345, 789, 135, 689 };

            foreach (var productId in productIds) 
            {
                context.CancellationToken.ThrowIfCancellationRequested();
                Products.Prefetch(productId);
            }
        }
    }
}
@inject HttpClient Http
@inject ProductCatalog Products

<Router AppAssembly="typeof(Program).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

@code {
    private async Task OnNavigateAsync(NavigationContext context)
    {
        if (context.Path == "/about") 
        {
            var stats = new Stats { Page = "/about" };
            await Http.PostAsJsonAsync("api/visited", stats, 
                context.CancellationToken);
        }
        else if (context.Path == "/store")
        {
            var productIds = new[] { 345, 789, 135, 689 };

            foreach (var productId in productIds) 
            {
                context.CancellationToken.ThrowIfCancellationRequested();
                Products.Prefetch(productId);
            }
        }
    }
}

Observação

Não lançar se o token de cancelamento em NavigationContext for cancelado pode resultar em comportamento não intencional, como renderizar um componente de uma navegação anterior.

Interação do utilizador com conteúdo <Navigating>

Se houver um atraso significativo durante a navegação, como durante o carregamento lento de assemblies em um aplicativo Blazor WebAssembly ou para uma conexão de rede lenta com um aplicativo Blazor do lado do servidor, o componente Router pode indicar ao usuário que uma transição de página está ocorrendo.

Na parte superior do componente que especifica o componente Router, adicione uma diretiva @using para o namespace Microsoft.AspNetCore.Components.Routing:

@using Microsoft.AspNetCore.Components.Routing

Forneça conteúdo ao parâmetro Navigating para exibição durante eventos de transição de página.

No conteúdo do elemento do roteador (<Router>...</Router>):

<Navigating>
    <p>Loading the requested page&hellip;</p>
</Navigating>

Para obter um exemplo que usa a propriedade Navigating, consulte Lazy load assemblies in ASP.NET Core Blazor WebAssembly.