Compartilhar via


Roteamento do 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 do .NET 10 deste artigo.

Aviso

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

Este artigo explica o Blazor roteamento de solicitações de aplicativo com diretrizes sobre roteamento estático versus interativo, integração de roteamento de ponto de extremidade do ASP.NET Core, eventos de navegação e modelos de rota e restrições para Razor componentes.

O roteamento em Blazor é realizado 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 da rota. No runtime, o roteador pesquisa por classes de componente com um RouteAttribute e renderiza qualquer componente que tenha um modelo de rota correspondente à URL solicitada.

O seguinte componente HelloWorld usa um modelo de rota /hello-world, e a página da Web renderizada do componente é acessada pela URL relativa /hello-world.

HelloWorld.razor:

@page "/hello-world"

<h1>Hello World!</h1>

O componente anterior é carregado no navegador /hello-world independentemente de você adicionar ou não o componente à navegação da interface do usuário do aplicativo como um link.

Roteamento estático versus interativo

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

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

Quando um modo de renderização interativa é atribuído ao componente Routes, o roteador Blazor se torna interativo após a SSR estática com o 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 da solicitação HTTP para determinar qual componente será renderizado. Quando o roteador se torna interativo, ele usa a URL do documento (a URL na barra de endereços do navegador) para determinar qual componente será renderizado. Isso significa que o roteador interativo pode alterar dinamicamente qual componente é renderizado se a URL do documento for alterada dinamicamente para outra URL interna válida e poderá fazê-lo sem executar uma solicitação HTTP para buscar o novo conteúdo da página.

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

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

Essa seção se aplica aos Blazor Web Apps que operam em um circuito.

O Blazor Web App é integrado ao Roteamento de Endpoint do ASP.NET Core. Um aplicativo ASP.NET Core é configurado com endpoints para componentes roteáveis e para definir o componente raiz a ser renderizado para esses endpoints no arquivo MapRazorComponentsProgram. O componente raiz padrão (primeiro componente carregado) é o componente App (App.razor):

app.MapRazorComponents<App>();

Esta seção se aplica a Blazor Server aplicativos que operam em um circuito.

O Blazor Server é integrado ao Roteamento de Ponto de Extremidade do ASP.NET Core. Um aplicativo ASP.NET Core é configurado para aceitar conexões de entrada para componentes interativos com MapBlazorHub no arquivo Program:

app.UseRouting();

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

Esta seção se aplica a Blazor Server aplicativos que operam em um circuito.

O Blazor Server é integrado ao Roteamento de Ponto de Extremidade do ASP.NET Core. Um aplicativo ASP.NET Core é 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 Razor Page, que atua como o host do aplicativo Blazor Server do lado do servidor. Por convenção, a página host geralmente é nomeada _Host.cshtml na pasta Pages do aplicativo.

A rota especificada no arquivo de host é chamada de rota de fallback 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 no roteamento de componentes no aplicativo Blazor Server.

Para obter informações sobre como configurar MapFallbackToPage para hospedagem de servidor de URL não raiz, consulte caminho base do aplicativo ASP.NET Core Blazor.

Modelos de rota

O componente Router habilita o roteamento para componentes Razore está localizado no componente Routes do aplicativo (Components/Routes.razor).

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

Quando um Razorcomponente (.razor) com uma @pagediretiva é compilado, a classe de componente gerada recebe um RouteAttribute que especifica o modelo de rota do componente.

Quando o aplicativo é iniciado, o assembly especificado como AppAssembly do Roteador é verificado para a coleta de informações de rota para os componentes do aplicativo que têm um RouteAttribute.

Em runtime, o componente RouteView:

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

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

Os componentes dão suporte a vários modelos de rota usando várias @page diretivas. 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 resolvam corretamente, o aplicativo precisa incluir uma marcação de <base> (local do conteúdo <head>) com o caminho base do aplicativo especificado no atributo href . Para obter mais informações, consulte Caminho base do aplicativo ASP.NET CoreBlazor.

O Router não interage com valores de cadeia de caracteres de consulta. Para trabalhar com cadeias de caracteres de consulta, consulte cadeias de caracteres de consulta.

Como alternativa para especificar o modelo de rota como um literal de cadeia de caracteres com a diretiva @page, modelos de rota baseados em constante podem ser especificados com a @attribute diretiva.

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

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

Observação

Com a versão do .NET 5.0.1 e para quaisquer versões adicionais de 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.

Concentrar um elemento na navegação

O componente FocusOnNavigate define o foco da interface do usuário em um elemento com base 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 no cabeçalho de nível superior da página (<h1>). Essa é uma estratégia comum para garantir que a navegação em uma página será anunciada no uso de um leitor de tela.

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

Para solicitações em que o conteúdo não foi encontrado, um componente Razor pode ser atribuído ao parâmetro NotFoundPage de componente Router. O parâmetro funciona em conjunto com NavigationManager.NotFound, um método chamado no código do desenvolvedor que dispara uma Resposta Não Encontrada. NavigationManager.NotFound é descrito no próximo artigo, ASP.NET Core navegaçãoBlazor.

O Blazor modelo de projeto inclui uma NotFound.razor página. Essa página é renderizada automaticamente sempre que NavigationManager.NotFound é chamada, possibilitando lidar com rotas ausentes com uma experiência de usuário 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 NotFound componente é atribuído ao parâmetro do NotFoundPage roteador. NotFoundPage é compatível com o roteamento que pode ser utilizado em middleware de reexecução de páginas de códigos de status, inclusive middleware que não seja Blazor.

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 obter mais informações, consulte o próximo artigo sobre a navegação do ASP.NET CoreBlazor.

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

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

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

Há suporte para itens arbitrários como conteúdo do parâmetro NotFound, como outros componentes interativos. Para aplicar um layout padrão ao conteúdo de NotFound, confira Layouts do ASP.NET Core Blazor.

Blazor Web Apps não usam o NotFound parâmetro (<NotFound>...</NotFound> marcação), mas o parâmetro tem suporte† para compatibilidade com versões anteriores no .NET 8/9 para evitar uma alteração significativa na estrutura. 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 malsucedidas.

Compatível neste contexto significa que adicionar marcação <NotFound>...</NotFound> não gera uma exceção, mas usar a marcação não é eficaz.

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

Rotear para componentes de vários assemblies

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

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

Roteamento estático

Para descobrir componentes roteáveis de assemblies adicionais para SSR estática, mesmo que o roteador mais tarde se torne interativo para renderização interativa, os assemblies deverão ser divulgados para a estrutura Blazor. Chame o método AddAdditionalAssemblies com os assemblies adicionais encadeados ao MapRazorComponents no arquivo Program do projeto do servidor.

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

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

Observação

As diretrizes anteriores também se aplicam em cenários de biblioteca de classes de componente. Diretrizes importantes adicionais para bibliotecas de classes e SSR estática são encontradas nas bibliotecas de classes (RCLs) Razor do ASP.NET Core com renderização estática do lado do servidor (SSR estática).

Roteamento interativo

Um modo de renderização interativo pode ser atribuído ao componente Routes (Routes.razor) que torna o roteador Blazor interativo após a SSR estática e o roteamento estático no servidor. Por exemplo, <Routes @rendermode="InteractiveServer" /> atribui a renderização interativa do lado do servidor (SSR interativa) ao componente Routes. O componente Router herda a renderização interativa do lado do servidor (SSR interativa) 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áginas internas. Para obter mais informações, consulte ASP.NET Persistência de estado prerendered CoreBlazor.

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

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

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

Assemblies adicionais são verificados além do assembly especificado para AppAssembly.

Observação

As diretrizes anteriores também se aplicam em cenários de biblioteca de classes de componente.

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 do servidor. Nesse caso, não há assemblies externos com componentes roteáveis, portanto, não é necessário especificar um valor para AdditionalAssemblies.

Esta seção aplica-se a aplicativos Blazor Server.

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

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

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

Assemblies adicionais são verificados além do assembly especificado para AppAssembly.

Parâmetros de rota

O roteador usa parâmetros de rota para preencher os parâmetros de componente correspondentes com o mesmo nome. Nomes de parâmetro de rota não diferenciam maiúsculas de minúsculas. No exemplo a seguir, o parâmetro text atribui o valor do segmento de rota à propriedade do Text componente. Quando uma solicitação é feita para /route-parameter-1/amazing, o conteúdo é renderizado 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; }
}

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

Não há suporte a parâmetros opcionais. No exemplo a seguir, duas @page diretivas 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 vidaOnInitialized{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 navega 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 caracteres de consulta, consulte cadeias de caracteres de consulta.

Restrições da rota

É uma restrição de rota que garante a correspondência de tipo entre um segmento de rota e um componente.

No exemplo a seguir, a rota para o componente User só terá correspondência se:

  • Um segmento de rota Id está presente na URL de 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

Restrições de rota não funcionam com valores de cadeia de caracteres de consulta. Para trabalhar com cadeias de caracteres de consulta, consulte cadeias de caracteres 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 invariável, confira o aviso abaixo da tabela para mais informações.

Restrição Exemplo Correspondências de exemplo Invariável
cultura
correspondência
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} Não BlazorSample.styles.css, não favicon.ico Sim

Aviso

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

As restrições de rota também funcionam com parâmetros opcionais. No exemplo a seguir, Id é obrigatório, mas Option é um parâmetro de rota booliano 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; }
}

Evitar a captura de arquivos em parâmetros 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 para capturar caminhos que não são 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 (.), um arquivo será solicitado. Por exemplo, a URL relativa /example/some.thing é interpretada pelo roteador como uma solicitação de um arquivo chamado some.thing. Sem configuração adicional, um aplicativo retornará uma resposta 404 – Não encontrado se some.thing devesse rotear para um componente com uma diretiva @page e some.thing é um valor de parâmetro de rota. Para usar uma rota com um ou mais parâmetros que contenham um ponto, o aplicativo precisará configurar a rota com um modelo personalizado.

Considere o componente Example a seguir que pode receber um parâmetro de rota do último segmento da URL.

Example.razor:

@page "/example/{param?}"

<p>
    Param: @Param
</p>

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

Para permitir que o aplicativo de uma solução hospedada encaminhe a solicitação com um ponto no parâmetro de rota , adicione um modelo de rota de arquivo de fallback com o parâmetro opcional no arquivo :

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

Para configurar um aplicativo Blazor Server para rotear a solicitação com um ponto no parâmetro de rota param, adicione um modelo de rota de página de fallback com o parâmetro opcional no arquivo Program:

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

Saiba mais em Roteamento no ASP.NET Core.

Para permitir que o aplicativo Server de uma solução Blazor WebAssemblyhospedada encaminhe a solicitação com um ponto no parâmetro de rota param, adicione um modelo de rota de arquivo de fallback com o parâmetro opcional em Startup.Configure.

Startup.cs:

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

Para configurar um aplicativo Blazor Server para rotear a solicitação com um ponto no parâmetro de rota param, adicione um modelo de rota de página de fallback com o parâmetro opcional em Startup.Configure.

Startup.cs:

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

Saiba mais em Roteamento no ASP.NET Core.

Parâmetros de rota catch-all

Os parâmetros de rota catch-all, que capturam caminhos entre vários limites de pasta, têm suporte nos componentes.

Os parâmetros de rota catch-all são:

  • Nomeados de forma a corresponder ao nome do segmento de rota. A nomenclatura não diferencia maiúsculas de 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 a URL /catch-all/this/is/a/test com um modelo de rota /catch-all/{*pageRoute}, o valor de PageRoute é definido como this/is/a/test.

Barras 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 resulta em this/is/a/test*.

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

O componente Router dá suporte a um recurso de OnNavigateAsync. O manipulador 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, confira Carregamento preguiçoso de assemblies no ASP.NET Core Blazor WebAssembly.

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

  • Uma vez, quando o componente de ponto de extremidade solicitado é inicialmente renderizado estaticamente.
  • Uma segunda vez quando o navegador renderiza o componente do ponto de extremidade.

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

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

Gerenciar cancelamentos em OnNavigateAsync

O objeto NavigationContext transmitido ao retorno de chamada OnNavigateAsync contém um CancellationToken definido quando ocorre um novo evento de navegação. O retorno de chamada OnNavigateAsync precisa lançar quando esse token de cancelamento é definido a fim de evitar continuar a executar o retorno de chamada OnNavigateAsync em uma navegação desatualizada.

Se um usuário navegar até um ponto de extremidade, mas depois navegar imediatamente até um novo ponto de extremidade, o aplicativo não deverá continuar executando o retorno de chamada OnNavigateAsync para o primeiro ponto de extremidade.

No exemplo a seguir:

  • O token de cancelamento é transmitido na chamada a PostAsJsonAsync, o que pode cancelar o POST se o usuário navegar para longe do ponto de extremidade /about.
  • O token de cancelamento é definido durante uma operação de pré-busca do produto se o usuário navegar para longe do ponto de extremidade /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 poderá resultar em um comportamento não intencional, como a renderização de um componente de uma navegação anterior.

Interação do usuário 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 poderá 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 roteador (<Router>...</Router>):

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

Para obter um exemplo que usa a propriedade Navigating, confira Carregamento preguiçoso de assemblies no ASP.NET Core Blazor WebAssembly.