Teilen über


Routing und Navigation in ASP.NET Core Blazor

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Warnung

Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der Supportrichtlinie für .NET und .NET Core. Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

Wichtig

Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.

Informationen zum aktuellen Release finden Sie in der .NET 8-Version dieses Artikels.

In diesem Artikel wird erläutert, wie Sie das Anforderungsrouting für Blazor-Apps verwalten und die NavLink-Komponente zum Erstellen von Navigationslinks verwenden.

Wichtig

Die Codebeispiele in diesem Artikel zeigen Methoden, die für Navigation aufgerufen werden, einen in Klassen und Komponenten injizierten NavigationManager.

Statisches und interaktives Routing

Dieser Abschnitt gilt für Blazor Web Apps.

Wenn das Prerendering aktiviert ist, führt der Blazor-Router (Router-Komponente, <Router> in Routes.razor) während des statischen serverseitigen Renderings (statisches SSR) ein statisches Routing zu Komponenten durch. Dieser Routingtyp wird als statisches Routing bezeichnet.

Wenn der Routes-Komponente ein interaktiver Rendermodus zugewiesen wird, wird der Blazor-Router nach statischem SSR mit statischem Routing auf dem Server interaktiv. Diese Art von Routing wird als interaktives Routing bezeichnet.

Statische Router verwenden Endpunktrouting und den HTTP-Anforderungspfad, um zu bestimmen, welche Komponente gerendert werden soll. Wenn der Router interaktiv wird, wird die URL des Dokuments (die URL in der Adressleiste des Browsers) verwendet, um zu bestimmen, welche Komponente gerendert werden soll. Das bedeutet, dass der interaktive Router dynamisch ändern kann, welche Komponente gerendert wird, wenn sich die URL des Dokuments dynamisch in eine andere gültige interne URL ändert. Dazu ist keine HTTP-Anforderung zum Abrufen neuer Seiteninhalte erforderlich.

Interaktives Routing verhindert auch das Vorabrendern, da neue Seiteninhalte nicht vom Server über eine normale Seitenanforderung angefordert werden. Weitere Informationen finden Sie unter Prerendering von Razor-Komponenten in ASP.NET Core.

Routenvorlagen

Die Router-Komponente ermöglicht das Routing an Razor-Komponenten und befindet sich in der Routes-Komponente der App (Components/Routes.razor).

Die Router-Komponente ermöglicht das Routing an Razor-Komponenten. Die Router-Komponente wird in der App-Komponente verwendet (App.razor).

Wenn eine Razor-Komponente (.razor) mit einer @page-Anweisung kompiliert wird, wird für die generierte Komponentenklasse ein RouteAttribute-Objekt bereitgestellt, das die Routenvorlage der Komponente angibt.

Wenn die App gestartet wird, wird die Assembly gescannt, die als AppAssembly-Objekt des Routers angegeben wurde, um Routeninformationen für die Komponenten der App zu erfassen, die über ein RouteAttribute-Objekt verfügen.

Zur Laufzeit führt die RouteView-Komponente Folgendes aus:

  • Sie empfängt das RouteData-Objekt vom Router-Objekt zusammen mit den Routenparametern.
  • Sie rendert die angegebene Komponente mit deren Layout, einschließlich aller weiteren geschachtelten Layouts.

Optional können Sie einen DefaultLayout-Parameter mit einer Layoutklasse für Komponenten angeben, die kein Layout mit der @layout-Anweisung festlegen. Die Blazor-Projektvorlagen des Frameworks geben die MainLayout-Komponente (MainLayout.razor) als Standardlayout der App an. Weitere Informationen zu Layouts finden Sie unter Blazor-Layouts in ASP.NET Core.

Komponenten unterstützen mehrere Routenvorlagen mithilfe mehrerer @page-Anweisungen. Die folgende Beispielkomponente lädt Anforderungen für /blazor-route und /different-blazor-route.

BlazorRoute.razor:

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

<PageTitle>Routing</PageTitle>

<h1>Routing Example</h1>

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

<PageTitle>Routing</PageTitle>

<h1>Routing Example</h1>

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

<h1>Blazor routing</h1>
@page "/blazor-route"
@page "/different-blazor-route"

<h1>Blazor routing</h1>
@page "/blazor-route"
@page "/different-blazor-route"

<h1>Blazor routing</h1>
@page "/blazor-route"
@page "/different-blazor-route"

<h1>Blazor routing</h1>

Wichtig

Damit URLs ordnungsgemäß aufgelöst werden können, muss die App das Tag <base> (Speicherort des <head>-Inhalts) mit dem im Attribut href angegebenen App-Basispfad enthalten. Weitere Informationen finden Sie unter Hosten und Bereitstellen von Blazor in ASP.NET Core.

Router interagiert nicht mit Abfragezeichenfolgenwerten. Informationen zur Arbeit mit Abfragezeichenfolgen finden Sie im Abschnitt Abfragezeichenfolgen.

Alternativ zur Angabe der Routenvorlage als Zeichenfolgenliteral mit der Anweisung @page können konstantenbasierte Routenvorlagen mit der @attribute-Anweisung angegeben werden.

Im folgenden Beispiel wird die Anweisung @page in einer Komponente durch die Anweisung @attribute und die konstantenbasierte Routenvorlage in Constants.CounterRoute ersetzt, die an anderer Stelle in der App auf /counter festgelegt wird:

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

Hinweis

Seit der Veröffentlichung von ASP.NET Core 5.0.1 und allen weiteren 5.x-Releases enthält die Router-Komponente den PreferExactMatches-Parameter, der auf @true festgelegt ist. Weitere Informationen finden Sie unter Migrieren von ASP.NET Core 3.1 zu 5.0.

Fokussieren eines Elements bei der Navigation

Verwenden Sie die FocusOnNavigate-Komponente, um den UI-Fokus auf Grundlage eines CSS-Selektors auf ein Element festzulegen, nachdem Sie von einer Seite zu einer anderen navigiert sind.

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

Wenn die Router-Komponente zu einer neuen Seite navigiert, legt die FocusOnNavigate-Komponente den Fokus auf den Header der obersten Ebene (<h1>) der Seite fest. Dies ist eine gängige Strategie, um sicherzustellen, dass eine Seitennavigation bei Verwendung der Sprachausgabe angekündigt wird.

Bereitstellen von benutzerdefiniertem Inhalt, wenn kein Inhalt gefunden wurde

Die Router-Komponente ermöglicht es der App, benutzerdefinierte Inhalte anzugeben, wenn für die angeforderte Route keine Inhalte gefunden werden.

Legen Sie benutzerdefinierten Inhalt für den NotFound-Parameter der Router-Komponente fest:

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

Beliebige Elemente werden als Inhalt der NotFound-Parameter unterstützt, z. B. andere interaktive Komponenten. Informationen zum Anwenden eines Standardlayouts auf NotFound-Inhalte finden Sie unter Blazor-Layouts in ASP.NET Core.

Wichtig

Blazor Web Apps verwenden nicht den NotFound-Parameter (<NotFound>...</NotFound>-Markup), der Parameter wird jedoch aus Gründen der Abwärtskompatibilität unterstützt, um eine einschneidende Änderung im Framework zu vermeiden. Die serverseitige ASP.NET Core Middleware-Pipeline verarbeitet Anforderungen auf dem Server. Verwenden Sie serverseitige Techniken, um fehlerhafte Anforderungen zu verarbeiten. Weitere Informationen finden Sie unter ASP.NET Core Blazor-Rendermodi.

Weiterleiten an Komponenten aus mehreren Assemblys

Dieser Abschnitt gilt für Blazor Web Apps.

Verwenden Sie den Parameter AdditionalAssemblies der Router-Komponente und den Endpunktkonventions-Generator AddAdditionalAssemblies, um routingfähige Komponenten in zusätzlichen Assemblys zu ermitteln. In den folgenden Unterabschnitten wird erläutert, wann und wie die einzelnen APIs verwendet werden.

Statisches Routing

Um routingfähige Komponenten von zusätzlichen Assemblys für statisches serverseitiges Rendering (statisches SSR) zu ermitteln, auch wenn der Router später für interaktives Rendering interaktiv wird, müssen die Assemblys für das Blazor-Framework offengelegt werden. Rufen Sie die AddAdditionalAssemblies-Methode mit den zusätzlichen Assemblys auf, die in der Datei Program des Serverprojekts mit MapRazorComponents verkettet sind.

Das folgende Beispiel enthält die routingfähigen Komponenten in der Assembly des BlazorSample.Client-Projekts. Dazu wird die Datei _Imports.razor des Projekts verwendet:

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

Hinweis

Die vorstehende Anleitung gilt auch für Szenarien mit Komponentenklassenbibliotheken. Weitere wichtige Anleitungen für Klassenbibliotheken und statisches SSR finden Sie in den ASP.NET Core Razor-Klassenbibliotheken (Razor Class Libraries, RCLs) mit statischem serverseitigem Rendering (statisches SSR).

Interaktives Routing

Der Routes-Komponente (Routes.razor) kann ein interaktiver Rendermodus zugewiesen werden. Dadurch wird der Blazor-Router nach statischem SSR und statischem Routing auf dem Server interaktiv. <Routes @rendermode="InteractiveServer" /> weist beispielsweise der Routes-Komponente interaktives serverseitiges Rendering (interaktives SSR) zu. Die Router-Komponente erbt interaktives serverseitiges Rendering (interaktives SSR) von der Routes-Komponente. Der Router wird nach dem statischen Routing auf dem Server interaktiv.

Die interne Navigation für interaktives Routing umfasst nicht das Anfordern neuer Seiteninhalte vom Server. Daher findet das Vorabrendern nicht für interne Seitenanforderungen statt. Weitere Informationen finden Sie unter Prerendering von Razor-Komponenten in ASP.NET Core.

Wenn die Routes-Komponente im Serverprojekt definiert ist, sollte der AdditionalAssemblies-Parameter der Router-Komponente die Assembly des .Client-Projekts enthalten. Dadurch kann der Router bei interaktivem Rendering ordnungsgemäß funktionieren.

Im folgenden Beispiel befindet sich die Routes-Komponente im Serverprojekt, und die Datei _Imports.razor des BlazorSample.Client-Projekts gibt die Assembly an, die nach routingfähigen Komponenten durchsucht werden soll:

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

Zusätzliche Assemblys werden neben der für AppAssembly angegebenen Assembly gescannt.

Hinweis

Die vorstehende Anleitung gilt auch für Szenarien mit Komponentenklassenbibliotheken.

Alternativ sind routingfähige Komponenten nur im .Client-Projekt vorhanden, wobei eine globale interaktive WebAssembly oder automatisches Rendering angewendet wird, und die Routes-Komponente wird im .Client-Projekt, nicht im Serverprojekt definiert. In diesem Fall gibt es keine externen Assemblys mit routingfähigen Komponenten, daher ist es nicht erforderlich, einen Wert für AdditionalAssemblies anzugeben.

Dieser Abschnitt gilt für Blazor Server-Apps.

Verwenden Sie den Parameter AdditionalAssemblies der Router-Komponente und den Endpunktkonventions-Generator AddAdditionalAssemblies, um routingfähige Komponenten in zusätzlichen Assemblys zu ermitteln.

Im folgenden Beispiel ist Component1 eine für das Routing geeignete Komponente, die in einer Komponentenklassenbibliothek namens ComponentLibrary definiert ist, auf die verwiesen wird.

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

Zusätzliche Assemblys werden neben der für AppAssembly angegebenen Assembly gescannt.

Routenparameter

Der Router verwendet Routenparameter, um die entsprechenden Komponentenparameter mit demselben Namen aufzufüllen. Bei den Routenparameternamen muss die Groß- und Kleinschreibung nicht berücksichtigt werden. Im folgenden Beispiel weist der Parameter text den Wert des Routensegments der Eigenschaft Text der Komponente zu. Wenn eine Anforderung für /route-parameter-1/amazing erfolgt, wird der Inhalt als Blazor is amazing! gerendert.

RouteParameter1.razor:

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

<PageTitle>Route Parameter 1</PageTitle>

<h1>Route Parameter Example 1</h1>

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

@code {
    [Parameter]
    public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"

<PageTitle>Route Parameter 1</PageTitle>

<h1>Route Parameter Example 1</h1>

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

@code {
    [Parameter]
    public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"

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

@code {
    [Parameter]
    public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"

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

@code {
    [Parameter]
    public string? Text { get; set; }
}
@page "/route-parameter-1/{text}"

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

@code {
    [Parameter]
    public string Text { get; set; }
}
@page "/route-parameter-1/{text}"

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

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

Optionale Parameter werden unterstützt. Im folgenden Beispiel weist der optionale Parameter text den Wert des Routensegments der Eigenschaft Text der Komponente zu. Wenn das Segment nicht vorhanden ist, wird der Wert von Text auf fantastic festgelegt.

Optionale Parameter werden nicht unterstützt. Im folgenden Beispiel werden zwei @page-Anweisungen angewendet. Die erste Anweisung ermöglicht die Navigation zur Komponente ohne einen Parameter. Die zweite Direktive weist der Text-Eigenschaft der Komponente den Wert für die {text}-Routenparameter zu.

RouteParameter2.razor:

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

<PageTitle>Route Parameter 2</PageTitle>

<h1>Route Parameter Example 2</h1>

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

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

    protected override void OnParametersSet() => Text = Text ?? "fantastic";
}
@page "/route-parameter-2/{text?}"

<PageTitle>Route Parameter 2</PageTitle>

<h1>Route Parameter Example 2</h1>

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

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

    protected override void OnParametersSet() => Text = Text ?? "fantastic";
}
@page "/route-parameter-2/{text?}"

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

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

    protected override void OnParametersSet()
    {
        Text = Text ?? "fantastic";
    }
}
@page "/route-parameter-2/{text?}"

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

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

    protected override void OnParametersSet()
    {
        Text = Text ?? "fantastic";
    }
}
@page "/route-parameter-2/{text?}"

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

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

    protected override void OnParametersSet()
    {
        Text = Text ?? "fantastic";
    }
}
@page "/route-parameter-2"
@page "/route-parameter-2/{text}"

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

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

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

Wenn die OnInitialized{Async}-Lebenszyklusmethode anstelle der OnParametersSet{Async}-Lebenszyklusmethode verwendet wird, erfolgt die Standardzuweisung der Text-Eigenschaft zu fantastic nicht, wenn Benutzende innerhalb derselben Komponente navigieren. Diese Situation tritt z. B. auf, wenn von /route-parameter-2/amazing zu /route-parameter-2 navigiert wird. Da die Komponenteninstanz beibehalten wird und neue Parameter akzeptiert, wird die Methode OnInitialized nicht erneut aufgerufen.

Hinweis

Routenparameter funktionieren nicht mit Abfragezeichenfolgenwerten. Informationen zur Arbeit mit Abfragezeichenfolgen finden Sie im Abschnitt Abfragezeichenfolgen.

Routeneinschränkungen

Eine Routeneinschränkung erzwingt die Typübereinstimmung in einem Routensegment zu einer Komponente.

Im folgenden Beispiel stimmt die Route zur User-Komponente nur überein, wenn:

  • ein Id-Routensegment in der Anforderungs-URL vorhanden ist.
  • das Id-Segment ein Integer (int) ist.

User.razor:

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

<PageTitle>User</PageTitle>

<h1>User Example</h1>

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

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

Hinweis

Routeneinschränkungen funktionieren nicht mit Abfragezeichenfolgenwerten. Informationen zur Arbeit mit Abfragezeichenfolgen finden Sie im Abschnitt Abfragezeichenfolgen.

Die in der folgenden Tabelle aufgeführten Routeneinschränkungen sind verfügbar. Informationen zu den Routeneinschränkungen der invarianten Kultur finden Sie in der Warnung unter der Tabelle.

Constraint Beispiel Beispiele für Übereinstimmungen Invariante
Kultur
Übereinstimmend
bool {active:bool} true, FALSE Nein
datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm Ja
decimal {price:decimal} 49.99, -1,000.01 Ja
double {weight:double} 1.234, -1,001.01e8 Ja
float {weight:float} 1.234, -1,001.01e8 Ja
guid {id:guid} 00001111-aaaa-2222-bbbb-3333cccc4444, {00001111-aaaa-2222-bbbb-3333cccc4444} Nein
int {id:int} 123456789, -123456789 Ja
long {ticks:long} 123456789, -123456789 Ja
nonfile {parameter:nonfile} Nicht BlazorSample.styles.css, nicht favicon.ico Ja

Warnung

Für Routeneinschränkungen, mit denen die URL überprüft wird und die in den CLR-Typ umgewandelt werden (beispielsweise int oder DateTime), wird immer die invariante Kultur verwendet. Diese Einschränkungen setzen voraus, dass die URL nicht lokalisierbar ist.

Routeneinschränkungen funktionieren auch mit optionalen Parametern. Im folgenden Beispiel ist Id erforderlich, während Option ein optionaler boolescher Routenparameter ist.

User.razor:

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

<p>
    Id: @Id
</p>

<p>
    Option: @Option
</p>

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

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

Vermeiden der Dateierfassung in einem Routenparameter

Die folgende Routenvorlage erfasst versehentlich statische Objektpfade in seinem optionalen Routenparameter (Optional). Zum Beispiel wird das Stylesheet der App (.styles.css) erfasst, wodurch die Stile der App zerstört werden:

@page "/{optional?}"

...

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

Um einen Routenparameter auf die Erfassung von Nicht-Dateipfaden zu beschränken, verwenden Sie die :nonfile-Einschränkung in der Routenvorlage:

@page "/{optional:nonfile?}"

Routing mit URLs, die Punkte enthalten

Bei einer serverseitigen Standardroutenvorlage wird davon ausgegangen, dass eine Datei angefordert wird, wenn das letzte Segment einer Anforderungs-URL einen Punkt (.) enthält. Beispielsweise wird die URL /example/some.thing vom Router als Anforderung für eine Datei mit dem Namen some.thing interpretiert. Ohne zusätzliche Konfiguration gibt eine App die Antwort 404 – Nicht gefunden zurück, wenn some.thing an eine Komponente mit einer @page-Anweisung weiterleiten sollte und some.thing ein Routenparameterwert ist. Wenn eine Route mit mindestens einem Parameter verwendet werden soll, der einen Punkt enthält, muss die Route von der App mit einer benutzerdefinierten Vorlage konfiguriert werden.

Sehen Sie sich z. B. die folgende Example-Komponente an, die einen Routenparameter aus dem letzten Segment der URL empfangen kann.

Example.razor:

@page "/example/{param?}"

<p>
    Param: @Param
</p>

@code {
    [Parameter]
    public string? Param { get; set; }
}
@page "/example/{param?}"

<p>
    Param: @Param
</p>

@code {
    [Parameter]
    public string? Param { get; set; }
}
@page "/example/{param?}"

<p>
    Param: @Param
</p>

@code {
    [Parameter]
    public string Param { get; set; }
}
@page "/example"
@page "/example/{param}"

<p>
    Param: @Param
</p>

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

Um der Server-App einer gehosteten Blazor WebAssemblyLösung zu erlauben, die Anforderung mit einem Punkt im param-Routenparameter weiterzuleiten, fügen Sie mit dem optionalen Parameter in der Program-Datei eine Ausweichseiten-Routenvorlage hinzu:

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

Um eine Blazor Server-App so zu konfigurieren, dass die Anforderung mit einem Punkt im param-Routenparameter weitergeleitet wird, fügen Sie mit dem optionalen Parameter in der Program-Datei eine Ausweichseiten-Routenvorlage hinzu:

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

Weitere Informationen finden Sie unter Routing in ASP.NET Core.

Wenn Sie der Server-App einer gehosteten Blazor WebAssembly-Lösung erlauben möchten, dass sie die Anforderung mit einem Punkt im param-Routenparameter weiterleitet, fügen Sie eine Ausweichdatei-Routenvorlage mit dem optionale Parameter in Startup.Configure hinzu.

Startup.cs:

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

Fügen Sie eine Ausweichdatei-Routenvorlage hinzu, wobei sich der optionale Parameter in Startup.Configure befindet, um eine Blazor Server-App so zu konfigurieren, dass die Anforderung mit einem Punkt im param-Routenparameter weiterleitet wird.

Startup.cs:

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

Weitere Informationen finden Sie unter Routing in ASP.NET Core.

Catch-All-Routenparameter

Catch-All-Routenparameter, die Pfade über mehrere Ordnergrenzen hinweg erfassen, werden in Komponenten unterstützt.

Für Catch-All-Routenparameter gilt:

  • Sie müssen so benannt werden, dass sie dem Routensegmentnamen entsprechen. Die Groß-/Kleinschreibung muss bei der Benennung nicht beachtet werden.
  • Ein string-Typ. Im Framework steht keine automatische Übertragung zur Verfügung.
  • Am Ende der URL.

CatchAll.razor:

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

<PageTitle>Catch All</PageTitle>

<h1>Catch All Parameters Example</h1>

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

<p>
    PageRoute: @PageRoute
</p>

@code {
    [Parameter]
    public string? PageRoute { get; set; }
}
@page "/catch-all/{*pageRoute}"

<PageTitle>Catch All</PageTitle>

<h1>Catch All Parameters Example</h1>

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

<p>
    PageRoute: @PageRoute
</p>

@code {
    [Parameter]
    public string? PageRoute { get; set; }
}
@page "/catch-all/{*pageRoute}"

@code {
    [Parameter]
    public string? PageRoute { get; set; }
}
@page "/catch-all/{*pageRoute}"

@code {
    [Parameter]
    public string? PageRoute { get; set; }
}
@page "/catch-all/{*pageRoute}"

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

Bei der URL /catch-all/this/is/a/test mit der Routenvorlage /catch-all/{*pageRoute} wird der Wert für PageRoute auf this/is/a/test festgelegt.

Schrägstriche und Segmente des erfassten Pfads werden decodiert. Bei der Routenvorlage /catch-all/{*pageRoute} hält die URL /catch-all/this/is/a%2Ftest%2Athis/is/a/test* an.

Hilfsprogramme für URI und Navigationszustand

Verwenden Sie NavigationManager, um URIs und die Navigation im C#-Code zu verwalten. NavigationManager stellt das Ereignis und die Methoden bereit, die in der folgenden Tabelle aufgeführt sind.

Member Beschreibung
Uri Ruft den aktuellen absoluten URI ab.
BaseUri Ruft den Basis-URI (mit einem nachgestellten Schrägstrich) ab, der relativen URI-Pfaden vorangestellt werden kann, um einen absoluten URI zu erhalten. In der Regel entspricht BaseUri dem Attribut href im Element <base> des Dokuments (Speicherort des <head>-Inhalts).
NavigateTo Navigiert zum angegebenen URI. Bei forceLoad lautet der Wert false:
  • Die erweiterte Navigation ist unter der aktuellen URL verfügbar, und die erweiterte Blazor-Navigation ist aktiviert.
  • Andernfalls lädt Blazor die Seite für die angeforderte URL vollständig neu.
Bei forceLoad lautet der Wert true:
  • Clientseitiges Routing wird umgangen.
  • Der Browser ist gezwungen, die neue Seite vom Server zu laden, unabhängig davon, ob der URI normalerweise vom clientseitigen, interaktiven Router verarbeitet wird oder nicht.

Weitere Informationen finden Sie im Abschnitt Erweiterte Navigation und Formularverarbeitung.

Wenn replace den Wert true hat, wird der aktuelle URI im Browserverlauf ersetzt, anstatt einen neuen URI auf den Verlaufsstapel zu pushen.

LocationChanged Ein Ereignis, das ausgelöst wird, wenn sich die Navigationsposition geändert hat. Weitere Informationen finden Sie im Abschnitt Positionsänderungen.
ToAbsoluteUri Konvertiert einen relativen URI in einen absoluten URI.
ToBaseRelativePath Konvertiert auf der Grundlage des Basis-URI der App einen absoluten URI in einen URI relativ zum Präfix des Basis-URI. Ein Beispiel finden Sie im Abschnitt Erzeugen eines URI relativ zum Basis-URI-Präfix.
RegisterLocationChangingHandler Registriert einen Handler zum Verarbeiten eingehender Navigationsereignisse. Beim Aufrufen von NavigateTo wird immer der Handler aufgerufen.
GetUriWithQueryParameter Gibt einen URI zurück, der durch Aktualisieren von NavigationManager.Uri erstellt wird, wobei ein einzelner Parameter hinzugefügt, aktualisiert oder entfernt wurde. Weitere Informationen finden Sie im Abschnitt Abfragezeichenfolgen.
Member Beschreibung
Uri Ruft den aktuellen absoluten URI ab.
BaseUri Ruft den Basis-URI (mit einem nachgestellten Schrägstrich) ab, der relativen URI-Pfaden vorangestellt werden kann, um einen absoluten URI zu erhalten. In der Regel entspricht BaseUri dem Attribut href im Element <base> des Dokuments (Speicherort des <head>-Inhalts).
NavigateTo Navigiert zum angegebenen URI. Bei forceLoad lautet der Wert true:
  • Clientseitiges Routing wird umgangen.
  • Der Browser ist gezwungen, die neue Seite vom Server zu laden, unabhängig davon, ob der URI normalerweise vom clientseitigen Router verarbeitet wird oder nicht.
Wenn replace den Wert true hat, wird der aktuelle URI im Browserverlauf ersetzt, anstatt einen neuen URI auf den Verlaufsstapel zu pushen.
LocationChanged Ein Ereignis, das ausgelöst wird, wenn sich die Navigationsposition geändert hat. Weitere Informationen finden Sie im Abschnitt Positionsänderungen.
ToAbsoluteUri Konvertiert einen relativen URI in einen absoluten URI.
ToBaseRelativePath Konvertiert auf der Grundlage des Basis-URI der App einen absoluten URI in einen URI relativ zum Präfix des Basis-URI. Ein Beispiel finden Sie im Abschnitt Erzeugen eines URI relativ zum Basis-URI-Präfix.
RegisterLocationChangingHandler Registriert einen Handler zum Verarbeiten eingehender Navigationsereignisse. Beim Aufrufen von NavigateTo wird immer der Handler aufgerufen.
GetUriWithQueryParameter Gibt einen URI zurück, der durch Aktualisieren von NavigationManager.Uri erstellt wird, wobei ein einzelner Parameter hinzugefügt, aktualisiert oder entfernt wurde. Weitere Informationen finden Sie im Abschnitt Abfragezeichenfolgen.
Member Beschreibung
Uri Ruft den aktuellen absoluten URI ab.
BaseUri Ruft den Basis-URI (mit einem nachgestellten Schrägstrich) ab, der relativen URI-Pfaden vorangestellt werden kann, um einen absoluten URI zu erhalten. In der Regel entspricht BaseUri dem Attribut href im Element <base> des Dokuments (Speicherort des <head>-Inhalts).
NavigateTo Navigiert zum angegebenen URI. Bei forceLoad lautet der Wert true:
  • Clientseitiges Routing wird umgangen.
  • Der Browser ist gezwungen, die neue Seite vom Server zu laden, unabhängig davon, ob der URI normalerweise vom clientseitigen Router verarbeitet wird oder nicht.
Wenn replace den Wert true hat, wird der aktuelle URI im Browserverlauf ersetzt, anstatt einen neuen URI auf den Verlaufsstapel zu pushen.
LocationChanged Ein Ereignis, das ausgelöst wird, wenn sich die Navigationsposition geändert hat. Weitere Informationen finden Sie im Abschnitt Positionsänderungen.
ToAbsoluteUri Konvertiert einen relativen URI in einen absoluten URI.
ToBaseRelativePath Konvertiert auf der Grundlage des Basis-URI der App einen absoluten URI in einen URI relativ zum Präfix des Basis-URI. Ein Beispiel finden Sie im Abschnitt Erzeugen eines URI relativ zum Basis-URI-Präfix.
GetUriWithQueryParameter Gibt einen URI zurück, der durch Aktualisieren von NavigationManager.Uri erstellt wird, wobei ein einzelner Parameter hinzugefügt, aktualisiert oder entfernt wurde. Weitere Informationen finden Sie im Abschnitt Abfragezeichenfolgen.
Member Beschreibung
Uri Ruft den aktuellen absoluten URI ab.
BaseUri Ruft den Basis-URI (mit einem nachgestellten Schrägstrich) ab, der relativen URI-Pfaden vorangestellt werden kann, um einen absoluten URI zu erhalten. In der Regel entspricht BaseUri dem Attribut href im Element <base> des Dokuments (Speicherort des <head>-Inhalts).
NavigateTo Navigiert zum angegebenen URI. Bei forceLoad lautet der Wert true:
  • Clientseitiges Routing wird umgangen.
  • Der Browser ist gezwungen, die neue Seite vom Server zu laden, unabhängig davon, ob der URI normalerweise vom clientseitigen Router verarbeitet wird oder nicht.
LocationChanged Ein Ereignis, das ausgelöst wird, wenn sich die Navigationsposition geändert hat.
ToAbsoluteUri Konvertiert einen relativen URI in einen absoluten URI.
ToBaseRelativePath Konvertiert auf der Grundlage des Basis-URI der App einen absoluten URI in einen URI relativ zum Präfix des Basis-URI. Ein Beispiel finden Sie im Abschnitt Erzeugen eines URI relativ zum Basis-URI-Präfix.

Standortänderungen

Für das LocationChanged-Ereignis bietet LocationChangedEventArgs die folgenden Informationen zu Navigationsereignissen:

Die folgende Komponente führt folgende Aktionen aus:

  • Sie navigiert zur Counter-Komponente der App (Counter.razor), wenn die Schaltfläche mit NavigateTo geklickt wird.
  • Sie reagiert auf das „Location Changed“-Ereignis, indem sie NavigationManager.LocationChanged abonniert.
    • Die Einbindung der HandleLocationChanged-Methode wird aufgehoben, wenn Dispose vom Framework aufgerufen wird. Durch das Aufheben der Einbindung der Methode wird die Garbage Collection für die Komponente ermöglicht.

    • Die Protokollierungsimplementierung protokolliert die folgenden Informationen, wenn die Schaltfläche geklickt wird:

      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

<PageTitle>Navigate</PageTitle>

<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;
}
@page "/navigate"
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation

<PageTitle>Navigate</PageTitle>

<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;
}
@page "/navigate"
@using Microsoft.Extensions.Logging 
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation

<h1>Navigate in component code 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;
    }
}
@page "/navigate"
@using Microsoft.Extensions.Logging 
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation

<h1>Navigate in component code 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;
    }
}
@page "/navigate"
@using Microsoft.Extensions.Logging 
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation

<h1>Navigate in component code 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;
    }
}
@page "/navigate"
@using Microsoft.Extensions.Logging 
@implements IDisposable
@inject ILogger<Navigate> Logger
@inject NavigationManager Navigation

<h1>Navigate in component code 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;
    }
}

Weitere Informationen zur Beseitigung von Komponenten finden Sie unter Lebenszyklus von Razor-Komponenten in ASP.NET Core.

Erweiterte Navigations- und Formularverarbeitung

Dieser Abschnitt gilt für Blazor Web Apps.

Blazor Web Apps können zwei Arten von Routing für Anforderungen zur Seitennavigation und Formularverarbeitung verwenden:

  • Normale Navigation (dokumentübergreifende Navigation): Für die Anforderungs-URL wird ein Neuladen der ganzen Seite ausgelöst.
  • Erweiterte Navigation (Dokumentnavigation): Blazor fängt die Anforderung ab und führt stattdessen eine fetch-Anforderung aus. Blazor fügt den Antwortinhalt in das DOM der Seite ein. Durch die erweiterte Navigation und Formularverarbeitung von Blazor wird vermieden, dass ein Neuladen der ganzen Seite erforderlich ist. Zudem wird der Seitenzustand beibehalten, sodass Seiten schneller geladen werden – normalerweise sogar, ohne die Scrollposition des Benutzers oder der Benutzerin auf der Seite zu verlieren.

Die erweiterte Navigation ist verfügbar, wenn:

  • Das Blazor Web App-Skript (blazor.web.js) wird verwendet, nicht das Blazor Server- Skript (blazor.server.js) oder Blazor WebAssembly-Skript (blazor.webassembly.js).
  • Das Feature ist nicht explizit deaktiviert.
  • Die Ziel-URL befindet sich innerhalb des internen Basis-URI-Bereichs (Basispfad der App).

Wenn serverseitiges Routing und erweiterte Navigation aktiviert sind, werden Positionsänderungshandler nur für die programmgesteuerte Navigation aufgerufen, die von einer interaktiven Runtime initiiert werden. In zukünftigen Releases können zusätzliche Navigationstypen, z. B. Linkklicks, auch Positionsänderungshandler aufrufen.

Bei einer erweiterten Navigation werden in der Regel LocationChanged-Ereignishandler aufgerufen, die bei interaktiven Server- und WebAssembly-Runtimes registriert sind. Es gibt Fälle, in denen Positionsänderungshandler möglicherweise keine erweiterte Navigation abfangen. Beispielsweise könnte ein*e Benutzer*in zu einer anderen Seite wechseln, bevor eine interaktive Runtime verfügbar ist. Daher ist es wichtig, dass die App-Logik nicht auf einen Handler zum Ändern der Position angewiesen ist, da keine Garantie für die Ausführung des Handlers besteht.

Beim Aufruf von NavigateTo:

  • Wenn forceLoad den Wert false aufweist (Standardwert):
    • Die erweiterte Navigation ist unter der aktuellen URL verfügbar, und die erweiterte Blazor-Navigation ist aktiviert.
    • Andernfalls lädt Blazor die Seite für die angeforderte URL vollständig neu.
  • Wenn forceLoad den Wert true aufweist: Blazor lädt die Seite für die angeforderte URL vollständig neu, unabhängig davon, ob die erweiterte Navigation verfügbar ist oder nicht.

Sie können die aktuelle Seite aktualisieren, indem Sie NavigationManager.Refresh(bool forceLoad = false)aufrufen, wodurch bei Bedarf immer eine erweiterte Navigation angewendet wird. Wenn die erweiterte Navigation nicht verfügbar ist, lädt Blazor die ganze Seite neu.

Navigation.Refresh();

Übergeben Sie true an den Parameter forceLoad, damit immer die ganze Seite neu geladen wird, auch wenn die erweiterte Navigation verfügbar ist:

Navigation.Refresh(true);

Die erweiterte Navigation ist standardmäßig aktiviert, kann jedoch mithilfe des HTML-Attributs data-enhance-nav hierarchisch und pro Link gesteuert werden.

In den folgenden Beispielen wird die erweiterte Navigation deaktiviert:

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

Wenn es sich bei dem Ziel um einen Nicht-Blazor-Endpunkt handelt, wird die erweiterte Navigation nicht angewendet, und die Seite wird clientseitig mit JavaScript vollständig neu geladen. Dadurch wird sichergestellt, dass im Framework keine Verwirrung über externe Seiten entsteht, die nicht in eine vorhandene Seite gepatcht werden sollten.

Um die erweiterte Formularverarbeitung zu aktivieren, fügen Sie den Enhance-Parameter zu EditForm-Formularen oder das data-enhance-Attribut zu HTML-Formularen (<form>) hinzu:

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

Die erweiterte Formularverarbeitung ist nicht hierarchisch und wird nicht an untergeordnete Formulare übergeben:

Nicht unterstützt: Sie können die erweiterte Navigation im Vorgängerelement eines Formulars nicht festlegen, um die erweiterte Navigation für das Formular zu aktivieren.

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

Erweiterte Formularbeiträge funktionieren nur mit Blazor-Endpunkten. Das Bereitstellen eines erweiterten Formulars an einen Nicht-Blazor-Endpunkt führt zu einem Fehler.

So deaktivieren Sie die erweiterte Navigation:

  • Entfernen Sie für ein EditForm-Formular den Parameter Enhance aus dem Formularelement (oder legen Sie diesen auf false fest: Enhance="false").
  • Entfernen Sie für einen <form>-HTML-Element den Parameter data-enhance aus dem Formularelement (oder legen Sie diesen auf false fest: data-enhance="false").

Die erweiterte Navigation und Formularverarbeitung von Blazor können dynamische Änderungen am Dokumentobjektmodell (DOM) rückgängig machen, wenn der aktualisierte Inhalt nicht Teil des Serverrenderings ist. Verwenden Sie das data-permanent-Attribut, um den Inhalt eines Elements beizubehalten.

Im folgenden Beispiel wird der Inhalt des <div>-Elements dynamisch durch ein Skript aktualisiert, wenn die Seite geladen wird:

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

Sobald Blazor den Client gestartet hat, können Sie das enhancedload-Ereignis verwenden, um nach erweiterten Seitenaktualisierungen zu lauschen. Das ermöglicht das erneute Anwenden von Änderungen auf das Dokumentobjektmodell (DOM), das möglicherweise durch ein erweitertes Seitenupdate rückgängig gemacht wurde.

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

Informationen zum globalen Deaktivieren der erweiterten Navigation und Formularverarbeitung finden Sie unter ASP.NET Core Blazor-Start.

Die erweiterte Navigation mit statischem serverseitigem Rendering (statisches SSR) erfordert besondere Aufmerksamkeit beim Laden von JavaScript. Weitere Informationen finden Sie unter ASP.NET Core Blazor JavaScript mit statischem serverseitigem Rendering (statisches SSR).

Erzeugen eines URI relativ zum Basis-URI-Präfix

Ausgehend vom Basis-URI der Anwendung konvertiert ToBaseRelativePath einen absoluten URI in einen URI relativ zum Präfix des Basis-URI.

Betrachten Sie das folgende Beispiel:

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

Wenn der Basis-URI der Anwendung https://localhost:8000 lautet, erhalten Sie die folgenden Ergebnisse:

  • Die Übergabe von https://localhost:8000/segment in inputURI liefert als baseRelativePath den Wert segment.
  • Die Übergabe von https://localhost:8000/segment1/segment2 in inputURI liefert als baseRelativePath den Wert segment1/segment2.

Wenn der Basis-URI der App nicht mit dem Basis-URI von inputURI übereinstimmt, wird eine ArgumentException ausgelöst.

Die Übergabe von https://localhost:8001/segment in inputURI führt zur folgenden Ausnahme:

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

NavigationManager verwendet die Verlaufs-API des Browsers, um den Navigationsverlaufstatus zu erhalten, der mit jeder von der App vorgenommenen Speicherortänderung verbunden ist. Der Verlaufsstatus ist besonders bei externen Umleitungsszenarien nützlich, z. B. beim Authentifizieren von Benutzenden mit externen identity-Anbietern. Weitere Informationen dazu finden Sie im Abschnitt Navigationsoptionen.

Übergeben Sie NavigationOptions an NavigateTo, um die folgenden Verhaltensweisen zu steuern:

  • ForceLoad: Umgehen des clientseitigen Routings. Der Browser ist gezwungen, die neue Seite vom Server zu laden, unabhängig davon, ob der URI vom clientseitigen Router verarbeitet wird oder nicht. Der Standardwert ist false.
  • ReplaceHistoryEntry: Ersetzen des aktuellen Eintrags im Verlaufsstapel. Wenn false, wird der neue Eintrag an den Verlaufsstapel angefügt. Der Standardwert ist false.
  • HistoryEntryState: Ruft den Status ab, der an den Verlaufseintrag angefügt werden soll, oder legt ihn fest.
Navigation.NavigateTo("/path", new NavigationOptions
{
    HistoryEntryState = "Navigation state"
});

Weitere Informationen zum Abrufen des Status, der dem Zielverlaufseintrag bei der Verarbeitung von Speicherortänderungen zugeordnet ist, finden Sie im Abschnitt Verarbeiten/Verhindern von Speicherortänderungen.

Abfragezeichenfolgen

Verwenden Sie das -[SupplyParameterFromQuery]Attribut, um anzugeben, dass ein Komponentenparameter aus der Abfragezeichenfolge stammt.

Verwenden Sie das -[SupplyParameterFromQuery]Attribut mit dem -[Parameter]Attribut, um anzugeben, dass ein Komponentenparameter einer routingfähigen Komponente aus der Abfragezeichenfolge stammt.

Hinweis

Komponentenparameter können Abfrageparameterwerte nur in routingfähigen Komponenten mit einer @page-Direktive empfangen.

Nur routingfähige Komponenten empfangen Abfrageparameter direkt, um den Top-Down-Informationsfluss nicht zu unterwandern und um die Reihenfolge der Parameterverarbeitung (sowohl durch das Framework als auch durch die App) zu verdeutlichen. Durch diesen Entwurf werden fast unmerkliche Codefehler vermieden, die dadurch entstehen, dass beim Schreiben des App-Codes eine bestimmte Reihenfolge der Parameterverarbeitung vorausgesetzt wird. Es steht Ihnen frei, benutzerdefinierte kaskadierende Parameter zu definieren oder diese direkt regulären Komponentenparametern zuzuweisen, um Abfrageparameterwerte an nicht routingfähige Komponenten zu übergeben.

Komponentenparameter, die aus der Abfragezeichenfolge bereitgestellt werden, unterstützen die folgenden Typen:

  • bool, DateTime, decimal, double, float, Guid, int, long, string.
  • Nullwerte zulassende Varianten des vorhergehenden Typs.
  • Arrays der genannten Typen, unabhängig davon, ob sie NULL-Werte zulassen oder nicht.

Die richtige kulturinvariante Formatierung wird für den angegebenen Typ angewendet (CultureInfo.InvariantCulture).

Geben Sie die Name-Eigenschaft des Attributs [SupplyParameterFromQuery] an, um einen Abfrageparameternamen zu verwenden, der sich vom Namen des Komponentenparameters unterscheidet. Im folgenden Beispiel lautet der C#-Name des Komponentenparameters {COMPONENT PARAMETER NAME}. Für den Platzhalter {QUERY PARAMETER NAME} wird ein anderer Abfrageparametername angegeben:

Im Gegensatz zu Komponentenparameter-Eigenschaften ([Parameter]) können [SupplyParameterFromQuery]-Eigenschaften zusätzlich zu public mit private gekennzeichnet werden.

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

Genau wie Komponentenparameter-Eigenschaften ([Parameter]) sind [SupplyParameterFromQuery]-Eigenschaften in .NET 6/7 immer public-Eigenschaften. In .NET 8 oder höher können [SupplyParameterFromQuery]-Eigenschaften mit public oder private gekennzeichnet werden.

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

Im folgenden Beispiel mit der URL /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman:

  • Die Filter-Eigenschaft wird in scifi stars aufgelöst.
  • Die Page-Eigenschaft wird in 3 aufgelöst.
  • Das Stars-Array wird aus den Abfrageparametern mit den Namen star (Name = "star") aufgefüllt und in LeVar Burton und Gary Oldman aufgelöst.

Hinweis

Die Abfragezeichenfolgenparameter in der folgenden Routingseitenkomponente funktionieren auch in einer nicht routingfähigen Komponente ohne Anweisung @page (z. B. Search.razor für eine freigegebene Search-Komponente, die in anderen Komponenten verwendet wird).

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

Verwenden Sie GetUriWithQueryParameter, um einen oder mehrere Abfrageparameter für die aktuelle URL hinzuzufügen, zu ändern oder zu entfernen:

@inject NavigationManager Navigation

...

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

Im vorherigen Beispiel:

  • Der {NAME}-Platzhalter gibt den Namen des Abfrageparameters an. Der {VALUE}-Platzhalter gibt den Wert als unterstützten Typ an. Unterstützte Typen werden weiter unten in diesem Abschnitt aufgeführt.
  • Eine Zeichenfolge wird mit einem einzelnen Parameter zurückgegeben, der der aktuellen URL entspricht:
    • Wird hinzugefügt, wenn der Abfrageparametername in der aktuellen URL nicht vorhanden ist.
    • Wird auf den angegebenen Wert aktualisiert, wenn der Abfrageparameter in der aktuellen URL vorhanden ist.
    • Wird entfernt, wenn der Typ des angegebenen Werts NULL-Werte zulässt und der Wert null ist.
  • Die richtige kulturinvariante Formatierung wird für den angegebenen Typ angewendet (CultureInfo.InvariantCulture).
  • Name und Wert des Abfrageparameters sind URL-codiert.
  • Alle Werte mit übereinstimmendem Abfrageparameternamen werden ersetzt, wenn mehrere Instanzen des Typs vorhanden sind.

Rufen Sie GetUriWithQueryParameters auf, um einen aus Uri erstellten URI zu erstellen, wobei mehrere Parameter hinzugefügt, aktualisiert oder entfernt wurden. Für jeden Wert verwendet das Framework value?.GetType(), um den Laufzeittyp für jeden Abfrageparameter zu bestimmen, und wählt die richtige kulturinvariante Formatierung aus. Das Framework löst bei nicht unterstützten Typen einen Fehler aus.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameters({PARAMETERS})

Der Platzhalter {PARAMETERS} ist ein IReadOnlyDictionary<string, object>.

Übergeben Sie eine URI-Zeichenfolge an GetUriWithQueryParameters, um einen neuen URI aus einem bereitgestellten URI generieren, wobei mehrere Parameter hinzugefügt, aktualisiert oder entfernt wurden. Für jeden Wert verwendet das Framework value?.GetType(), um den Laufzeittyp für jeden Abfrageparameter zu bestimmen, und wählt die richtige kulturinvariante Formatierung aus. Das Framework löst bei nicht unterstützten Typen einen Fehler aus. Unterstützte Typen werden weiter unten in diesem Abschnitt aufgeführt.

@inject NavigationManager Navigation

...

Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
  • Der Platzhalter {URI} ist der URI mit oder ohne Abfragezeichenfolge.
  • Der Platzhalter {PARAMETERS} ist ein IReadOnlyDictionary<string, object>.

Unterstützte Typen sind identisch mit unterstützten Typen für Routeneinschränkungen:

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

Unter anderem unterstützte Typen:

  • Nullwerte zulassende Varianten des vorhergehenden Typs.
  • Arrays der genannten Typen, unabhängig davon, ob sie NULL-Werte zulassen oder nicht.

Warnung

Mit standardmäßiger aktivierter Komprimierung vermeiden Sie die Erstellung sicherer (authentifizierter/autorisierter) serverseitiger Komponenten, die Daten aus nicht vertrauenswürdigen Quellen rendern. Nicht vertrauenswürdige Quellen umfassen Routenparameter, Abfragezeichenfolgen, Daten aus JS-Interoperabilität und andere Datenquellen, die ein Drittbenutzer steuern kann (Datenbanken, externe Dienste). Weitere Informationen finden Sie unter ASP.NET Core BlazorSignalR Anleitungen und Anleitung zur Risikominderung für ASP.NET Core Blazor interaktives serverseitiges Rendering.

Abfrageparameterwert ersetzen, wenn der Parameter vorhanden ist

Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
Aktuelle URL Generierte 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

Abfrageparameter und -wert anfügen, wenn der Parameter nicht vorhanden ist

Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
Aktuelle URL Generierte 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

Abfrageparameter ersetzen, wenn der Parameterwert null ist

Navigation.GetUriWithQueryParameter("full name", (string)null)
Aktuelle URL Generierte 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/

Abfrageparameter hinzufügen, aktualisieren und entfernen

Siehe folgendes Beispiel:

  • name wird entfernt, sofern vorhanden.
  • age wird mit dem Wert 25 (int) hinzugefügt, falls nicht vorhanden. Wenn vorhanden, wird age auf den Wert 25 aktualisiert.
  • eye color wird hinzugefügt oder auf den Wert green aktualisiert.
Navigation.GetUriWithQueryParameters(
    new Dictionary<string, object?>
    {
        ["name"] = null,
        ["age"] = (int?)25,
        ["eye color"] = "green"
    })
Aktuelle URL Generierte 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

Unterstützung für aufzählbare Werte

Siehe folgendes Beispiel:

  • full name wird hinzugefügt oder auf den einzelnen Wert Morena Baccarin aktualisiert.
  • ping-Parameter werden hinzugefügt oder durch 35, 16, 87 und 240 ersetzt.
Navigation.GetUriWithQueryParameters(
    new Dictionary<string, object?>
    {
        ["full name"] = "Morena Baccarin",
        ["ping"] = new int?[] { 35, 16, null, 87, 240 }
    })
Aktuelle URL Generierte 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

Um mit einer hinzugefügten oder geänderten Abfragezeichenfolge zu navigieren, übergeben Sie eine generierte URL an NavigateTo.

Aufrufe im folgenden Beispiel:

  • GetUriWithQueryParameter, um den Abfrageparameter name mit dem Wert Morena Baccarin hinzuzufügen oder zu ersetzen.
  • Ruft NavigateTo auf, um die Navigation zur neuen URL auszulösen.
Navigation.NavigateTo(
    Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));

Die Abfragezeichenfolge einer Anforderung wird von der NavigationManager.Uri-Eigenschaft abgerufen:

@inject NavigationManager Navigation

...

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

Um die Parameter einer Abfragezeichenfolge zu analysieren, besteht ein Ansatz in der Verwendung von URLSearchParams mit JavaScript (JS) Interop:

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

Weitere Informationen zur JavaScript-Isolation mit JavaScript-Modulen finden Sie unter Aufrufen von JavaScript-Funktionen über .NET-Methoden in Blazor in ASP.NET Core.

Hashbasiertes Routing an benannte Elemente

Navigieren Sie über die folgenden Ansätze mithilfe eines hashbasierten Elementverweises (#) zu einem benannten Element. Für Routen zu Elementen innerhalb der Komponente und für Routen zu Elementen in externen Komponenten werden Pfade relativ zum Stamm verwendet. Der führende Schrägstrich (/) ist optional.

Beispiele für jeden der folgenden Ansätze zeigen die Navigation zu einem Element mit dem id-Wert targetElement in der Counter-Komponente:

  • Ankerelement (<a>) mit href:

    <a href="/counter#targetElement">
    
  • NavLink-Komponente mit href:

    <NavLink href="/counter#targetElement">
    
  • Übergabe der relativen URL durch NavigationManager.NavigateTo:

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

Das folgende Beispiel veranschaulicht das hashbasierte Routing zu benannten H2-Überschriften innerhalb einer Komponente und zu externen Komponenten.

Platzieren Sie in den Home- (Home.razor) und Counter-Komponenten (Counter.razor) das folgende Markup für die Navigationsziele am unteren Rand des vorhandenen Komponentenmarkups. <div> erzeugt künstlichen vertikalen Raum, um das Scrollverhalten des Browsers zu veranschaulichen:

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

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

Fügen Sie der App die folgende HashedRouting-Komponente hinzu.

HashedRouting.razor:

@page "/hashed-routing"
@inject NavigationManager Navigation

<PageTitle>Hashed routing</PageTitle>

<h1>Hashed routing to named elements</h1>

<ul>
    <li>
        <a href="/hashed-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="/hashed-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");
    }
}

Benutzerinteraktion mit <Navigating>-Inhalt

Wenn während der Navigation eine erhebliche Verzögerung auftritt, z. B. bei Lazy-Loading-Assemblys in einer Blazor WebAssembly-App oder langsamer Netzwerkverbindung mit einer serverseitigen Blazor-App, kann die Router-Komponente dem oder der Benutzer*in mitteilen, dass ein Seitenübergang auftritt.

Fügen Sie oben in der Komponente, die die Router-Komponente angibt, eine @using-Anweisung für den Microsoft.AspNetCore.Components.Routing-Namespace hinzu:

@using Microsoft.AspNetCore.Components.Routing

Bereitstellen von Inhalten für den Navigating-Parameter für die Anzeige während Seitenübergangsereignissen.

Im Inhalt des Routerelements (<Router>...</Router>):

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

Ein Beispiel, in dem die Navigating-Eigenschaft verwendet wird, finden Sie unter Verzögertes Laden von Assemblys in Blazor WebAssembly in ASP.NET Core.

Behandeln von asynchronen Navigationsereignissen mit OnNavigateAsync

Die Router-Komponente unterstützt ein OnNavigateAsync-Feature. Der OnNavigateAsync-Handler wird aufgerufen, wenn der Benutzer:

  • zum ersten Mal eine Route benutzt, indem er direkt über den Browser dorthin navigiert.
  • Zu einer neuen Route mithilfe eines Links oder eines NavigationManager.NavigateTo-Aufrufs navigiert.
<Router AppAssembly="typeof(App).Assembly" 
    OnNavigateAsync="OnNavigateAsync">
    ...
</Router>

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

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

Ein Beispiel, in dem OnNavigateAsync verwendet wird, finden Sie unter Verzögertes Laden von Assemblys in Blazor WebAssembly in ASP.NET Core.

Beim Vorabrendering auf dem Server wird OnNavigateAsync zweimal ausgeführt:

  • Einmal, wenn die angeforderte Endpunktkomponente zuerst statisch als Teil der Seite gerendert wird.
  • Ein zweites Mal, wenn der Browser die Endpunktkomponente rendert.

Um zu verhindern, dass Entwicklercode in OnNavigateAsync doppelt ausgeführt wird, kann die Routes-Komponente NavigationContext zur Verwendung in der OnAfterRender{Async}-Lebenszyklusmethode speichern, wo firstRender überprüft werden kann. Weitere Informationen finden Sie im Abschnitt Voarabrendern mit JavaScript-Interoperabilität.

Die App-Komponente kann das NavigationContext-Objekt zur Verwendung in OnAfterRender{Async} speichern, um zu verhindern, dass Entwicklercode in OnNavigateAsync zweimal ausgeführt wird. Dort kann firstRender auch überprüft werden. Weitere Informationen finden Sie im Abschnitt Voarabrendern mit JavaScript-Interoperabilität.

Verarbeiten von Abbrüchen in OnNavigateAsync

Das NavigationContext-Objekt, das an den OnNavigateAsync-Rückruf übergeben wird, enthält ein CancellationToken, das beim Auftreten eines neuen Navigationsereignisses festgelegt wird. Der OnNavigateAsync-Rückruf muss ausgelöst werden, wenn dieses Abbruchtoken festgelegt wird, um zu vermeiden, dass der OnNavigateAsync-Rückruf für eine veraltete Navigation weiterhin ausgeführt wird.

Wenn ein Benutzer zu einem Endpunkt navigiert, aber dann sofort zu einem neuen Endpunkt wechselt, sollte die App den OnNavigateAsync-Rückruf für den ersten Endpunkt nicht weiter ausführen.

Im folgenden Beispiel:

  • Das Abbruchtoken wird im Aufruf von PostAsJsonAsync übergeben, der den POST-Vorgang abbrechen kann, wenn der Benutzer vom /about-Endpunkt weg navigiert.
  • Das Abbruchtoken wird während eines Produktvorabrufs festgelegt, wenn der Benutzer vom /store-Endpunkt weg navigiert.
@inject HttpClient Http
@inject ProductCatalog Products

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

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

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

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

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

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

Hinweis

Wenn der Rückruf nicht ausgelöst wird, wenn das Abbruchtoken in NavigationContext abgebrochen wird, kann dies zu unbeabsichtigtem Verhalten führen, z. B. zum Rendern einer Komponente aus einer vorherigen Navigation.

Verarbeiten/Verhindern von Speicherortänderungen

RegisterLocationChangingHandler registriert einen Handler zum Verarbeiten eingehender Navigationsereignisse. Der durch LocationChangingContext bereitgestellte Kontext des Handlers umfasst die folgenden Eigenschaften:

Eine Komponente kann in der OnAfterRender{Async}-Lebenszyklusmethode mehrere Speicherortänderungshandler registrieren. Die Navigation ruft alle Speicherortänderungshandler auf, die für die gesamte App (über mehrere Komponenten hinweg) registriert sind, und eine beliebige interne Navigation führt sie alle parallel aus. Zusätzlich zu NavigateTo werden Handler unter den folgenden Umständen aufgerufen:

  • Wenn interne Links ausgewählt werden, die Links sind, die auf URLs unter dem Basispfad der App verweisen.
  • Beim Navigieren mit den Schaltflächen „Vorwärts“ und „Zurück“ in einem Browser.

Handler werden nur für interne Navigation innerhalb der App ausgeführt. Wenn der Benutzer einen Link auswählt, der zu einer anderen Website navigiert oder die Adressleiste manuell in eine andere Website ändert, werden die Speicherortänderungshandler nicht ausgeführt.

Implementieren Sie IDisposable, und verwerfen Sie registrierte Handler, um ihre Registrierung aufzuheben. Weitere Informationen finden Sie unter Rendering von Razor-Komponenten in ASP.NET Core.

Wichtig

Versuchen Sie nicht, DOM-Bereinigungsaufgaben per JavaScript-Interoperabilität (JS) auszuführen, wenn Positionsänderungen verarbeitet werden. Verwenden Sie das MutationObserver-Muster in JS auf dem Client. Weitere Informationen finden Sie unter JavaScript-Interoperabilität von Blazor in ASP.NET Core (JS-Interoperabilität).

Im folgenden Beispiel wird ein Speicherortänderungshandler für Navigationsereignisse registriert.

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

Da die interne Navigation asynchron abgebrochen werden kann, können mehrere sich überschneidende Aufrufe registrierter Handler auftreten. Beispielsweise können mehrere Handleraufrufe auftreten, wenn der Benutzer die Schaltfläche „Zurück“ auf einer Seite schnell auswählt oder mehrere Links auswählt, bevor eine Navigation ausgeführt wird. Nachfolgend finden Sie eine Zusammenfassung der asynchronen Navigationslogik:

  • Wenn ein Speicherortänderungshandler registriert ist, werden wird die gesamte Navigation anfangs rückgängig gemacht und dann erneut wiedergegeben, wenn die Navigation nicht abgebrochen wird.
  • Wenn sich überschneidende Navigationsanforderungen vorgenommen werden, wird die neueste Anforderung immer frühere Anforderungen abbrechen, was Folgendes bedeutet:
    • Die App kann mehrere Schaltflächenauswahlen von „Zurück“ und „Vorwärts“ als einzelne Auswahl behandeln.
    • Wenn der Benutzer mehrere Links auswählt, bevor die Navigation abgeschlossen ist, bestimmt der letzte ausgewählte Link die Navigation.

Weitere Informationen zum Übergeben von NavigationOptions an NavigateTo, um Einträge und den Status des Navigationsverlaufsstapels zu steuern, finden Sie im Abschnitt Navigationsoptionen.

Weiteren Beispielcode finden Sie in der NavigationManagerComponent in BasicTestApp (dotnet/aspnetcore-Referenzquelle).

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Die NavigationLock-Komponente fängt Navigationsereignisse ab, solange sie gerendert werden, und „sperrt“ damit praktisch jegliche Navigation, bis eine Entscheidung getroffen wurde, fortzufahren oder abzubrechen. Verwenden Sie NavigationLock, wenn das Abfangen der Navigation auf die Lebensdauer einer Komponente begrenzt werden kann.

NavigationLock-Parameter:

  • ConfirmExternalNavigation legt ein Browserdialogfeld fest, um den Benutzer aufzufordern, die externe Navigation zu bestätigen oder abzubrechen. Der Standardwert ist false. Das Anzeigen des Bestätigungsdialogfelds erfordert anfängliche Benutzerinteraktion mit der Seite, bevor die externe Navigation mit der URL in der Adressleiste des Browsers ausgelöst wird. Weitere Informationen zur Interaktionsanforderung finden Sie unter Fenster: beforeunload-Ereignis (MDN-Dokumentation).
  • OnBeforeInternalNavigation legt einen Rückruf für interne Navigationsereignisse fest.

In der folgenden NavLock-Komponente:

  • Ein Versuch, dem Link zur Website von Microsoft zu folgen, muss vom Benutzer bestätigt werden, bevor die Navigation zu https://www.microsoft.com erfolgreich ist.
  • PreventNavigation wird aufgerufen, um die Navigation zu verhindern, wenn der Benutzer es ablehnt, die Navigation über einen JavaScript (JS) Interop-Aufruf zu bestätigen, der das JSconfirm-Dialogfeld erzeugt.

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

Weiteren Beispielcode finden Sie in der ConfigurableNavigationLock-Komponente in BasicTestApp (dotnet/aspnetcore-Referenzquelle).

Verwenden Sie bei der Erstellung von Navigationslinks eine NavLink-Komponente anstelle von HTML-Hyperlinkelementen (<a>). Eine NavLink-Komponente verhält sich wie ein <a>-Element, abgesehen davon, dass sie eine active-CSS-Klasse umschaltet, je nachdem, ob das href-Element mit der aktuellen URL übereinstimmt. Die active-Klasse zeigt einem Benutzer auf, welche Seite unter den angezeigten Navigationslinks aktiv ist. Optional können Sie NavLink.ActiveClass einen CSS-Klassennamen zuweisen, um eine benutzerdefinierte CSS-Klasse auf den gerenderten Link anzuwenden, wenn die aktuelle Route mit href übereinstimmt.

Es gibt zwei NavLinkMatch-Optionen, die Sie dem Match-Attribut des <NavLink>-Elements zuweisen können:

Im vorangegangenen Beispiel entspricht HomeNavLinkhref="" der home -URL und erhält nur die CSS-Klasse active im Standard-Basispfad der App (/). Die zweite NavLink-Komponente empfängt die active-Klasse, wenn der Benutzer eine beliebige URL mit einem component-Präfix aufruft (z. B. /component und /component/another-segment).

Zusätzliche NavLink-Komponentenattribute werden an das gerenderte Ankertag weitergegeben. Im folgenden Beispiel schließt die NavLink-Komponente das target-Attribut ein:

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

Das folgende HTML-Markup wird gerendert:

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

Warnung

Aufgrund der Art und Weise, in der Blazor untergeordneten Inhalt rendert, erfordert das Rendern von NavLink-Komponenten in einer for-Schleife eine lokale Indexvariable, wenn die inkrementierende Schleifenvariable im Inhalt der untergeordneten Komponente (NavLink) verwendet wird:

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

Die Verwendung einer Indexvariable in diesem Szenario ist eine Anforderung für jede untergeordnete Komponente, die eine Schleifenvariable im untergeordneten Inhalt verwendet, nicht nur für die NavLink-Komponente.

Alternativ dazu können Sie eine foreach-Schleife mit Enumerable.Range verwenden:

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

NavLink Komponenteneinträge können dynamisch über Spiegelung aus den Komponenten der App erstellt werden. Im folgenden Beispiel wird der allgemeine Ansatz für weitere Anpassungen veranschaulicht.

Für die folgende Demonstration wird eine einheitliche Standardbenennungskonvention für die App-Komponenten verwendet:

  • Routingfähige Komponentendateinamen verwenden z. B. Pascal case†Pages/ProductDetail.razor.
  • Dateipfade für weiterleitbare Komponenten stimmen mit ihren URLs in Kebab-Schreibweise‡ überein, wobei in der Routenvorlage einer Komponente Bindestriche zwischen Wörtern erscheinen. Beispielsweise wird die Komponente ProductDetail mit der Routenvorlage /product-detail (@page "/product-detail") in einem Browser an der relativen URL /product-detail angefordert.

† Bei der Pascal-Schreibweise (Camel-Case-Schreibweise mit großem Anfangsbuchstaben) werden keine Leerzeichen und Interpunktionszeichen verwendet, und der erste Buchstabe jedes Worts, einschließlich des ersten Worts, ist ein Großbuchstabe.
‡Kebab Case ist eine Benennungskonvention ohne Leerzeichen und Interpunktion, die Kleinbuchstaben und Bindestriche zwischen Wörtern verwendet.

Im Razor Markup der NavMenu Komponente (NavMenu.razor) unter der Standardseite Home werden NavLink Komponenten aus einer Auflistung hinzugefügt:

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

Die GetRoutableComponents Methode im @code Block:

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

Im vorherigen Beispiel werden die folgenden Seiten nicht in die gerenderte Liste der Komponenten eingeschlossen:

  • Home Seite: Die Seite wird separat von den automatisch generierten Links aufgelistet, da sie oben in der Liste angezeigt wird und den Match Parameter festlegen soll.
  • Error Seite: Die Fehlerseite wird nur zum Framework navigiert und sollte nicht aufgelistet werden.

Ein Beispiel für den obigen Code in einer Beispielanwendung, die Sie lokal ausführen können, erhalten Sie in der Blazor Web App- oder Blazor WebAssembly-Beispielanwendung.

Integration von ASP.NET Core-Endpunktrouting

Dieser Abschnitt gilt für Blazor Web Apps, die über eine Leitung betrieben werden.

Dieser Abschnitt gilt für Blazor Server-Apps.

Eine Blazor Web App ist in das ASP.NET Core-Endpunktrouting integriert. Eine ASP.NET Core-App ist so konfiguriert, dass sie eingehende Verbindungen für interaktive Komponenten mit MapRazorComponents in der Program-Datei akzeptiert. Die Standardstammkomponente (erste geladene Komponente) ist die App-Komponente (App.razor):

app.MapRazorComponents<App>();

Blazor Server ist in das ASP.NET Core-Endpunktrouting integriert. Eine ASP.NET Core-App ist so konfiguriert, dass sie eingehende Verbindungen für interaktive Komponenten mit MapBlazorHub in der Program-Datei akzeptiert:

app.UseRouting();

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

Blazor Server ist in das ASP.NET Core-Endpunktrouting integriert. Eine ASP.NET Core-App ist so konfiguriert, dass sie eingehende Verbindungen für interaktive Komponenten mit MapBlazorHub in Startup.Configure akzeptiert.

Die typische Konfiguration ist die Weiterleitung aller Anforderungen an eine Razor-Seite, die als Host für den serverseitigen Teil der Blazor Server-App fungiert. Gemäß der Konvention wird die Hostseite in der Regel im Ordner Pages der App mit _Host.cshtml benannt.

Die in der Hostdatei angegebene Route wird als Fallbackroute bezeichnet, da sie mit einer niedrigen Priorität bei der Routenanpassung arbeitet. Die Ausweichroute wird verwendet, wenn andere Routen nicht passen. Dadurch kann die App andere Controller und Seiten verwenden, ohne das Komponentenrouting in der Blazor Server-App zu beeinträchtigen.

Informationen zum Konfigurieren von MapFallbackToPage für das Serverhosting an einer Nicht-Stamm-URL finden Sie unter Hosten und Bereitstellen von ASP.NET Core Blazor.