Udostępnij za pomocą


nawigacja ASP.NET Core Blazor

Uwaga / Notatka

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z aktualną wersją, zobacz artykuł w wersji .NET 10.

W tym artykule wyjaśniono, jak wyzwalać i obsługiwać nawigację między stronami w programie Blazor. Użytkownicy mogą nawigować między różnymi stronami przy użyciu zwykłych linków HTML, a Blazor usprawnia nawigację w aplikacji, aby uniknąć ponownego ładowania pełnej strony i zapewnić płynniejsze działanie. NavLink Użyj składnika , aby utworzyć linki nawigacji, które automatycznie stosują styl, gdy link pasuje do bieżącej strony. W przypadku programowego zarządzania nawigacją i identyfikatorem URI w kodzie języka C# użyj usługi NavigationManager.

W tym artykule wyjaśniono, jak wyzwalać i obsługiwać nawigację między stronami w programie Blazor. NavLink Użyj składnika , aby utworzyć linki nawigacji, które automatycznie stosują styl, gdy link pasuje do bieżącej strony. W przypadku programowego zarządzania nawigacją i identyfikatorem URI w kodzie języka C# użyj usługi NavigationManager.

Ważne

Przykłady kodu w tym artykule pokazują metody wywoływane na Navigation, który jest wstrzykiwany jako NavigationManager w klasach i komponentach.

NavLink Podczas tworzenia linków nawigacyjnych użyj składnika zamiast elementów hiperłącza HTML (<a>). NavLink Składnik zachowuje się jak <a> element, z wyjątkiem, że przełącza klasę active CSS w zależności od tego, czy jego href pasuje do bieżącego adresu URL. Klasa active pomaga użytkownikowi zrozumieć, która strona jest aktywną stroną wśród wyświetlanych linków nawigacji. Opcjonalnie przypisz do NavLink.ActiveClass nazwę klasy CSS, aby zastosować niestandardową klasę CSS do renderowanego linku, gdy bieżąca trasa jest zgodna z href.

W składniku NavMenu (NavMenu.razor) aplikacji Blazor utworzonej na podstawie szablonu projektu Blazor:

<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>

W poprzednim przykładzie HomeNavLinkhref="" pasuje do adresu URL strony głównej i otrzymuje tylko klasę active CSS na domyślnej ścieżce podstawowej aplikacji (/). Drugi NavLink otrzymuje klasę active, gdy użytkownik odwiedzi Counter komponent pod adresem /counter.

Istnieją dwie NavLinkMatch opcje, które można przypisać do Match atrybutu <NavLink> elementu:

  • NavLinkMatch.All: NavLink jest aktywna, gdy jest zgodna z bieżącym adresem URL, ignorując ciąg zapytania i fragment. Aby dołączyć dopasowanie do ciągu/fragmentu zapytania, użyj przełącznika ustawionego Microsoft.AspNetCore.Components.Routing.NavLink.EnableMatchAllForQueryStringAndFragmentAppContext na true.
  • NavLinkMatch.Prefix (ustawienie domyślne): NavLink jest aktywny, gdy pasuje do dowolnego prefiksu bieżącego adresu URL.

Aby wdrożyć niestandardową logikę dopasowania, utwórz podklasę z NavLink i zastąp jej metodę ShouldMatch. Zwróć true z metody, gdy chcesz zastosować klasę CSS active.

public class CustomNavLink : NavLink
{
    protected override bool ShouldMatch(string currentUriAbsolute)
    {
        // Custom matching logic
    }
}

Istnieją dwie NavLinkMatch opcje, które można przypisać do Match atrybutu <NavLink> elementu:

  • NavLinkMatch.All: NavLink jest aktywna, gdy pasuje do całego bieżącego adresu URL, w tym ciągu zapytania i fragmentu.
  • NavLinkMatch.Prefix (ustawienie domyślne): NavLink jest aktywny, gdy pasuje do dowolnego prefiksu bieżącego adresu URL.

Dodatkowe atrybuty składnika NavLink są przekazywane do renderowanego elementu zakotwiczenia. W poniższym przykładzie komponent NavLink zawiera atrybut target:

<NavLink href="example-page" target="_blank">Example page</NavLink>

Renderowane są następujące znaczniki HTML:

<a href="example-page" target="_blank">Example page</a>

Ostrzeżenie

Ze względu na sposób renderowania zawartości podrzędnej przez Blazor, składniki NavLink renderowane wewnątrz pętli for wymagają lokalnej zmiennej indeksu, jeśli zmienna iteracyjna pętli jest używana w zawartości składnika (podrzędnego) NavLink.

@for (int c = 1; c < 4; c++)
{
    var ct = c;
    <li ...>
        <NavLink ...>
            <span ...></span> Product #@ct
        </NavLink>
    </li>
}

Użycie zmiennej indeksu w tym scenariuszu jest wymaganiem dla każdego składnika podrzędnego, który używa zmiennej pętli w swojej zawartości , a nie tylko składnika .

Alternatywnie użyj pętli z foreachEnumerable.Range:

@foreach (var c in Enumerable.Range(1, 3))
{
    <li ...>
        <NavLink ...>
            <span ...></span> Product #@c
        </NavLink>
    </li>
}

Narzędzia do obsługi identyfikatorów URI i stanów nawigacji

Użyj NavigationManager do zarządzania identyfikatorami URI i nawigacją w kodzie C#. NavigationManager Zawiera zdarzenia i metody pokazane w poniższej tabeli.

Członek Description
Uri Pobiera aktualny bezwzględny URI.
BaseUri Pobiera podstawowy identyfikator URI (z końcowym ukośnikiem), który można poprzedzić względnymi ścieżkami identyfikatora URI w celu utworzenia bezwzględnego identyfikatora URI. BaseUri Zazwyczaj odpowiada atrybutowi href elementu dokumentu <base> (lokalizacji <head> zawartości).
NavigateTo Przechodzi do określonego adresu URI. Jeśli forceLoad ma wartość false:
  • Ulepszona nawigacja jest dostępna pod bieżącym adresem URL, Blazor i jest aktywowana.
  • Blazor W przeciwnym razie wykonuje ponowne ładowanie pełnej strony dla żądanego adresu URL.
Jeśli forceLoad ma wartość true:
  • Routing po stronie klienta jest pomijany.
  • Przeglądarka jest zmuszona do załadowania nowej strony z serwera, niezależnie od tego, czy identyfikator URI jest zwykle obsługiwany przez router interaktywny po stronie klienta.

Aby uzyskać więcej informacji, zobacz sekcję Rozszerzona nawigacja i obsługa formularzy .

Jeśli replace jest true, bieżący identyfikator URI w historii przeglądarki zostanie zastąpiony, zamiast dodawać nowy identyfikator URI do stosu historii.

LocationChanged Zdarzenie, które uruchamia się automatycznie po zmianie lokalizacji nawigacji. Aby uzyskać więcej informacji, zobacz sekcję Zmiany lokalizacji .
NotFound Wywoływana w celu obsługi scenariuszy, w których nie można odnaleźć żądanego zasobu. Aby uzyskać więcej informacji, zobacz sekcję Nie znaleziono odpowiedzi .
ToAbsoluteUri Konwertuje względny identyfikator URI na bezwzględny identyfikator URI.
ToBaseRelativePath Na podstawie identyfikatora URI aplikacji konwertuje bezwzględny identyfikator URI na taki, który jest względny względem prefiksu podstawowego URI. Przykład można znaleźć w sekcji Tworzenie identyfikatora URI względnie do prefiksu podstawowego URI.
RegisterLocationChangingHandler Rejestruje obsługę do przetwarzania przychodzących zdarzeń nawigacyjnych. Wywołanie NavigateTo zawsze uruchamia procedurę obsługi.
GetUriWithQueryParameter Zwraca identyfikator URI utworzony przez aktualizację NavigationManager.Uri za pomocą pojedynczego parametru dodanego, zaktualizowanego lub usuniętego. Aby uzyskać więcej informacji, zobacz sekcję Ciągi zapytania.
Członek Description
Uri Pobiera aktualny bezwzględny URI.
BaseUri Pobiera podstawowy identyfikator URI (z końcowym ukośnikiem), który można poprzedzić względnymi ścieżkami identyfikatora URI w celu utworzenia bezwzględnego identyfikatora URI. BaseUri Zazwyczaj odpowiada atrybutowi href elementu dokumentu <base> (lokalizacji <head> zawartości).
NavigateTo Przechodzi do określonego adresu URI. Jeśli forceLoad ma wartość false:
  • Ulepszona nawigacja jest dostępna pod bieżącym adresem URL, Blazor i jest aktywowana.
  • Blazor W przeciwnym razie wykonuje ponowne ładowanie pełnej strony dla żądanego adresu URL.
Jeśli forceLoad ma wartość true:
  • Routing po stronie klienta jest pomijany.
  • Przeglądarka jest zmuszona do załadowania nowej strony z serwera, niezależnie od tego, czy identyfikator URI jest zwykle obsługiwany przez router interaktywny po stronie klienta.

Aby uzyskać więcej informacji, zobacz sekcję Rozszerzona nawigacja i obsługa formularzy .

Jeśli replace jest true, bieżący identyfikator URI w historii przeglądarki zostanie zastąpiony, zamiast dodawać nowy identyfikator URI do stosu historii.

LocationChanged Zdarzenie, które uruchamia się automatycznie po zmianie lokalizacji nawigacji. Aby uzyskać więcej informacji, zobacz sekcję Zmiany lokalizacji .
ToAbsoluteUri Konwertuje względny identyfikator URI na bezwzględny identyfikator URI.
ToBaseRelativePath Na podstawie identyfikatora URI aplikacji konwertuje bezwzględny identyfikator URI na taki, który jest względny względem prefiksu podstawowego URI. Przykład można znaleźć w sekcji Tworzenie identyfikatora URI względnie do prefiksu podstawowego URI.
RegisterLocationChangingHandler Rejestruje obsługę do przetwarzania przychodzących zdarzeń nawigacyjnych. Wywołanie NavigateTo zawsze uruchamia procedurę obsługi.
GetUriWithQueryParameter Zwraca identyfikator URI utworzony przez aktualizację NavigationManager.Uri za pomocą pojedynczego parametru dodanego, zaktualizowanego lub usuniętego. Aby uzyskać więcej informacji, zobacz sekcję Ciągi zapytania.
Członek Description
Uri Pobiera aktualny bezwzględny URI.
BaseUri Pobiera podstawowy identyfikator URI (z końcowym ukośnikiem), który można poprzedzić względnymi ścieżkami identyfikatora URI w celu utworzenia bezwzględnego identyfikatora URI. BaseUri Zazwyczaj odpowiada atrybutowi href elementu dokumentu <base> (lokalizacji <head> zawartości).
NavigateTo Przechodzi do określonego adresu URI. Jeśli forceLoad ma wartość true:
  • Routing po stronie klienta jest pomijany.
  • Przeglądarka jest zmuszona do załadowania nowej strony z serwera, niezależnie od tego, czy identyfikator URI jest zwykle obsługiwany przez router po stronie klienta.
Jeśli replace jest true, bieżący identyfikator URI w historii przeglądarki zostanie zastąpiony, zamiast dodawać nowy identyfikator URI do stosu historii.
LocationChanged Zdarzenie, które uruchamia się automatycznie po zmianie lokalizacji nawigacji. Aby uzyskać więcej informacji, zobacz sekcję Zmiany lokalizacji .
ToAbsoluteUri Konwertuje względny identyfikator URI na bezwzględny identyfikator URI.
ToBaseRelativePath Na podstawie identyfikatora URI aplikacji konwertuje bezwzględny identyfikator URI na taki, który jest względny względem prefiksu podstawowego URI. Przykład można znaleźć w sekcji Tworzenie identyfikatora URI względnie do prefiksu podstawowego URI.
RegisterLocationChangingHandler Rejestruje obsługę do przetwarzania przychodzących zdarzeń nawigacyjnych. Wywołanie NavigateTo zawsze uruchamia procedurę obsługi.
GetUriWithQueryParameter Zwraca identyfikator URI utworzony przez aktualizację NavigationManager.Uri za pomocą pojedynczego parametru dodanego, zaktualizowanego lub usuniętego. Aby uzyskać więcej informacji, zobacz sekcję Ciągi zapytania.
Członek Description
Uri Pobiera aktualny bezwzględny URI.
BaseUri Pobiera podstawowy identyfikator URI (z końcowym ukośnikiem), który można poprzedzić względnymi ścieżkami identyfikatora URI w celu utworzenia bezwzględnego identyfikatora URI. BaseUri Zazwyczaj odpowiada atrybutowi href elementu dokumentu <base> (lokalizacji <head> zawartości).
NavigateTo Przechodzi do określonego adresu URI. Jeśli forceLoad ma wartość true:
  • Routing po stronie klienta jest pomijany.
  • Przeglądarka jest zmuszona do załadowania nowej strony z serwera, niezależnie od tego, czy identyfikator URI jest zwykle obsługiwany przez router po stronie klienta.
Jeśli replace jest true, bieżący identyfikator URI w historii przeglądarki zostanie zastąpiony, zamiast dodawać nowy identyfikator URI do stosu historii.
LocationChanged Zdarzenie, które uruchamia się automatycznie po zmianie lokalizacji nawigacji. Aby uzyskać więcej informacji, zobacz sekcję Zmiany lokalizacji .
ToAbsoluteUri Konwertuje względny identyfikator URI na bezwzględny identyfikator URI.
ToBaseRelativePath Na podstawie identyfikatora URI aplikacji konwertuje bezwzględny identyfikator URI na taki, który jest względny względem prefiksu podstawowego URI. Przykład można znaleźć w sekcji Tworzenie identyfikatora URI względnie do prefiksu podstawowego URI.
GetUriWithQueryParameter Zwraca identyfikator URI utworzony przez aktualizację NavigationManager.Uri za pomocą pojedynczego parametru dodanego, zaktualizowanego lub usuniętego. Aby uzyskać więcej informacji, zobacz sekcję Ciągi zapytania.
Członek Description
Uri Pobiera aktualny bezwzględny URI.
BaseUri Pobiera podstawowy identyfikator URI (z końcowym ukośnikiem), który można poprzedzić względnymi ścieżkami identyfikatora URI w celu utworzenia bezwzględnego identyfikatora URI. BaseUri Zazwyczaj odpowiada atrybutowi href elementu dokumentu <base> (lokalizacji <head> zawartości).
NavigateTo Przechodzi do określonego adresu URI. Jeśli forceLoad ma wartość true:
  • Routing po stronie klienta jest pomijany.
  • Przeglądarka jest zmuszona do załadowania nowej strony z serwera, niezależnie od tego, czy identyfikator URI jest zwykle obsługiwany przez router po stronie klienta.
LocationChanged Zdarzenie, które uruchamia się automatycznie po zmianie lokalizacji nawigacji.
ToAbsoluteUri Konwertuje względny identyfikator URI na bezwzględny identyfikator URI.
ToBaseRelativePath Na podstawie identyfikatora URI aplikacji konwertuje bezwzględny identyfikator URI na taki, który jest względny względem prefiksu podstawowego URI. Przykład można znaleźć w sekcji Tworzenie identyfikatora URI względnie do prefiksu podstawowego URI.

Zmiany lokalizacji

W odniesieniu do LocationChanged wydarzenia LocationChangedEventArgs przedstawia następujące informacje dotyczące zdarzeń nawigacji:

Następujący składnik:

  • Przechodzi do składnika aplikacji Counter (Counter.razor) po wybraniu przycisku przy użyciu polecenia NavigateTo.
  • Obsługuje zdarzenie zmiany lokalizacji, poprzez subskrypcję NavigationManager.LocationChanged.
    • Metoda HandleLocationChanged jest odpięta, gdy Dispose jest wywoływana przez framework. Odłączanie metody umożliwia odzyskiwanie zasobów składnika.

    • Implementacja rejestratora rejestruje następujące informacje po wybraniu przycisku:

      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;
}

Aby uzyskać więcej informacji na temat usuwania komponentów, zobacz ASP.NET Core Razor komponentów.

W przypadku przekierowania podczas renderowania statycznego po stronie serwera (statyczny przewodnik SSR) NavigationManager polega na zgłaszaniu NavigationException przechwyconego przez platformę elementu , który konwertuje błąd na przekierowanie. Kod, który istnieje po wywołaniu NavigateTo metody , nie jest wywoływany. W przypadku korzystania z programu Visual Studio debuger przerywa działanie wyjątku, co wymaga usunięcia zaznaczenia pola wyboru Przerwanie, gdy ten typ wyjątku jest obsługiwany przez użytkownika w interfejsie użytkownika programu Visual Studio, aby uniknąć zatrzymania debugera dla przyszłych przekierowań.

Możesz użyć <BlazorDisableThrowNavigationException> właściwości MSBuild ustawionej na true wartość w pliku projektu aplikacji, aby wyrazić zgodę, aby nie zgłaszać NavigationExceptionobiektu . Ponadto kod po wywołaniu do NavigateTo wykonania, gdy nie zostałby uruchomiony wcześniej. To zachowanie jest domyślnie włączone w szablonie projektu .NET 10 lub nowszym Blazor Web App :

<BlazorDisableThrowNavigationException>true</BlazorDisableThrowNavigationException>

Uwaga / Notatka

W programie .NET 10 lub nowszym możesz wyrazić zgodę, aby nie zgłaszać obiektu NavigationException , ustawiając <BlazorDisableThrowNavigationException> właściwość MSBuild na true wartość w pliku projektu aplikacji. Aby skorzystać z nowej właściwości i zachowania programu MSBuild, uaktualnij aplikację do platformy .NET 10 lub nowszej.

Nie znaleziono odpowiedzi

NavigationManager Udostępnia metodę NotFound obsługi scenariuszy, w których żądany zasób nie jest znaleziony podczas renderowania statycznego po stronie serwera (statycznego renderowania SSR) lub globalnego interaktywnego renderowania:

  • Statyczny SSR: wywołanie NavigationManager.NotFound ustawia kod stanu HTTP na wartość 404.

  • Renderowanie interakcyjne: sygnalizuje, że Blazor router (Router składnik) renderuje zawartość Nie znaleziono.

  • Renderowanie strumieniowe: jeśli rozszerzona nawigacja jest aktywna, renderowanie strumieniowe wyświetla zawartość oznaczoną jako "nie znaleziono" bez ponownego ładowania strony. Po zablokowaniu rozszerzonej nawigacji framework przekierowuje do zawartości "Not Found" poprzez odświeżenie strony.

Uwaga / Notatka

W poniższej dyskusji wspomniano, że komponent Nie znaleziono Razor można przypisać do parametru Router komponentu NotFoundPage. Parametr działa zgodnie z opisem NavigationManager.NotFound i został opisany bardziej szczegółowo w dalszej części tej sekcji.

Renderowanie strumieniowe może renderować tylko składniki, które mają trasę, takie jak NotFoundPage przypisanie (NotFoundPage="...") lub ponowne przypisanie strony kodu stanu (UseStatusCodePagesWithReExecute). DefaultNotFound Zawartość 404 ("Not found" zwykły tekst) nie ma trasy, więc nie można jej używać podczas renderowania strumieniowego.

Uwaga / Notatka

Nie znaleziono fragmentu renderowania (<NotFound>...</NotFound>) nie jest obsługiwany w programie .NET 10 lub nowszym.

NavigationManager.NotFound renderowanie zawartości używa następujących elementów, niezależnie od tego, czy odpowiedź została uruchomiona, czy nie (w kolejności):

  • Jeśli NotFoundEventArgs.Path jest ustawiona, renderuj zawartość przypisanej strony.
  • Jeśli Router.NotFoundPage jest ustawiona, renderuj przypisaną stronę.
  • Strona ponownego uruchamiania oprogramowania pośredniczącego z kodami statusu, jeśli została skonfigurowana.
  • Brak działań, jeśli żadne z powyższych podejść nie zostanie przyjęte.

Oprogramowanie pośredniczące do ponownego wykonywania stron kodu stanu ma pierwszeństwo w przypadku problemów z routingu w przeglądarce, takich jak niepoprawny adres URL wpisany w pasku adresu przeglądarki lub wybranie linku bez punktu końcowego w aplikacji.

Gdy składnik jest renderowany statycznie (statyczny SSR) i NavigationManager.NotFound jest wywoływany, kod stanu 404 jest ustawiany dla odpowiedzi.

@page "/render-not-found-ssr"
@inject NavigationManager Navigation

@code {
    protected override void OnInitialized()
    {
        Navigation.NotFound();
    }
}

Aby udostępnić zawartość Not Found na potrzeby globalnego renderowania interaktywnego, użyj strony Not Found (Razor komponent).

Uwaga / Notatka

Szablon Blazor projektu zawiera NotFound.razor stronę. Ta strona jest automatycznie generowana za każdym razem, gdy NavigationManager.NotFound jest wywoływana, co umożliwia obsługę brakujących tras przy użyciu spójnego doświadczenia użytkownika.

Pages/NotFound.razor:

@page "/not-found"
@layout MainLayout

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

Składnik NotFound jest przypisywany do parametru routera NotFoundPage . NotFoundPage obsługuje routing, który może być wykorzystywany w oprogramowaniu pośredniczącym do ponownego wykonywania dla stron kodu stanu, obejmując również middleware niezależne od Blazor.

W poniższym przykładzie poprzedni NotFound składnik znajduje się w folderze aplikacji Pages i jest przekazywany do parametru NotFoundPage.

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

Gdy składnik jest renderowany w globalnym trybie renderowania interaktywnego, wywołanie NavigationManager.NotFound sygnalizuje Blazor routerowi, aby renderował składnik NotFound.

@page "/render-not-found-interactive"
@inject NavigationManager Navigation

@if (RendererInfo.IsInteractive)
{
    <button @onclick="TriggerNotFound">Trigger Not Found</button>
}

@code {
    private void TriggerNotFound()
    {
        Navigation.NotFound();
    }
}

Możesz użyć zdarzenia OnNotFound do powiadomień, gdy wywoływane jest NavigationManager.NotFound. Zdarzenie jest wyzwalane tylko wtedy, gdy NavigationManager.NotFound jest wywoływane, a nie dla żadnej odpowiedzi 404. Na przykład ustawienie HttpContextAccessor.HttpContext.Response.StatusCode na 404 nie powoduje wyzwolenia NavigationManager.NotFound/OnNotFound polecenia.

Aplikacje, które implementują router niestandardowy, mogą również używać polecenia NavigationManager.NotFound. Niestandardowy router może renderować zawartość „Nie znaleziono” z dwóch źródeł, w zależności od stanu odpowiedzi.

  • Niezależnie od stanu odpowiedzi, ścieżki ponownego wykonania do strony można użyć, przekazując ją do UseStatusCodePagesWithReExecute elementu:

    app.UseStatusCodePagesWithReExecute(
        "/not-found", createScopeForStatusCodePages: true);
    
  • Po rozpoczęciu odpowiedzi, NotFoundEventArgs.Path można użyć, subskrybując do OnNotFoundEvent w routerze.

    @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;
            }
        }
    }
    

W poniższym przykładzie dla składników, które przyjmują interakcyjne renderowanie po stronie serwera (interakcyjne SSR), zawartość niestandardowa jest renderowana w zależności od tego, gdzie OnNotFound jest wywoływana. Jeśli zdarzenie zostanie wyzwolone przez następujący Movie składnik, gdy film nie zostanie znaleziony podczas inicjowania składnika, zostanie wyświetlony niestandardowy komunikat informujący o tym, że żądany film nie zostanie znaleziony. Jeśli zdarzenie zostanie wyzwolone przez User składnik w poniższym przykładzie, pojawi się inny komunikat, który informuje, że użytkownik nie został znaleziony.

Poniższa NotFoundContext usługa zarządza kontekstem i komunikatem, gdy zawartość nie zostanie znaleziona przez składniki.

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;
    }
}

Usługa jest zarejestrowana w pliku po stronie Program serwera:

builder.Services.AddScoped<NotFoundContext>();

Strona NotFound wstawia NotFoundContext i wyświetla nagłówek oraz komunikat.

Pages/NotFound.razor:

@page "/not-found"
@layout MainLayout
@inject NotFoundContext NotFoundContext

<h3>@NotFoundContext.Heading</h3>
<div>
    <p>@NotFoundContext.Message</p>
</div>

Składnik Routes (Routes.razor) ustawia składnik NotFound jako stronę Nie znaleziono za pomocą parametru NotFoundPage.

<Router AppAssembly="typeof(Program).Assembly" NotFoundPage="typeof(Pages.NotFound)">
    ...
</Router>

Na przykładzie następujących komponentów:

  • Usługa NotFoundContext jest wstrzykiwana wraz z elementem NavigationManager.
  • W OnInitializedAsync, HandleNotFound jest obsługujący zdarzenie przypisany do zdarzenia OnNotFound. HandleNotFound wywołuje NotFoundContext.UpdateContext aby ustawić nagłówek i komunikat dla kontentu nie znaleziono w komponencie NotFound.
  • Komponenty zazwyczaj używają identyfikatora z parametru ścieżki, aby uzyskać film lub użytkownika z repozytorium danych, takiego jak baza danych. W poniższych przykładach żadna jednostka nie jest zwracana (null), aby zasymulować, co się stanie, gdy jednostka nie zostanie znaleziona.
  • Gdy żaden element nie jest zwracany do OnInitializedAsync, NavigationManager.NotFound jest wywoływana, co z kolei wyzwala zdarzenie OnNotFound i obsługę zdarzeń HandleNotFound. Router wyświetla komunikat "Nie znaleziono".
  • Metoda HandleNotFound jest odłączana przy usuwaniu komponentu w IDisposable.Dispose.

Movie komponent (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; }
    }
}

User komponent (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; }
    }
}

Aby uzyskać dostęp do poprzednich składników w lokalnym pokazie za pomocą aplikacji testowej, utwórz wpisy w składniku NavMenu (NavMenu.razor), aby uzyskać dostęp do składników Movie i User. Identyfikatory jednostek, przekazane jako parametry trasy, w poniższym przykładzie są wartościami przykładowymi, które nie mają wpływu, ponieważ nie są faktycznie używane przez komponenty, które symulują nieznalezienie filmu ani użytkownika.

W pliku 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>

Ulepszona nawigacja i obsługa formularzy

Ta sekcja dotyczy Blazor Web Appów.

Blazor Web App są w stanie obsługiwać dwa typy routingu dla nawigacji stron i obsługi formularzy żądania:

  • Normalna nawigacja (nawigacja między dokumentami): ponowne ładowanie pełnostronicowe jest wyzwalane dla adresu URL żądania.
  • Ulepszona nawigacja (nawigacja w obrębie tego samego dokumentu): Blazor przechwytuje żądanie i zamiast tego wykonuje żądanie fetch. Blazor następnie wprowadza poprawki do zawartości odpowiedzi w DOM strony. BlazorUlepszone funkcje nawigacji i obsługi formularzy eliminują konieczność pełnego przeładowania strony i pozwalają na lepsze zachowanie stanu strony, co sprawia, że strony ładują się szybciej, zwykle bez utraty położenia przewijania użytkownika.

Ulepszona nawigacja jest dostępna, gdy:

  • Skrypt Blazor Web App (blazor.web.js) jest używany, a nie Blazor Server skrypt (blazor.server.js) ani Blazor WebAssembly skrypt (blazor.webassembly.js).
  • Ta funkcja nie jest jawnie wyłączona.
  • Docelowy adres URL znajduje się w wewnętrznej podstawowej przestrzeni identyfikatora URI (ścieżka podstawowa aplikacji), a link do strony nie ma ustawionego atrybutu data-enhance-nav na wartość false.

Jeśli włączono routing po stronie serwera i rozszerzoną nawigację, programy obsługi zmieniające lokalizacje są wywoływane tylko w przypadku nawigacji programowej inicjowanej przez interakcyjne środowisko uruchomieniowe. W przyszłych wersjach dodatkowe typy nawigacji, takie jak przejście do linku, mogą również wywoływać procedury obsługujące zmiany lokalizacji.

W przypadku ulepszonej nawigacji LocationChanged obsługiwacze zdarzeń zarejestrowane w środowiskach uruchomieniowych Interactive Server i WebAssembly są zazwyczaj wywoływane. Istnieją przypadki, gdy programy obsługi zmiany lokalizacji mogą nie przechwytywać zaawansowanej nawigacji. Na przykład użytkownik może przełączyć się na inną stronę przed udostępnieniem interakcyjnego środowiska uruchomieniowego. Dlatego ważne jest, aby logika aplikacji nie polegała na wywoływaniu obsługi zmiany lokalizacji, ponieważ nie ma gwarancji jej wykonania.

Podczas wywoływania NavigateTo:

  • Jeśli forceLoad to false, co jest wartością domyślną:
    • Ulepszona nawigacja jest dostępna pod bieżącym adresem URL, Blazor i jest aktywowana.
    • Blazor W przeciwnym razie wykonuje ponowne ładowanie pełnej strony dla żądanego adresu URL.
  • Jeśli forceLoad jest true: Blazor przeprowadza ponowne ładowanie całej strony dla żądanego adresu URL, niezależnie od tego, czy rozszerzona nawigacja jest dostępna.

Możesz odświeżyć bieżącą stronę, wywołując metodę NavigationManager.Refresh(bool forceLoad = false), która zawsze wykonuje rozszerzoną nawigację, jeśli jest dostępna. Jeśli rozszerzona nawigacja nie jest dostępna, Blazor wykonuje ponowne ładowanie pełnej strony.

Navigation.Refresh();

Przekaż true do parametru forceLoad , aby upewnić się, że ponowne ładowanie pełnostronicowe jest zawsze wykonywane, nawet jeśli jest dostępna rozszerzona nawigacja:

Navigation.Refresh(true);

Rozszerzona nawigacja jest domyślnie włączona, ale może być kontrolowana hierarchicznie i na podstawie linku przy użyciu atrybutu data-enhance-nav HTML.

Następujące przykłady wyłączają nawigację rozszerzoną:

<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>

Jeśli miejsce docelowe nie jest punktem końcowym Blazor, ulepszona nawigacja nie ma zastosowania, a skrypt JavaScript po stronie klienta próbuje ponownie, ładując pełną stronę. To zapewnia brak wątpliwości dla frameworku w kwestii stron zewnętrznych, które nie powinny być łączone z istniejącą stroną.

Aby włączyć rozszerzoną obsługę formularzy, dodaj parametr Enhance do formularzy EditForm lub atrybut data-enhance do formularzy HTML (<form>):

<EditForm ... Enhance ...>
    ...
</EditForm>
<form ... data-enhance ...>
    ...
</form>

Ulepszona obsługa formularzy nie jest hierarchiczna i nie przepływa do formularzy podrzędnych:

Nieobsługiwane: nie można ustawić rozszerzonej nawigacji na elemencie przodka formularza, aby włączyć rozszerzoną nawigację dla formularza.

<div ... data-enhance ...>
    <form ...>
        <!-- NOT enhanced -->
    </form>
</div>

Ulepszone posty formularza działają tylko z punktami końcowymi Blazor. Opublikowanie rozszerzonego formularza do punktu końcowego innego niż Blazor powoduje wystąpienie błędu.

Aby wyłączyć rozszerzoną nawigację:

  • W przypadku elementu EditFormusuń Enhance parametr z elementu formularza (lub ustaw go na wartość false: Enhance="false").
  • W przypadku kodu HTML <form>usuń data-enhance atrybut z elementu formularza (lub ustaw go na wartość false: data-enhance="false").

BlazorUlepszona nawigacja i obsługa formularzy mogą cofnąć dynamiczne zmiany w modelu DOM, jeśli zaktualizowana zawartość nie jest częścią renderowaną na serwerze. Aby zachować zawartość elementu, użyj atrybutu data-permanent .

W poniższym przykładzie zawartość <div> elementu jest aktualizowana dynamicznie przez skrypt podczas ładowania strony:

<div data-permanent>
    ...
</div>

Gdy Blazor zostanie uruchomiony na kliencie, możesz użyć zdarzenia enhancedload do nasłuchiwania ulepszonych aktualizacji strony. Umożliwia to ponowne stosowanie zmian do modelu DOM, które mogły zostać cofnięte przez rozszerzoną aktualizację strony.

Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));

Aby wyłączyć rozszerzoną nawigację i obsługę formularzy globalnie, zobacz uruchamianie ASP.NET CoreBlazor.

Ulepszona nawigacja przy użyciu renderowania statycznego po stronie serwera (statyczna usługa SSR) wymaga szczególnej uwagi podczas ładowania kodu JavaScript. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor JavaScript z renderowaniem statycznym po stronie serwera (static SSR) .

Utwórz URI względem prefiksu podstawowego URI

Na podstawie bazowego identyfikatora URI aplikacji, ToBaseRelativePath przekształca bezwzględny identyfikator URI na identyfikator URI względny do prefiksu bazowego identyfikatora URI.

Rozważmy następujący przykład:

try
{
    baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
    ...
}

Jeśli podstawowy identyfikator URI aplikacji to https://localhost:8000, zostaną uzyskane następujące wyniki:

  • Przekazanie https://localhost:8000/segment w inputURI skutkuje w baseRelativePathsegment.
  • Przekazanie https://localhost:8000/segment1/segment2 w inputURI skutkuje w baseRelativePathsegment1/segment2.

Jeśli podstawowy identyfikator URI aplikacji nie jest zgodny z podstawowym identyfikatorem URI inputURI, zostanie zgłoszony ArgumentException.

Przekazywanie https://localhost:8001/segment w inputURI powoduje wystąpienie następującego wyjątku:

System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'

Używa NavigationManager interfejsu API historii przeglądarki do utrzymania stanu historii nawigacji związanego z każdą zmianą lokalizacji dokonywaną przez aplikację. Utrzymywanie stanu historii jest szczególnie przydatne w scenariuszach przekierowania zewnętrznego, takich jak w przypadku uwierzytelniania użytkowników z zewnętrznymi dostawcami tożsamości. Aby uzyskać więcej informacji, zobacz sekcję Opcje nawigacji.

Przekaż NavigationOptions do NavigateTo w celu kontrolowania następujących zachowań:

  • ForceLoad: Pomiń routing po stronie klienta i wymuś przeglądarkę do załadowania nowej strony z serwera, bez względu na to, czy identyfikator URI jest obsługiwany przez router po stronie klienta. Domyślna wartość to false.
  • ReplaceHistoryEntry: Zastąp bieżący wpis w stosie historii. Jeśli false, dodaj nowy wpis do stosu historii. Domyślna wartość to false.
  • HistoryEntryState: Pobiera lub ustawia stan, który ma być dołączany do wpisu historii.
Navigation.NavigateTo("/path", new NavigationOptions
{
    HistoryEntryState = "Navigation state"
});

Aby uzyskać więcej informacji na temat uzyskiwania stanu skojarzonego z wpisem historii docelowej podczas obsługi zmian lokalizacji, zobacz sekcję Obsługa/zapobieganie zmianom lokalizacji.

Ciągi zapytań

Użyj atrybutu [SupplyParameterFromQuery] , aby określić, że parametr składnika pochodzi z ciągu zapytania.

Użyj atrybutu [SupplyParameterFromQuery] z atrybutem [Parameter], aby określić, że parametr komponentu składnika trasy pochodzi z ciągu zapytania.

Uwaga / Notatka

Parametry składnika mogą odbierać tylko wartości parametrów zapytania w routowalnych składnikach z dyrektywą @page.

Tylko routowalne składniki bezpośrednio odbierają parametry zapytania, aby uniknąć zakłócania przepływu informacji z góry na dół i aby kolejność przetwarzania parametrów była jasna, zarówno przez platformę, jak i przez aplikację. Ten projekt pozwala uniknąć drobnych usterek w kodzie aplikacji, które zostały napisane przy założeniu określonej kolejności przetwarzania parametrów. Możesz definiować niestandardowe parametry kaskadowe lub bezpośrednio przypisywać do zwykłych parametrów składnika w celu przekazania wartości parametrów zapytania do składników niezwiązanych z routingem.

Parametry składnika dostarczone z ciągu zapytania obsługują następujące typy:

  • bool, DateTime, , decimal, doublefloatGuid, int, long, . string
  • Warianty dopuszczające wartość null poprzednich typów danych.
  • Tablice powyższych typów, niezależnie od tego, czy mogą przyjmować wartość null, czy nie.

Poprawne formatowanie niezależne od kultury jest stosowane dla danego typu (CultureInfo.InvariantCulture).

Określ właściwość atrybutu [SupplyParameterFromQuery]Name , aby użyć nazwy parametru zapytania innej niż nazwa parametru składnika. W poniższym przykładzie nazwa języka C# parametru składnika to {COMPONENT PARAMETER NAME}. Dla symbolu zastępczego {QUERY PARAMETER NAME} określono inną nazwę parametru zapytania:

Właściwości [Parameter] można oznaczyć jako [SupplyParameterFromQuery] i jako private, w przeciwieństwie do właściwości parametru składnika (public).

[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }

Podobnie jak właściwości parametrów składnika ([Parameter]), właściwości [SupplyParameterFromQuery] są zawsze właściwościami public w .NET 6/7. W programie .NET 8 lub nowszym właściwości [SupplyParameterFromQuery] można oznaczyć jako public lub private.

[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }

W poniższym przykładzie z adresem URL :/search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman

  • Właściwość Filter odnosi się do scifi stars.
  • Właściwość Page odnosi się do 3.
  • Tablica Stars jest wypełniana z parametrów zapytania o nazwie star (Name = "star") i odwołuje się do LeVar Burton i Gary Oldman.

Uwaga / Notatka

Parametry ciągu zapytania w następującym komponencie strony routowalnej działają również w komponencie nieroutowalnym bez dyrektywy @page (na przykład Search.razor w przypadku współużytkowanego Search komponentu używanego w innych komponentach).

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; }
}

Służy GetUriWithQueryParameter do dodawania, zmieniania lub usuwania co najmniej jednego parametru zapytania w bieżącym adresie URL:

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})

W poprzednim przykładzie:

  • Symbol {NAME} zastępczy określa nazwę parametru zapytania. Element {VALUE} zastępczy określa wartość jako obsługiwany typ. Obsługiwane typy są wymienione w dalszej części tej sekcji.
  • Zwracany jest ciąg równy bieżącemu adresowi URL z pojedynczym parametrem.
    • Dodano, jeśli nazwa parametru zapytania nie istnieje w bieżącym adresie URL.
    • Wartość została zaktualizowana na podaną, jeśli parametr zapytania istnieje w bieżącym adresie URL.
    • Usunięto, jeśli typ podanej wartości ma wartość null, a wartość to null.
  • Poprawne formatowanie niezależne od kultury jest stosowane dla danego typu (CultureInfo.InvariantCulture).
  • Nazwa i wartość parametru zapytania są zakodowane pod adresem URL.
  • Wszystkie wartości o pasującej nazwie parametru zapytania są zastępowane, jeśli istnieje wiele wystąpień typu.

Wywołaj GetUriWithQueryParameters, aby utworzyć identyfikator URI skonstruowany z Uri z dodanymi, zaktualizowanymi lub usuniętymi wieloma parametrami. Dla każdej wartości, framework używa value?.GetType() do określenia typu w czasie uruchamiania dla każdego parametru zapytania i wybiera prawidłowe formatowanie niezależne od kultury. Struktura zgłasza błąd dla nieobsługiwanych typów.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameters({PARAMETERS})

Zastępczy symbol {PARAMETERS} jest IReadOnlyDictionary<string, object>.

Aby GetUriWithQueryParameters wygenerować nowy identyfikator URI na podstawie podanego identyfikatora URI z dodatkowymi, zaktualizowanymi lub usuniętymi parametrami, przekaż ciąg identyfikatora URI. Dla każdej wartości, framework używa value?.GetType() do określenia typu w czasie uruchamiania dla każdego parametru zapytania i wybiera prawidłowe formatowanie niezależne od kultury. Struktura zgłasza błąd dla nieobsługiwanych typów. Obsługiwane typy są wymienione w dalszej części tej sekcji.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
  • Symbol zastępczy {URI} to identyfikator URI z ciągiem zapytania lub bez niego.
  • Zastępczy symbol {PARAMETERS} jest IReadOnlyDictionary<string, object>.

Obsługiwane typy są identyczne z obsługiwanymi typami ograniczeń tras:

  • bool
  • DateOnly
  • DateTime
  • decimal
  • double
  • float
  • Guid
  • int
  • long
  • string
  • TimeOnly

Obsługiwane typy obejmują:

  • Warianty dopuszczające wartość null poprzednich typów danych.
  • Tablice powyższych typów, niezależnie od tego, czy mogą przyjmować wartość null, czy nie.

Ostrzeżenie

Dzięki kompresji, która jest domyślnie włączona, unikaj tworzenia bezpiecznych (uwierzytelnionych/autoryzowanych) interaktywnych składników po stronie serwera, które renderuje dane z niezaufanych źródeł. Niezaufane źródła obejmują parametry trasy, ciągi zapytań, dane z JS międzyoperacyjności i wszelkie inne źródło danych, które użytkownik zewnętrzny może kontrolować (bazy danych, usługi zewnętrzne). Aby uzyskać więcej informacji, zobacz wskazówki dotyczące ASP.NET CoreBlazorSignalR oraz wskazówki dotyczące łagodzenia zagrożeń dla interaktywnego renderowania po stronie serwera w ASP.NET CoreBlazor.

Zastąp wartość parametru zapytania, gdy parametr istnieje

Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
Bieżący adres URL Wygenerowany adres URL
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

Dołączanie parametru zapytania i wartości, gdy parametr nie istnieje

Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
Bieżący adres URL Wygenerowany adres URL
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

Usuwanie parametru zapytania, gdy wartość parametru jest null

Navigation.GetUriWithQueryParameter("full name", (string)null)
Bieżący adres URL Wygenerowany adres URL
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/

Dodawanie, aktualizowanie i usuwanie parametrów zapytania

W poniższym przykładzie:

  • name zostanie usunięta, jeśli jest obecna.
  • age parametr jest dodawany z wartością 25 (int), jeśli nie istnieje. Jeśli jest obecny, age zostanie zaktualizowany do wartości 25.
  • eye color jest dodawany lub aktualizowany do wartości green.
Navigation.GetUriWithQueryParameters(
    new Dictionary<string, object?>
    {
        ["name"] = null,
        ["age"] = (int?)25,
        ["eye color"] = "green"
    })
Bieżący adres URL Wygenerowany adres URL
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

Obsługa wartości wyliczalnych

W poniższym przykładzie:

  • full name jest dodawany lub aktualizowany na Morena Baccarin, pojedynczą wartość.
  • pingparametry są dodawane lub zastępowane parametrami 35, 1687 i 240.
Navigation.GetUriWithQueryParameters(
    new Dictionary<string, object?>
    {
        ["full name"] = "Morena Baccarin",
        ["ping"] = new int?[] { 35, 16, null, 87, 240 }
    })
Bieżący adres URL Wygenerowany adres URL
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

Aby nawigować za pomocą dodanego lub zmodyfikowanego ciągu zapytania, przekaż wygenerowany adres URL do .NavigateTo

Następujące przykładowe wywołania:

  • GetUriWithQueryParameter aby dodać lub zamienić name parametr zapytania przy użyciu wartości Morena Baccarin.
  • Wywołanie NavigateTo powoduje nawigację do nowego adresu URL.
Navigation.NavigateTo(
    Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));

Ciąg zapytania w żądaniu jest uzyskiwany z właściwości NavigationManager.Uri.

@inject NavigationManager Navigation

...

var query = new Uri(Navigation.Uri).Query;

Aby przeanalizować parametry ciągu zapytania, jednym z podejść jest użycie interop z JavaScript (URLSearchParamsJS):

export createQueryString = (string queryString) => new URLSearchParams(queryString);

Aby uzyskać więcej informacji na temat izolacji języka JavaScript z modułami języka JavaScript, zobacz Wywoływanie funkcji Języka JavaScript z metod platformy .NET w programie ASP.NET Core Blazor.

Przejdź do nazwanego elementu za pomocą następujących podejść z zahashowanym odwołaniem (#) do elementu. Trasy do elementów w składniku oraz trasy do elementów w składnikach zewnętrznych używają ścieżek względnych od katalogu głównego. Ukośnik początkowy (/) jest opcjonalny.

Przykłady każdego z poniższych podejść pokazują nawigację do elementu określonego przez idtargetElement w komponencie Counter.

  • Element kotwiczący (<a>) z href

    <a href="/counter#targetElement">
    
  • NavLink komponent z elementem href:

    <NavLink href="/counter#targetElement">
    
  • NavigationManager.NavigateTo przekazywanie względnego adresu URL:

    Navigation.NavigateTo("/counter#targetElement");
    

W poniższym przykładzie pokazano przechodzenie do nagłówków H2 w składniku i do składników zewnętrznych.

W składnikach Home (Home.razor) i Counter (Counter.razor) umieść następujące znaczniki u dołu istniejącego znacznika składnika, aby służyć jako elementy docelowe nawigacji. Funkcja <div> tworzy sztuczną przestrzeń pionową w celu zademonstrowania zachowania przewijania przeglądarki:

<div class="border border-info rounded bg-info" style="height:500px"></div>

<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>

Dodaj następujący FragmentRouting składnik do aplikacji.

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

Obsługa/zapobieganie zmianom lokalizacji

RegisterLocationChangingHandler rejestruje obsługiwacz w celu przetwarzania przychodzących zdarzeń nawigacyjnych. Kontekst obsługi udostępniany przez LocationChangingContext ma następujące właściwości:

Składnik może zarejestrować wiele programów obsługi zmiany lokalizacji w metodzie cyklu życia OnAfterRender{Async}. Nawigacja wywołuje wszystkie programy obsługi zmieniające lokalizacje zarejestrowane w całej aplikacji (w wielu składnikach), a każda nawigacja wewnętrzna wykonuje je wszystkie równolegle. Oprócz NavigateTo wywoływane są również procedury obsługi:

  • Podczas wybierania linków wewnętrznych, czyli linków wskazujących na adresy URL w ścieżce podstawowej aplikacji.
  • Podczas nawigowania za pomocą przycisków do przodu i wstecz w przeglądarce.

Obsługiwacze są wykonywane tylko na potrzeby nawigacji wewnątrz aplikacji. Jeśli użytkownik wybierze link prowadzący do innej witryny lub ręcznie zmieni adres w pasku adresu na inny, obsługiwacze zmiany lokalizacji nie są wykonywane.

Zaimplementuj IDisposable i usuń zarejestrowane programy obsługi w celu ich wyrejestrowania. Aby uzyskać więcej informacji, zobacz usuwanie komponentów w ASP.NET Core Razor.

Ważne

Nie próbuj wykonywać zadań oczyszczania DOM za pośrednictwem interop języka JavaScript (JS) podczas obsługi zmian adresu. MutationObserver Użyj wzorca w JS w kliencie. Aby uzyskać więcej informacji, zobacz ASP.NET Core Blazor JavaScript interoperability (JS interop).

W poniższym przykładzie rejestruje się obsługę zmiany lokalizacji dla zdarzeń nawigacji.

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();
}

Ponieważ nawigacja wewnętrzna może zostać anulowana asynchronicznie, może wystąpić wiele nakładających się wywołań zarejestrowanych obsługiwaczy. Na przykład wiele wywołań programu obsługi może wystąpić, gdy użytkownik szybko wybierze przycisk Wstecz na stronie lub wybierze wiele linków przed wykonaniem nawigacji. Poniżej przedstawiono podsumowanie logiki nawigacji asynchronicznej:

  • Jeśli zarejestrowano jakiekolwiek programy obsługi zmiany lokalizacji, nawigacja jest początkowo cofnięta do stanu początkowego, a następnie odtwarzana, jeśli nawigacja nie zostanie anulowana.
  • W przypadku nakładania się żądań nawigacji najnowsze żądanie zawsze anuluje wcześniejsze żądania, co oznacza następujące kwestie:
    • Aplikacja może traktować wiele opcji przycisków wstecz i do przodu jako pojedynczy wybór.
    • Jeśli użytkownik wybierze wiele linków przed zakończeniem nawigacji, wybranie ostatniego linku określa nawigację.

Aby uzyskać więcej informacji na temat przekazywania NavigationOptions do NavigateTo w celu kontrolowania wpisów i stanu stosu historii nawigacji, zobacz sekcję Nawigacja opcje.

Aby uzyskać dodatkowy przykładowy kod, zobacz NavigationManagerComponent w BasicTestApp (źródło referencyjne dotnet/aspnetcore).

Uwaga / Notatka

Linki dokumentacyjne do źródła referencyjnego .NET zwykle ładują domyślną gałąź repozytorium, która odzwierciedla obecne prace rozwojowe nad nadchodzącą wersją .NET. Aby wybrać tag dla określonej wersji, użyj listy rozwijanej Przełącz gałęzie lub tagi. Aby uzyskać więcej informacji, zobacz Jak wybrać tag wersji kodu źródłowego ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Składnik NavigationLock przechwytuje zdarzenia nawigacji, o ile jest renderowany, skutecznie "blokując" daną nawigację do momentu podjęcia decyzji o kontynuowaniu lub anulowaniu. Użyj NavigationLock gdy przechwytywanie nawigacji można ograniczyć do okresu istnienia składnika.

NavigationLock parametry:

  • ConfirmExternalNavigation Ustawia okno dialogowe przeglądarki, aby monitować użytkownika o potwierdzenie lub anulowanie nawigacji zewnętrznej. Domyślna wartość to false. Wyświetlenie okna dialogowego potwierdzenia wymaga początkowej interakcji użytkownika ze stroną przed wyzwoleniem nawigacji zewnętrznej za pomocą adresu URL na pasku adresu przeglądarki. Aby uzyskać więcej informacji na temat wymagań dotyczących interakcji, zobacz Okno: beforeunload zdarzenie.
  • OnBeforeInternalNavigation Ustawia wywołanie zwrotne dla zdarzeń nawigacji wewnętrznej.

W poniższym składniku NavLock:

  • Próba przejścia do witryny internetowej firmy Microsoft musi zostać potwierdzona przez użytkownika, zanim nawigacja do https://www.microsoft.com zakończy się pomyślnie.
  • PreventNavigation jest wywoływane, aby zapobiec nawigacji, jeśli użytkownik odmówi potwierdzenia jej za pośrednictwem wywołania międzyoperacyjnego języka JavaScript (JS), które uruchamia dialog .

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();
        }
    }
}

Aby uzyskać dodatkowy przykładowy kod, zobacz ConfigurableNavigationLock składnik w BasicTestApp (dotnet/aspnetcore źródle odwołania)..

NavLink Wpisy komponentów można dynamicznie tworzyć z komponentów aplikacji za pomocą refleksji. W poniższym przykładzie przedstawiono ogólne podejście do dalszego dostosowywania.

W przypadku następującej demonstracji dla składników aplikacji jest używana spójna, standardowa konwencja nazewnictwa:

  • Nazwy plików składników routable używają wielkich liter w stylu Pascal, na przykład Pages/ProductDetail.razor.
  • Ścieżki plików składników routable pasują do ich adresów URL w stylu kebab-case‡, z myślnikami pojawiającymi się między słowami w szablonie trasy składnika. Na przykład składnik ProductDetail z szablonem trasy /product-detail (@page "/product-detail") jest żądany w przeglądarce pod względnym adresem URL /product-detail.

†Pascal case (znany też jako upper camel case) to konwencja nazewnictwa bez spacji i interpunkcji, w której każdy wyraz, łącznie z pierwszym, zaczyna się wielką literą.
Kebab case to konwencja nazewnictwa bez spacji i znaków interpunkcyjnych, która używa małych liter i kresek między wyrazami.

W znaczniku Razor składnika NavMenu (NavMenu.razor) na domyślnej stronie Home, składniki NavLink są dodawane z kolekcji:

<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>

Metoda GetRoutableComponents w @code bloku:

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);

Powyższy przykład nie zawiera następujących stron na renderowanej liście składników:

  • Home page: Strona jest wyświetlana oddzielnie od automatycznie wygenerowanych linków, ponieważ powinna pojawić się na górze listy oraz ustawić parametr Match.
  • Error page: Do strony błędu przechodzi tylko system i nie powinna być wyświetlana.

Aby zademonstrować powyższy kod w przykładowej aplikacji, uzyskaj przykładowąBlazor Web App aplikację lub Blazor WebAssembly.