Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Note
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 10 de cet article.
Avertissement
Cette version d'ASP.NET Core n'est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 10 de cet article.
Cet article explique comment déclencher et gérer la navigation de page dans Blazor. Bien que les utilisateurs puissent naviguer entre différentes pages à l’aide de liens HTML normaux, Blazor améliore la navigation au sein de l’application pour éviter les rechargements de pages complètes et offrir une expérience plus fluide. Utilisez le NavLink composant pour créer des liens de navigation qui appliquent automatiquement le style lorsque le lien correspond à la page active. Pour la navigation programmatique et la gestion des URI dans le code C#, utilisez le NavigationManager service.
Cet article explique comment déclencher et gérer la navigation de page dans Blazor. Utilisez le NavLink composant pour créer des liens de navigation qui appliquent automatiquement le style lorsque le lien correspond à la page active. Pour la navigation programmatique et la gestion des URI dans le code C#, utilisez le NavigationManager service.
Important
Les exemples de code tout au long de cet article illustrent l’appel de méthodes sur Navigation, qui est un NavigationManager injecté dans les classes et les composants.
NavLink composant
Utilisez un composant NavLink à la place des éléments de lien hypertexte HTML (<a>) quand vous créez des liens de navigation. Un composant NavLink se comporte comme un élément <a>, à ceci près qu’il ajoute/supprime une classe CSS active selon que son href correspond ou non à l’URL actuelle. La classe active permet à un utilisateur de comprendre quelle est la page active parmi les liens de navigation affichés. Si vous le souhaitez, affectez un nom de classe CSS à NavLink.ActiveClass pour appliquer une classe CSS personnalisée au lien affiché quand la route actuelle correspond à href.
Dans le NavMenu composant (NavMenu.razor) d’une Blazor application créée à partir d’un Blazor modèle de projet :
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
Dans l’exemple précédent, le HomeNavLinkhref="" correspond à l’URL d’accueil et reçoit uniquement la classe CSS active sur le chemin de base par défaut de l’application (/). La seconde NavLink reçoit la classe active lorsque l’utilisateur visite le composant Counter à /counter.
Vous pouvez affecter deux options NavLinkMatch à l’attribut Match de l’élément <NavLink> :
-
NavLinkMatch.All: le NavLink est actif lorsqu’il correspond à l’URL actuelle, en ignorant la chaîne de requête et le fragment. Pour inclure la correspondance dans la chaîne/le fragment de requête, veuillez utiliser le commutateur
Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContextréglé surtrue. - NavLinkMatch.Prefix (par défaut) : NavLink est actif quand il correspond à un préfixe de l’URL actuelle.
Pour adopter une logique de correspondance personnalisée, sous-classez NavLink et remplacez sa méthode ShouldMatch. Retournez true de la méthode lorsque vous souhaitez appliquer la classe CSS active :
public class CustomNavLink : NavLink
{
protected override bool ShouldMatch(string currentUriAbsolute)
{
// Custom matching logic
}
}
Vous pouvez affecter deux options NavLinkMatch à l’attribut Match de l’élément <NavLink> :
- NavLinkMatch.All: le NavLink est actif lorsqu’il correspond à l’URL actuelle entière, y compris la chaîne de requête et le fragment.
- NavLinkMatch.Prefix (par défaut) : NavLink est actif quand il correspond à un préfixe de l’URL actuelle.
Des attributs de composant NavLink supplémentaires sont transmis à la balise d’ancrage rendue. Dans l’exemple suivant, le composant NavLink inclut l’attribut target :
<NavLink href="example-page" target="_blank">Example page</NavLink>
Le balisage HTML suivant est affiché :
<a href="example-page" target="_blank">Example page</a>
Avertissement
En raison de la façon dont Blazor affiche le contenu enfant, le rendu des composants NavLink dans une boucle for nécessite une variable d’index local si la variable de boucle d’incrémentation est utilisée dans le contenu du composant (enfant) NavLink :
@for (int c = 1; c < 4; c++)
{
var ct = c;
<li ...>
<NavLink ...>
<span ...></span> Product #@ct
</NavLink>
</li>
}
L’utilisation d’une variable d’index dans ce scénario est obligatoire pour tout composant enfant qui utilise une variable de boucle dans son contenu enfant, et pas seulement le composant NavLink.
Vous pouvez également utiliser une boucle foreach avec Enumerable.Range :
@foreach (var c in Enumerable.Range(1, 3))
{
<li ...>
<NavLink ...>
<span ...></span> Product #@c
</NavLink>
</li>
}
Outils d’assistance pour les URI et l’état de navigation
Utilisez NavigationManager pour gérer les URI et la navigation dans du code C#. NavigationManager fournit l’événement et les méthodes indiqués dans le tableau suivant.
| Membre | Descriptif |
|---|---|
| Uri | Obtient l’URI absolu actuel. |
| BaseUri | Obtient l’URI de base (avec une barre oblique finale) à ajouter aux chemins d’URI relatifs pour produire un URI absolu. En règle générale, BaseUri correspond à l’attribut href de l’élément <base> du document (emplacement du contenu de <head>). |
| NavigateTo | Permet d’accéder à l’URI spécifié. Si forceLoad a la valeur false :
forceLoad a la valeur true :
Pour plus d’informations, consultez la section Navigation améliorée et gestion des formulaires. Si |
| LocationChanged | Événement qui se déclenche en cas de changement de l’emplacement de navigation. Pour plus d’informations, consultez la section Changements d’emplacement. |
| NotFound | Appelé pour gérer les scénarios où une ressource demandée n’est pas trouvée. Pour plus d’informations, consultez la section Réponses introuvables . |
| ToAbsoluteUri | Convertit un URI relatif en URI absolu. |
| ToBaseRelativePath | En fonction de l’URI de base de l’application, convertit un URI absolu en URI par rapport au préfixe de l’URI de base. Pour obtenir un exemple, consultez la section Produire un URI par rapport au préfixe de l’URI de base. |
RegisterLocationChangingHandler |
Inscrit un gestionnaire pour traiter les événements de navigation entrants. Appeler NavigateTo déclenche toujours le gestionnaire. |
| GetUriWithQueryParameter | Retourne un URI construit en mettant à jour NavigationManager.Uri via l’ajout, la mise à jour ou la suppression d’un seul paramètre. Pour plus d’informations, consultez la section Chaînes de requête. |
| Membre | Descriptif |
|---|---|
| Uri | Obtient l’URI absolu actuel. |
| BaseUri | Obtient l’URI de base (avec une barre oblique finale) à ajouter aux chemins d’URI relatifs pour produire un URI absolu. En règle générale, BaseUri correspond à l’attribut href de l’élément <base> du document (emplacement du contenu de <head>). |
| NavigateTo | Permet d’accéder à l’URI spécifié. Si forceLoad a la valeur false :
forceLoad a la valeur true :
Pour plus d’informations, consultez la section Navigation améliorée et gestion des formulaires. Si |
| LocationChanged | Événement qui se déclenche en cas de changement de l’emplacement de navigation. Pour plus d’informations, consultez la section Changements d’emplacement. |
| ToAbsoluteUri | Convertit un URI relatif en URI absolu. |
| ToBaseRelativePath | En fonction de l’URI de base de l’application, convertit un URI absolu en URI par rapport au préfixe de l’URI de base. Pour obtenir un exemple, consultez la section Produire un URI par rapport au préfixe de l’URI de base. |
RegisterLocationChangingHandler |
Inscrit un gestionnaire pour traiter les événements de navigation entrants. Appeler NavigateTo déclenche toujours le gestionnaire. |
| GetUriWithQueryParameter | Retourne un URI construit en mettant à jour NavigationManager.Uri via l’ajout, la mise à jour ou la suppression d’un seul paramètre. Pour plus d’informations, consultez la section Chaînes de requête. |
| Membre | Descriptif |
|---|---|
| Uri | Obtient l’URI absolu actuel. |
| BaseUri | Obtient l’URI de base (avec une barre oblique finale) à ajouter aux chemins d’URI relatifs pour produire un URI absolu. En règle générale, BaseUri correspond à l’attribut href de l’élément <base> du document (emplacement du contenu de <head>). |
| NavigateTo | Permet d’accéder à l’URI spécifié. Si forceLoad a la valeur true :
replace a la valeur true, l’URI actuel dans l’historique du navigateur est remplacé au lieu d'ajouter un nouvel URI à la pile de l’historique. |
| LocationChanged | Événement qui se déclenche en cas de changement de l’emplacement de navigation. Pour plus d’informations, consultez la section Changements d’emplacement. |
| ToAbsoluteUri | Convertit un URI relatif en URI absolu. |
| ToBaseRelativePath | En fonction de l’URI de base de l’application, convertit un URI absolu en URI par rapport au préfixe de l’URI de base. Pour obtenir un exemple, consultez la section Produire un URI par rapport au préfixe de l’URI de base. |
RegisterLocationChangingHandler |
Inscrit un gestionnaire pour traiter les événements de navigation entrants. Appeler NavigateTo déclenche toujours le gestionnaire. |
| GetUriWithQueryParameter | Retourne un URI construit en mettant à jour NavigationManager.Uri via l’ajout, la mise à jour ou la suppression d’un seul paramètre. Pour plus d’informations, consultez la section Chaînes de requête. |
| Membre | Descriptif |
|---|---|
| Uri | Obtient l’URI absolu actuel. |
| BaseUri | Obtient l’URI de base (avec une barre oblique finale) à ajouter aux chemins d’URI relatifs pour produire un URI absolu. En règle générale, BaseUri correspond à l’attribut href de l’élément <base> du document (emplacement du contenu de <head>). |
| NavigateTo | Permet d’accéder à l’URI spécifié. Si forceLoad a la valeur true :
replace a la valeur true, l’URI actuel dans l’historique du navigateur est remplacé au lieu d'ajouter un nouvel URI à la pile de l’historique. |
| LocationChanged | Événement qui se déclenche en cas de changement de l’emplacement de navigation. Pour plus d’informations, consultez la section Changements d’emplacement. |
| ToAbsoluteUri | Convertit un URI relatif en URI absolu. |
| ToBaseRelativePath | En fonction de l’URI de base de l’application, convertit un URI absolu en URI par rapport au préfixe de l’URI de base. Pour obtenir un exemple, consultez la section Produire un URI par rapport au préfixe de l’URI de base. |
| GetUriWithQueryParameter | Retourne un URI construit en mettant à jour NavigationManager.Uri via l’ajout, la mise à jour ou la suppression d’un seul paramètre. Pour plus d’informations, consultez la section Chaînes de requête. |
| Membre | Descriptif |
|---|---|
| Uri | Obtient l’URI absolu actuel. |
| BaseUri | Obtient l’URI de base (avec une barre oblique finale) à ajouter aux chemins d’URI relatifs pour produire un URI absolu. En règle générale, BaseUri correspond à l’attribut href de l’élément <base> du document (emplacement du contenu de <head>). |
| NavigateTo | Permet d’accéder à l’URI spécifié. Si forceLoad a la valeur true :
|
| LocationChanged | Événement qui se déclenche en cas de changement de l’emplacement de navigation. |
| ToAbsoluteUri | Convertit un URI relatif en URI absolu. |
| ToBaseRelativePath | En fonction de l’URI de base de l’application, convertit un URI absolu en URI par rapport au préfixe de l’URI de base. Pour obtenir un exemple, consultez la section Produire un URI par rapport au préfixe de l’URI de base. |
Modifications d’emplacement
Pour l’événement LocationChanged, LocationChangedEventArgs fournit les informations suivantes sur les événements de navigation :
- Location : URL du nouvel emplacement.
-
IsNavigationIntercepted : Si la valeur est
true, cela signifie que Blazor a intercepté la navigation à partir du navigateur. Si la valeur estfalse, cela signifie que NavigationManager.NavigateTo a déclenché la navigation.
Le composant suivant :
- Accède au composant
Counter(Counter.razor) de l’application quand le bouton est sélectionné à l’aide de NavigateTo. - Gère l’événement de changement d’emplacement en s’abonnant à NavigationManager.LocationChanged.
La méthode
HandleLocationChangedest décrochée quandDisposeest appelé par le framework. Le décrochage de la méthode permet le nettoyage de la mémoire (garbage collection) du composant.L’implémentation du journaliseur entraîne la journalisation des informations suivantes quand le bouton est sélectionné :
BlazorSample.Pages.Navigate: Information: URL of new location: https://localhost:{PORT}/counter
Navigate.razor :
@page "/navigate"
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation
<h1>Navigate Example</h1>
<button class="btn btn-primary" @onclick="NavigateToCounterComponent">
Navigate to the Counter component
</button>
@code {
private void NavigateToCounterComponent() => Navigation.NavigateTo("counter");
protected override void OnInitialized() =>
Navigation.LocationChanged += HandleLocationChanged;
private void HandleLocationChanged(object? sender, LocationChangedEventArgs e) =>
Logger.LogInformation("URL of new location: {Location}", e.Location);
public void Dispose() => Navigation.LocationChanged -= HandleLocationChanged;
}
Pour plus d’informations sur l’élimination des composants, consultez Razor élimination de composants.
Comportement de redirection du Gestionnaire de navigation pendant le rendu côté serveur statique (SSR statique)
Pour une redirection pendant le rendu côté serveur statique (SSR statique), NavigationManager s’appuie sur la levée d’un NavigationException élément capturé par l’infrastructure, qui convertit l’erreur en redirection. Code qui existe après l’appel à NavigateTo n’est pas appelé. Lorsque vous utilisez Visual Studio, le débogueur s’arrête sur l’exception, ce qui vous oblige à décocher la case à cocher Lorsque ce type d’exception est géré par l’utilisateur dans l’interface utilisateur de Visual Studio pour éviter l’arrêt du débogueur pour les redirections ultérieures.
Vous pouvez utiliser la <BlazorDisableThrowNavigationException> propriété MSBuild définie sur true dans le fichier projet de l’application pour choisir de ne plus lever de NavigationExceptionfichier . En outre, le code après l’appel à NavigateTo s’exécuter quand il n’aurait pas été exécuté avant. Ce comportement est activé par défaut dans le modèle de projet .NET 10 ou version ultérieure Blazor Web App :
<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>
Note
Dans .NET 10 ou version ultérieure, vous pouvez choisir de ne pas lever d’élément NavigationException en définissant la <BlazorDisableThrowNavigationException> propriété true MSBuild dans le fichier projet de l’application. Pour tirer parti de la nouvelle propriété et du comportement MSBuild, mettez à niveau l’application vers .NET 10 ou version ultérieure.
Réponses introuvables
NavigationManager.NotFound gère les scénarios où une ressource demandée n’est pas trouvée pendant le rendu statique côté serveur (static SSR) ou le rendu interactif global :
SSR statique : l’appel NotFound définit le code d’état HTTP sur 404.
Rendu interactif : signale au Blazor routeur (
Routercomposant) le rendu du contenu introuvable.Rendu de diffusion en continu : si la navigation améliorée est active, le rendu de streaming affiche le contenu introuvable sans recharger la page. Lorsque la navigation améliorée est bloquée, l’infrastructure redirige vers le contenu introuvable avec une actualisation de page.
Note
La discussion suivante mentionne qu'un composant Introuvable Razor peut être attribué au paramètre Router du composant NotFoundPage. Le paramètre fonctionne de concert avec NotFound et est décrit plus en détail plus loin dans cette section.
Le rendu par streaming peut uniquement rendre des composants qui ont une route, comme une Router.NotFoundPage affectation (NotFoundPage="...") ou une affectation de page Middleware pour la réexécution des pages de code d'état ().
DefaultNotFound Le contenu 404 («Not found texte brut ») n’a pas d’itinéraire. Il ne peut donc pas être utilisé pendant le rendu en streaming.
Note
Le fragment de rendu introuvable (<NotFound>...</NotFound>) n’est pas pris en charge dans .NET 10 ou version ultérieure.
NotFound le rendu de contenu utilise les éléments suivants, que la réponse ait démarré ou non (dans l’ordre) :
- Si NotFoundEventArgs.Path est défini, le contenu de la page affectée est affiché.
- Si Router.NotFoundPage est défini, affichez la page affectée.
- Page middleware de réexécution des pages de code de statut, si configurée.
- Aucune action si aucune des approches précédentes n’est adoptée.
Le middleware de réexécution des pages de code de statut avec UseStatusCodePagesWithReExecute est prioritaire pour les problèmes de routage d’adresse basés sur le navigateur, comme une URL incorrecte saisie dans la barre d’adresse du navigateur ou un clic sur un lien qui n’a pas de point de terminaison dans l’application.
Lorsqu’un composant est rendu statiquement (SSR statique) et NotFound appelé, le code d’état 404 est défini sur la réponse :
@page "/render-not-found-ssr"
@inject NavigationManager Navigation
@code {
protected override void OnInitialized()
{
Navigation.NotFound();
}
}
Pour fournir du contenu Introuvable pour le rendu interactif global, utilisez une page Introuvable (composant Razor).
Note
Le Blazor modèle de projet inclut une NotFound.razor page. Cette page s’affiche automatiquement chaque fois qu’elle NotFound est appelée, ce qui permet de gérer les itinéraires manquants avec une expérience utilisateur cohérente.
Pages/NotFound.razor :
@page "/not-found"
@layout MainLayout
<h3>Not Found</h3>
<p>Sorry, the content you are looking for does not exist.</p>
Le NotFound composant est affecté à Router.NotFoundPage, qui prend en charge le routage utilisable par l’intergiciel de réexécution des pages de code d’état, y compris ceux qui ne sont pas des intergiciels Blazor.
Dans l’exemple suivant, le composant précédent NotFound est présent dans le dossier de Pages l’application et transmis au NotFoundPage paramètre :
<Router AppAssembly="@typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
<Found Context="routeData">
<RouteView RouteData="@routeData" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
</Router>
Lorsqu’un composant est rendu avec un mode de rendu interactif global, l’appel signale NotFound au Blazor routeur le rendu du NotFound composant :
@page "/render-not-found-interactive"
@inject NavigationManager Navigation
@if (RendererInfo.IsInteractive)
{
<button @onclick="TriggerNotFound">Trigger Not Found</button>
}
@code {
private void TriggerNotFound()
{
Navigation.NotFound();
}
}
Utilisez l’événement NavigationManager.OnNotFound pour les notifications lorsque NotFound est activé. L’événement est déclenché uniquement lorsqu’il NotFound est appelé, et non pour une réponse 404. Par exemple, régler HttpContextAccessor.HttpContext.Response.StatusCode sur 404 ne déclenche pas NotFound/OnNotFound.
Les applications qui implémentent un routeur personnalisé peuvent également utiliser NotFound. Le routeur personnalisé peut afficher le contenu introuvable à partir de deux sources, en fonction de l’état de la réponse :
Quel que soit l’état de réponse, le chemin de réexécution de la page peut être utilisé en le transmettant à UseStatusCodePagesWithReExecute:
app.UseStatusCodePagesWithReExecute( "/not-found", createScopeForStatusCodePages: true);Une fois la réponse initiée, NotFoundEventArgs.Path peut être utilisé en s'abonnant à
OnNotFoundEventdans le routeur :@code { [CascadingParameter] public HttpContext? HttpContext { get; set; } private void OnNotFoundEvent(object sender, NotFoundEventArgs e) { // Only execute the logic if HTTP response has started, // because setting NotFoundEventArgs.Path blocks re-execution if (HttpContext?.Response.HasStarted == false) { return; } var type = typeof(CustomNotFoundPage); var routeAttributes = type.GetCustomAttributes<RouteAttribute>(inherit: true); if (routeAttributes.Length == 0) { throw new InvalidOperationException($"The type {type.FullName} " + $"doesn't have a {nameof(RouteAttribute)} applied."); } var routeAttribute = (RouteAttribute)routeAttributes[0]; if (routeAttribute.Template != null) { e.Path = routeAttribute.Template; } } }
Dans l’exemple suivant pour les composants qui adoptent le rendu interactif côté serveur (SSR interactif), le contenu personnalisé est rendu en fonction de l’endroit où OnNotFound il est appelé. Si l’événement est déclenché par le composant suivant Movie lorsqu’un film est introuvable sur l’initialisation du composant, un message personnalisé indique que le film demandé n’est pas trouvé. Si l’événement est déclenché par le User composant dans l’exemple suivant, un message différent indique que l’utilisateur n’est pas trouvé.
Le service suivant NotFoundContext gère le contexte et le message pour lequel le contenu n’est pas trouvé par les composants.
NotFoundContext.cs :
public class NotFoundContext
{
public string? Heading { get; private set; }
public string? Message { get; private set; }
public void UpdateContext(string heading, string message)
{
Heading = heading;
Message = message;
}
}
Le service est inscrit dans le fichier côté Program serveur :
builder.Services.AddScoped<NotFoundContext>();
La page NotFound injecte NotFoundContext et affiche le titre ainsi que le message.
Pages/NotFound.razor :
@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext
<h3>@NotFoundContext.Heading</h3>
<div>
<p>@NotFoundContext.Message</p>
</div>
Le Routes composant (Routes.razor) définit le NotFound composant comme page Introuvable via le NotFoundPage paramètre :
<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
...
</Router>
Dans les exemples de composants suivants :
- Le
NotFoundContextservice est injecté, ainsi que le NavigationManager. - Dans OnInitializedAsync,
HandleNotFoundest un gestionnaire d’événements affecté à l’événement OnNotFound .HandleNotFoundappelsNotFoundContext.UpdateContextpour définir un titre et un message pour le contenu introuvable dans leNotFoundcomposant. - Les composants utilisent normalement un ID à partir d’un paramètre de routage pour obtenir un film ou un utilisateur à partir d’un référentiel de données, comme une base de données. Dans les exemples suivants, aucune entité n’est retournée (
null) pour simuler ce qui se passe lorsqu’une entité n’est pas trouvée. - Lorsqu’aucune entité n’est retournée à OnInitializedAsync, NotFound est appelée, ce qui déclenche à son tour l’événement OnNotFound et le gestionnaire d’événements
HandleNotFound. Le contenu introuvable s’affiche par le routeur. - La méthode
HandleNotFoundest désactivée lors de la suppression du composant dans IDisposable.Dispose.
Composant Movie (Movie.razor) :
@page "/movie/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext
<div>
No matter what ID is used, no matching movie is returned
from the call to GetMovie().
</div>
@code {
[Parameter]
public int Id { get; set; }
protected override async Task OnInitializedAsync()
{
NavigationManager.OnNotFound += HandleNotFound;
var movie = await GetMovie(Id);
if (movie == null)
{
NavigationManager.NotFound();
}
}
private void HandleNotFound(object? sender, NotFoundEventArgs e)
{
NotFoundContext.UpdateContext("Movie Not Found",
"Sorry! The requested movie wasn't found.");
}
private async Task<MovieItem[]?> GetMovie(int id)
{
// Simulate no movie with matching id found
return await Task.FromResult<MovieItem[]?>(null);
}
void IDisposable.Dispose()
{
NavigationManager.OnNotFound -= HandleNotFound;
}
public class MovieItem
{
public int Id { get; set; }
public string? Title { get; set; }
}
}
Composant User (User.razor) :
@page "/user/{Id:int}"
@implements IDisposable
@inject NavigationManager NavigationManager
@inject NotFoundContext NotFoundContext
<div>
No matter what ID is used, no matching user is returned
from the call to GetUser().
</div>
@code {
[Parameter]
public int Id { get; set; }
protected override async Task OnInitializedAsync()
{
NavigationManager.OnNotFound += HandleNotFound;
var user = await GetUser(Id);
if (user == null)
{
NavigationManager.NotFound();
}
}
private void HandleNotFound(object? sender, NotFoundEventArgs e)
{
NotFoundContext.UpdateContext("User Not Found",
"Sorry! The requested user wasn't found.");
}
private async Task<UserItem[]?> GetUser(int id)
{
// Simulate no user with matching id found
return await Task.FromResult<UserItem[]?>(null);
}
void IDisposable.Dispose()
{
NavigationManager.OnNotFound -= HandleNotFound;
}
public class UserItem
{
public int Id { get; set; }
public string? Name { get; set; }
}
}
Pour accéder aux composants précédemment mentionnés dans une démonstration locale avec une application de test, créez des entrées dans le composant NavMenu (NavMenu.razor) pour atteindre les composants Movie et User. Les ID d’entité, passés en tant que paramètres de routage, dans l’exemple suivant sont des valeurs fictives qui n’ont aucun effet, car elles ne sont pas réellement utilisées par les composants, qui simulent ne pas trouver un film ou un utilisateur.
Dans NavMenu.razor :
<div class="nav-item px-3">
<NavLink class="nav-link" href="movie/1">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Movie
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="user/2">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> User
</NavLink>
</div>
Navigation améliorée et gestion des formulaires
Cette section s’applique à Blazor Web App.
Les Blazor Web Apps sont capables de deux types de routage pour la navigation de page et les requêtes de gestion des formulaires :
- Navigation normale (navigation entre documents) : un rechargement de page complète est déclenché pour l’URL de la requête.
- Navigation améliorée (navigation dans le même document) : Blazor intercepte la requête et effectue une requête
fetchà la place. Blazor corrige ensuite le contenu de la réponse dans le DOM de la page. La navigation Blazor améliorée et la gestion des formulaires évitent d’avoir besoin d’un rechargement de page complète et conservent davantage l’état de la page. Les pages se chargent donc plus rapidement, généralement sans perdre la position de défilement de l’utilisateur sur la page.
La navigation améliorée est disponible lorsque :
- Le script de l’Blazor Web App (
blazor.web.js) est utilisé, et non le script Blazor Server (blazor.server.js) ou le script Blazor WebAssembly (blazor.webassembly.js). - La fonctionnalité n’est pas explicitement désactivée.
- L’URL de destination se trouve dans l’espace d’URI de base interne (chemin d’accès de base de l’application) et le lien vers la page n’a pas l’attribut
data-enhance-navdéfini surfalse.
Si le routage côté serveur et la navigation améliorée sont activés, les gestionnaires de modification d’emplacement sont appelés seulement pour la navigation par programmation lancée depuis un runtime interactif. Dans les prochaines versions, d’autres types de navigation, tels que le suivi d'un lien, pourront également faire appel à des gestionnaires de modification de l'emplacement.
Quand une navigation améliorée se produit, ce sont généralement des gestionnaires d’événements LocationChanged inscrits auprès du serveur interactif et des runtimes WebAssembly qui sont appelés. Il existe des cas où les gestionnaires de modification d’emplacement peuvent ne pas intercepter une navigation améliorée. Par exemple, l’utilisateur peut basculer vers une autre page avant qu’un runtime interactif ne devienne disponible. Par conséquent, il est important que la logique de l’application ne s’appuie pas sur l’appel d’un gestionnaire de modification d’emplacement, car il n’y a pas de garantie qu’un gestionnaire soit en cours d’exécution.
Lors de l'appel NavigateTo :
- Si
forceLoadestfalse, qui est la valeur par défaut :- Et une navigation améliorée est disponible à l'URL actuelle, et la navigation améliorée de Blazor est activée.
- Sinon, Blazor effectue un rechargement de page complète pour l’URL demandée.
- Si
forceLoadesttrue: Blazor effectue un rechargement de page complète pour l’URL demandée, que la navigation améliorée soit disponible ou non.
Vous pouvez actualiser la page active en appelant NavigationManager.Refresh(bool forceLoad = false), qui effectue toujours une navigation améliorée, si disponible. Si la navigation améliorée n’est pas disponible, Blazor effectue un rechargement de page complète.
Navigation.Refresh();
Passez true au paramètre forceLoad pour vous assurer qu’un rechargement de page complète est toujours effectué, même si la navigation améliorée est disponible :
Navigation.Refresh(true);
La navigation améliorée est activée par défaut, mais elle peut être contrôlée hiérarchiquement et par lien à l’aide de l’attribut HTML data-enhance-nav.
Les exemples suivants désactivent la navigation améliorée :
<a href="redirect" data-enhance-nav="false">
GET without enhanced navigation
</a>
<ul data-enhance-nav="false">
<li>
<a href="redirect">GET without enhanced navigation</a>
</li>
<li>
<a href="redirect-2">GET without enhanced navigation</a>
</li>
</ul>
Si la destination est un point de terminaison non-Blazor, la navigation améliorée ne s'applique pas et le JavaScript côté client tente à nouveau de charger une page complète. Cela garantit l’absence de confusion dans l’infrastructure concernant les pages externes qui ne doivent pas être patchées dans une page existante.
Pour activer la gestion améliorée des formulaires, ajoutez le paramètre Enhance aux formulaires EditForm ou l’attribut data-enhance aux formulaires HTML (<form>) :
<EditForm ... Enhance ...>
...
</EditForm>
<form ... data-enhance ...>
...
</form>
La gestion améliorée des formulaires n’est pas hiérarchique et ne passe pas aux formulaires enfants :
Non pris en charge : vous ne pouvez pas définir la navigation améliorée sur l’élément ancêtre d’un formulaire pour activer la navigation améliorée pour le formulaire.
<div ... data-enhance ...>
<form ...>
<!-- NOT enhanced -->
</form>
</div>
Les formulaires améliorés ne fonctionnent qu'avec des points de terminaison Blazor. L'envoi d'un formulaire amélioré à un point de terminaison non-Blazor entraîne une erreur.
Pour désactiver la navigation améliorée :
- Pour un EditForm, supprimez le paramètre Enhance de l’élément de formulaire (ou définissez-le sur
false:Enhance="false"). - Pour un code HTML
<form>, supprimez l’attributdata-enhancede l’élément de formulaire (ou définissez-le surfalse:data-enhance="false").
La navigation améliorée et la gestion des formulaires de Blazor peuvent annuler les modifications dynamiques apportées au DOM si le contenu mis à jour ne fait pas partie du rendu du serveur. Pour conserver le contenu d’un élément, utilisez l’attribut data-permanent.
Dans l’exemple suivant, le contenu de l’élément <div> est mis à jour dynamiquement par un script lorsque la page se charge :
<div data-permanent>
...
</div>
Une fois que Blazor a démarré sur le client, vous pouvez utiliser l’évènement enhancedload pour écouter les mises à jour de page améliorées. Cela permet de ré-appliquer les modifications apportées au DOM qui ont peut-être été annulées par une mise à jour de page améliorée.
Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));
Pour désactiver globalement la navigation améliorée et la gestion des formulaires, consultez Démarrage de ASP.NET Core Blazor.
La navigation améliorée avec le rendu statique côté serveur (SSR statique) nécessite une attention particulière lors du chargement de JavaScript. Pour plus d’informations, consultez JavaScript Blazor ASP.NET Core avec rendu côté serveur statique (SSR statique).
Produire un URI par rapport au préfixe de l’URI de base
En fonction de l’URI de base de l’application, ToBaseRelativePath convertit un URI absolu en URI par rapport au préfixe de l’URI de base.
Prenons l'exemple suivant :
try
{
baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
...
}
Si l’URI de base de l’application est https://localhost:8000, les résultats suivants sont obtenus :
- Passer
https://localhost:8000/segmentdansinputURIentraîne unbaseRelativePathdesegment. - Passer
https://localhost:8000/segment1/segment2dansinputURIentraîne unbaseRelativePathdesegment1/segment2.
Si l’URI de base de l’application ne correspond pas à l’URI de base de inputURI, une ArgumentException est levée.
Passer https://localhost:8001/segment dans inputURI entraîne l’exception suivante :
System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'
État de l’historique de navigation
Le NavigationManager utilise l’API d’historique du navigateur pour conserver l’état de l’historique de navigation associé à chaque changement d’emplacement effectué par l’application. La conservation de l’état de l’historique est particulièrement utile dans les scénarios de redirection externe, par exemple durant l’authentification des utilisateurs auprès de fournisseurs d’identité externes. Pour plus d’informations, consultez la section Options de navigation.
Options de navigation
Passez NavigationOptions à NavigateTo pour contrôler les comportements suivants :
-
ForceLoad : Contourne le routage côté client, et force le navigateur à charger la nouvelle page à partir du serveur, que l’URI soit géré ou non par le routeur côté client. La valeur par défaut est
false. -
ReplaceHistoryEntry : Remplacer l'entrée actuelle dans la pile de l'historique. Si la valeur est
false, ajoute la nouvelle entrée à la pile de l’historique. La valeur par défaut estfalse. - HistoryEntryState : Obtient ou définit l’état à ajouter à l’entrée d’historique.
Navigation.NavigateTo("/path", new NavigationOptions
{
HistoryEntryState = "Navigation state"
});
Pour plus d’informations sur l’obtention de l’état associé à l’entrée d’historique cible durant la gestion des changements d’emplacement, consultez la section Gérer/empêcher les changements d’emplacement.
Chaînes de requête
Utilisez l’attribut [SupplyParameterFromQuery] pour spécifier qu’un paramètre de composant provient de la chaîne de requête.
Utilisez l’attribut [SupplyParameterFromQuery] avec l’attribut [Parameter] pour spécifier qu’un paramètre de composant d’un composant routable provient de la chaîne de requête.
Note
Les paramètres de composant ne peuvent recevoir des valeurs de paramètre de requête que dans des composants routables dotés d'une directive @page.
Seuls les composants routables reçoivent directement les paramètres de requête afin d’éviter de subvertir le flux d’informations descendant et de rendre l’ordre de traitement des paramètres clair, à la fois par l’infrastructure et par l’application. Cette conception évite les bogues subtils dans le code d’application écrit en supposant un ordre de traitement spécifique des paramètres. Vous êtes libre de définir des paramètres en cascade personnalisés ou d’affecter directement des paramètres de composant standard pour passer les valeurs des paramètres de requête aux composants non routables.
Les paramètres de composant fournis à partir de la chaîne de requête prennent en charge les types suivants :
-
bool,DateTime,decimal,double,float,Guid,int,long,string. - Variantes Nullable des types précédents.
- Tableaux des types précédents, qu’il s’agisse ou non de types Nullable.
La mise en forme appropriée, indépendante de la culture, est appliquée pour le type donné (CultureInfo.InvariantCulture).
Spécifiez la propriété [SupplyParameterFromQuery] de l’attribut Name pour utiliser un nom de paramètre de requête différent du nom de paramètre de composant. Dans l’exemple suivant, le nom C# du paramètre de composant est {COMPONENT PARAMETER NAME}. Un autre nom de paramètre de requête est spécifié pour l’espace réservé {QUERY PARAMETER NAME} :
Contrairement aux propriétés des paramètres de composant ([Parameter]), les propriétés [SupplyParameterFromQuery] peuvent être marquées private en plus de public.
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }
Tout comme les propriétés de paramètre de composant ([Parameter]), les propriétés [SupplyParameterFromQuery] sont toujours des propriétés public dans .NET 6/7. Dans .NET 8 ou version ultérieure, les propriétés [SupplyParameterFromQuery] peuvent être marquées public ou private.
[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
Dans l’exemple suivant avec l’URL /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman :
- La propriété
Filterest résolue enscifi stars. - La propriété
Pageest résolue en3. - Le tableau
Starsest rempli à partir des paramètres de requête nommésstar(Name = "star"), et se résout enLeVar BurtonetGary Oldman.
Note
Les paramètres de chaîne de requête dans le composant de page routable suivant fonctionnent également dans un composant non routable sans directive @page (par exemple, Search.razor pour un composant Search partagé utilisé dans d’autres composants).
Search.razor :
@page "/search"
<h1>Search Example</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
@if (Stars is not null)
{
<p>Stars:</p>
<ul>
@foreach (var name in Stars)
{
<li>@name</li>
}
</ul>
}
@code {
[SupplyParameterFromQuery]
private string? Filter { get; set; }
[SupplyParameterFromQuery]
private int? Page { get; set; }
[SupplyParameterFromQuery(Name = "star")]
private string[]? Stars { get; set; }
}
Search.razor :
@page "/search"
<h1>Search Example</h1>
<p>Filter: @Filter</p>
<p>Page: @Page</p>
@if (Stars is not null)
{
<p>Stars:</p>
<ul>
@foreach (var name in Stars)
{
<li>@name</li>
}
</ul>
}
@code {
[Parameter]
[SupplyParameterFromQuery]
public string? Filter { get; set; }
[Parameter]
[SupplyParameterFromQuery]
public int? Page { get; set; }
[Parameter]
[SupplyParameterFromQuery(Name = "star")]
public string[]? Stars { get; set; }
}
Utilisez GetUriWithQueryParameter pour ajouter, changer ou supprimer un ou plusieurs paramètres de requête de l’URL actuelle :
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})
Pour l’exemple précédent :
- L’espace réservé
{NAME}spécifie le nom du paramètre de requête. L’espace réservé{VALUE}spécifie la valeur en tant que type pris en charge. Les types pris en charge sont listés plus loin dans cette section. - Une chaîne équivalente à l’URL actuelle est retournée avec un seul paramètre :
- Ajouté si le nom du paramètre de requête n’existe pas dans l’URL actuelle.
- Mise à jour avec la valeur fournie si le paramètre de requête existe dans l'URL actuelle.
- Supprimé si le type de la valeur fournie est Nullable et que la valeur est
null.
- La mise en forme appropriée, indépendante de la culture, est appliquée pour le type donné (CultureInfo.InvariantCulture).
- Le nom et la valeur du paramètre de requête sont codés dans l’URL.
- Toutes les valeurs portant le nom du paramètre de requête correspondant sont remplacées, s’il existe plusieurs instances du type.
Appelez GetUriWithQueryParameters pour créer un URI construit à partir de Uri avec plusieurs paramètres ajoutés, mis à jour ou supprimés. Pour chaque valeur, le framework utilise value?.GetType() afin de déterminer le type de runtime de chaque paramètre de requête, et sélectionne la mise en forme appropriée, indépendamment de la culture. Le framework génère une erreur pour les types non pris en charge.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters({PARAMETERS})
L’espace réservé {PARAMETERS} est un IReadOnlyDictionary<string, object>.
Passez une chaîne d’URI à GetUriWithQueryParameters pour générer un nouvel URI à partir d’un URI fourni avec plusieurs paramètres ajoutés, mis à jour ou supprimés. Pour chaque valeur, le framework utilise value?.GetType() afin de déterminer le type de runtime de chaque paramètre de requête, et sélectionne la mise en forme appropriée, indépendamment de la culture. Le framework génère une erreur pour les types non pris en charge. Les types pris en charge sont listés plus loin dans cette section.
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
- L’espace réservé
{URI}est l’URI avec ou sans chaîne de requête. - L’espace réservé
{PARAMETERS}est unIReadOnlyDictionary<string, object>.
Les types pris en charge sont identiques aux types pris en charge pour les contraintes de route :
boolDateOnlyDateTimedecimaldoublefloatGuidintlongstringTimeOnly
Les types pris en charge comprennent les suivants :
- Variantes Nullable des types précédents.
- Tableaux des types précédents, qu’il s’agisse ou non de types Nullable.
Avertissement
Avec la compression, qui est activée par défaut, évitez de créer des composants côté serveur interactifs (authentifiés/autorisés) sécurisés qui affichent des données en provenance de sources non approuvées. Les sources non approuvées incluent les paramètres de routage, les chaînes de requête, les données issues de l’interopérabilité JS, et toute autre source de données qu’un utilisateur tiers peut contrôler (bases de données, services externes). Pour plus d’informations, consultez Conseils pour ASP.NET Core BlazorSignalR et Conseils d’atténuation des menaces pour le rendu interactif côté serveur de ASP.NET Core Blazor.
Remplacer une valeur de paramètre de requête quand le paramètre existe
Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
| URL actuelle | URL générée |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&age=42 |
scheme://host/?full%20name=Morena%20Baccarin&age=42 |
scheme://host/?fUlL%20nAmE=David%20Krumholtz&AgE=42 |
scheme://host/?full%20name=Morena%20Baccarin&AgE=42 |
scheme://host/?full%20name=Jewel%20Staite&age=42&full%20name=Summer%20Glau |
scheme://host/?full%20name=Morena%20Baccarin&age=42&full%20name=Morena%20Baccarin |
scheme://host/?full%20name=&age=42 |
scheme://host/?full%20name=Morena%20Baccarin&age=42 |
scheme://host/?full%20name= |
scheme://host/?full%20name=Morena%20Baccarin |
Ajouter un paramètre de requête et une valeur quand le paramètre n’existe pas
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
| URL actuelle | URL générée |
|---|---|
scheme://host/?age=42 |
scheme://host/?age=42&name=Morena%20Baccarin |
scheme://host/ |
scheme://host/?name=Morena%20Baccarin |
scheme://host/? |
scheme://host/?name=Morena%20Baccarin |
Supprimer un paramètre de requête quand la valeur du paramètre est null
Navigation.GetUriWithQueryParameter("full name", (string)null)
| URL actuelle | URL générée |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&age=42 |
scheme://host/?age=42 |
scheme://host/?full%20name=Sally%20Smith&age=42&full%20name=Summer%20Glau |
scheme://host/?age=42 |
scheme://host/?full%20name=Sally%20Smith&age=42&FuLl%20NaMe=Summer%20Glau |
scheme://host/?age=42 |
scheme://host/?full%20name=&age=42 |
scheme://host/?age=42 |
scheme://host/?full%20name= |
scheme://host/ |
Ajouter, mettre à jour et supprimer des paramètres de requête
Dans l’exemple suivant :
-
nameest supprimé, le cas échéant. -
ageest ajouté avec la valeur25(int), s’il n’est pas présent. S’il est présent,ageest mis à jour avec la valeur25. -
eye colorest ajouté ou mis à jour avec la valeurgreen.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["name"] = null,
["age"] = (int?)25,
["eye color"] = "green"
})
| URL actuelle | URL générée |
|---|---|
scheme://host/?name=David%20Krumholtz&age=42 |
scheme://host/?age=25&eye%20color=green |
scheme://host/?NaMe=David%20Krumholtz&AgE=42 |
scheme://host/?age=25&eye%20color=green |
scheme://host/?name=David%20Krumholtz&age=42&keepme=true |
scheme://host/?age=25&keepme=true&eye%20color=green |
scheme://host/?age=42&eye%20color=87 |
scheme://host/?age=25&eye%20color=green |
scheme://host/? |
scheme://host/?age=25&eye%20color=green |
scheme://host/ |
scheme://host/?age=25&eye%20color=green |
Prise en charge des valeurs énumérables
Dans l’exemple suivant :
-
full nameest ajouté ou mis à jour avecMorena Baccarin, une valeur unique. - Les paramètres de
pingsont ajoutés ou remplacés par35,16,87et240.
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["full name"] = "Morena Baccarin",
["ping"] = new int?[] { 35, 16, null, 87, 240 }
})
| URL actuelle | URL générée |
|---|---|
scheme://host/?full%20name=David%20Krumholtz&ping=8&ping=300 |
scheme://host/?full%20name=Morena%20Baccarin&ping=35&ping=16&ping=87&ping=240 |
scheme://host/?ping=8&full%20name=David%20Krumholtz&ping=300 |
scheme://host/?ping=35&full%20name=Morena%20Baccarin&ping=16&ping=87&ping=240 |
scheme://host/?ping=8&ping=300&ping=50&ping=68&ping=42 |
scheme://host/?ping=35&ping=16&ping=87&ping=240&full%20name=Morena%20Baccarin |
Naviguer avec une chaîne de requête ajoutée ou modifiée
Pour naviguer avec une chaîne de requête ajoutée ou modifiée, passez une URL générée à NavigateTo.
L’exemple suivant appelle :
-
GetUriWithQueryParameter pour ajouter ou remplacer le paramètre de requête
nameà l’aide de la valeurMorena Baccarin. - Appelle NavigateTo pour déclencher la navigation vers la nouvelle URL.
Navigation.NavigateTo(
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));
La chaîne de requête d’une requête est obtenue à partir de la propriété NavigationManager.Uri :
@inject NavigationManager Navigation
...
var query = new Uri(Navigation.Uri).Query;
Pour analyser les paramètres d’une chaîne de requête, il existe une approche qui consiste à utiliser URLSearchParams avec l’interopérabilité JavaScript (JS) :
export createQueryString = (string queryString) => new URLSearchParams(queryString);
Pour plus d’informations sur l’isolation JavaScript avec des modules JavaScript, consultez Appeler des fonctions JavaScript à partir de méthodes .NET dans ASP.NET Core Blazor.
Accéder aux éléments nommés
Accédez à un élément nommé en utilisant les approches suivantes avec une référence hachée (#) à l’élément. Les itinéraires vers des éléments au sein du composant et vers des éléments dans des composants externes utilisent des chemins relatifs à la racine. Une barre oblique de début (/) est facultative.
Les exemples de chacune des approches suivantes illustrent la navigation vers un élément avec un id de targetElement dans le composant Counter :
Élément d’ancrage (
<a>) avec unhref:<a href="/counter#targetElement">Composant NavLink avec un
href:<NavLink href="/counter#targetElement">NavigationManager.NavigateTo en transmettant l'URL relative :
Navigation.NavigateTo("/counter#targetElement");
L’exemple suivant illustre la navigation vers les en-têtes H2 nommés au sein d’un composant et vers des composants externes.
Dans les composants Home (Home.razor) etCounter (Counter.razor), placez le balisage suivant en bas du balisage de composant existant pour servir de cibles de navigation. Le <div> crée un espace vertical artificiel pour illustrer le comportement de défilement du navigateur :
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
Ajoutez le composant FragmentRouting suivant à l’application.
FragmentRouting.razor :
@page "/fragment-routing"
@inject NavigationManager Navigation
<PageTitle>Fragment routing</PageTitle>
<h1>Fragment routing to named elements</h1>
<ul>
<li>
<a href="/fragment-routing#targetElement">
Anchor in this component
</a>
</li>
<li>
<a href="/#targetElement">
Anchor to the <code>Home</code> component
</a>
</li>
<li>
<a href="/counter#targetElement">
Anchor to the <code>Counter</code> component
</a>
</li>
<li>
<NavLink href="/fragment-routing#targetElement">
Use a `NavLink` component in this component
</NavLink>
</li>
<li>
<button @onclick="NavigateToElement">
Navigate with <code>NavigationManager</code> to the
<code>Counter</code> component
</button>
</li>
</ul>
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
@code {
private void NavigateToElement()
{
Navigation.NavigateTo("/counter#targetElement");
}
}
Gérer/empêcher les changements d’emplacement
RegisterLocationChangingHandler inscrit un gestionnaire pour traiter les événements de navigation entrants. Le contexte du gestionnaire fourni par LocationChangingContext comprend les propriétés suivantes :
- TargetLocation : obtient l’emplacement cible.
- HistoryEntryState : Obtient l'état associé à l'entrée de l'historique cible.
- IsNavigationIntercepted : détermine si la navigation a été interceptée à partir d’un lien.
- CancellationToken : obtient un CancellationToken pour déterminer si la navigation a été annulée, par exemple pour savoir si l’utilisateur a déclenché une autre navigation.
- PreventNavigation : Appelé pour empêcher la poursuite de la navigation.
Un composant peut inscrire plusieurs gestionnaires de changement d’emplacement dans la méthode de cycle de vie OnAfterRender{Async}. La navigation appelle tous les gestionnaires de changement d’emplacement inscrits dans l’ensemble de l’application (pour plusieurs composants), et la navigation interne les exécute tous en parallèle. Des gestionnaires NavigateTo supplémentaires sont appelés :
- Au moment de la sélection des liens internes, qui sont des liens pointant vers des URL sous le chemin de base de l’application.
- Durant la navigation à l’aide des boutons Précédent et Suivant d’un navigateur.
Les gestionnaires sont exécutés uniquement pour la navigation interne au sein de l’application. Si l’utilisateur sélectionne un lien qui lui permet de naviguer vers un autre site, ou s’il change manuellement la barre d’adresse pour accéder à un autre site, les gestionnaires de changement d’emplacement ne sont pas exécutés.
Implémentez IDisposable, et supprimez les gestionnaires inscrits pour les désinscrire. Pour plus d’informations, consultez Suppression de composants ASP.NET Core Razor.
Important
N’essayez pas d’exécuter des tâches de nettoyage DOM via l’interopérabilité JavaScript (JS) quand vous gérez les changements d’emplacement. Utiliser le motif MutationObserver dans JS sur le client. Pour plus d’informations, consultez Interopérabilité JavaScript d'ASP.NET Core Blazor (interop JS).
Dans l’exemple suivant, un gestionnaire de changement d’emplacement est inscrit pour les événements de navigation.
NavHandler.razor :
@page "/nav-handler"
@implements IDisposable
@inject NavigationManager Navigation
<p>
<button @onclick="@(() => Navigation.NavigateTo("/"))">
Home (Allowed)
</button>
<button @onclick="@(() => Navigation.NavigateTo("/counter"))">
Counter (Prevented)
</button>
</p>
@code {
private IDisposable? registration;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
registration =
Navigation.RegisterLocationChangingHandler(OnLocationChanging);
}
}
private ValueTask OnLocationChanging(LocationChangingContext context)
{
if (context.TargetLocation == "/counter")
{
context.PreventNavigation();
}
return ValueTask.CompletedTask;
}
public void Dispose() => registration?.Dispose();
}
Dans la mesure où la navigation interne peut être annulée de manière asynchrone, plusieurs appels à des gestionnaires inscrits peuvent se chevaucher. Par exemple, plusieurs appels de gestionnaires peuvent se produire quand l’utilisateur sélectionne rapidement le bouton Précédent sur une page, ou qu’il sélectionne plusieurs liens avant l’exécution d’une navigation. Voici un récapitulatif de la logique de navigation asynchrone :
- Si des gestionnaires de changement d’emplacement sont inscrits, l’ensemble de la navigation est initialement rétabli, puis relu, si la navigation n’est pas annulée.
- Si des demandes de navigation se chevauchent, la dernière demande annule toujours les demandes antérieures, ce qui signifie plusieurs choses :
- L’application peut traiter plusieurs sélections des boutons Précédent et Suivant sous forme d’une seule sélection.
- Si l’utilisateur sélectionne plusieurs liens avant la fin de la navigation, le dernier lien sélectionné détermine la navigation.
Pour plus d’informations sur le passage de NavigationOptions à NavigateTo pour contrôler les entrées et l’état de la pile de l’historique de navigation, consultez la section Options de navigation.
Pour obtenir un exemple de code supplémentaire, consultez les informations relatives au NavigationManagerComponent dans BasicTestApp (source de référence relative à dotnet/aspnetcore).
Note
Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Le composant NavigationLock intercepte les événements de navigation tant qu’ils sont affichés, ce qui permet de « verrouiller » efficacement toute navigation donnée jusqu’à ce qu’il soit décidé de la poursuivre ou de l’annuler. Utilisez NavigationLock quand l’interception de la navigation peut être délimitée en fonction de la durée de vie d’un composant.
Paramètres de NavigationLock :
-
ConfirmExternalNavigation définit une boîte de dialogue de navigateur pour inviter l’utilisateur à confirmer ou à annuler la navigation externe. La valeur par défaut est
false. L’affichage de la boîte de dialogue de confirmation nécessite une interaction initiale de l’utilisateur avec la page avant de déclencher une navigation externe avec l’URL dans la barre d’adresse du navigateur. Pour plus d’informations sur l’exigence d’interaction, consultez Fenêtre : événementbeforeunload. - OnBeforeInternalNavigation définit un rappel pour les événements de navigation internes.
Dans le composant NavLock suivant :
- Toute tentative de suivi du lien vers le site web de Microsoft doit être confirmée par l’utilisateur pour que la navigation vers
https://www.microsoft.comaboutisse. -
PreventNavigation est appelé pour empêcher la navigation si l’utilisateur refuse de confirmer celle-ci via un appel d’interopérabilité JavaScript (JS), qui génère la boîte de dialogue JS
confirm.
NavLock.razor :
@page "/nav-lock"
@inject IJSRuntime JSRuntime
@inject NavigationManager Navigation
<NavigationLock ConfirmExternalNavigation="true"
OnBeforeInternalNavigation="OnBeforeInternalNavigation" />
<p>
<button @onclick="Navigate">Navigate</button>
</p>
<p>
<a href="https://www.microsoft.com">Microsoft homepage</a>
</p>
@code {
private void Navigate()
{
Navigation.NavigateTo("/");
}
private async Task OnBeforeInternalNavigation(LocationChangingContext context)
{
var isConfirmed = await JSRuntime.InvokeAsync<bool>("confirm",
"Are you sure you want to navigate to the root page?");
if (!isConfirmed)
{
context.PreventNavigation();
}
}
}
Pour obtenir un exemple de code supplémentaire, consultez les informations relatives au composant ConfigurableNavigationLock dans BasicTestApp (source de référence relative à dotnet/aspnetcore).
Composants générés NavLink dynamiquement via la réflexion
Les entrées de composant NavLink peuvent être créées dynamiquement à partir des composants de l’application via la réflexion. L’exemple suivant illustre l’approche générale pour une personnalisation plus poussée.
Pour la démonstration suivante, une convention d’affectation de noms standard cohérente est utilisée pour les composants de l’application :
- Les noms de fichiers des composants routables utilisent la casse Pascal†, par exemple
Pages/ProductDetail.razor. - Les chemins d'accès aux fichiers des composants routables correspondent à leurs URL en majuscules, avec des traits d'union entre les mots dans le modèle de route d'un composant. Par exemple, un composant
ProductDetailavec le modèle de routage/product-detail(@page "/product-detail") est demandé dans un navigateur à l’URL relative/product-detail.
†La casse Pascal (casse mixte avec majuscules) est une convention de nommage sans espaces ni ponctuation où la première lettre de chaque mot est en majuscule, y compris le premier mot.
La casse kebab est une convention d’affectation de noms sans espaces et ponctuation qui utilise des lettres minuscules et des tirets entre les mots.
Dans le balisage Razor du composant NavMenu (NavMenu.razor) sous la page Home par défaut, les composants NavLink sont ajoutés à partir d’une collection :
<div class="nav-scrollable"
onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu"
aria-hidden="true"></span> Home
</NavLink>
</div>
+ @foreach (var name in GetRoutableComponents())
+ {
+ <div class="nav-item px-3">
+ <NavLink class="nav-link"
+ href="@Regex.Replace(name, @"(\B[A-Z]|\d+)", "-$1").ToLower()">
+ @Regex.Replace(name, @"(\B[A-Z]|\d+)", " $1")
+ </NavLink>
+ </div>
+ }
</nav>
</div>
Méthode GetRoutableComponents dans le bloc @code :
public IEnumerable<string> GetRoutableComponents() =>
Assembly.GetExecutingAssembly()
.ExportedTypes
.Where(t => t.IsSubclassOf(typeof(ComponentBase)))
.Where(c => c.GetCustomAttributes(inherit: true)
.OfType<RouteAttribute>()
.Any())
.Where(c => c.Name != "Home" && c.Name != "Error")
.OrderBy(o => o.Name)
.Select(c => c.Name);
L’exemple précédent n’inclut pas les pages suivantes dans la liste des composants affichée :
- Page
Home: la page est répertoriée séparément des liens générés automatiquement, car elle doit apparaître en haut de la liste et définir le paramètreMatch. - Page d’
Error: la page d’erreur n’est accessible que par le framework et ne doit pas être répertoriée.
Pour une démonstration du code précédent dans un exemple d’application, obtenez l'Blazor Web App ou Blazor WebAssembly exemple d’application.