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

In diesem Artikel werden die Begriffe Client/clientseitig und Server/serverseitig verwendet, um Speicherorte zu unterscheiden, an denen App-Code ausgeführt wird:

  • Client/clientseitig
    • Interaktives Clientrendering einer Blazor-Web-App. Die Program-Datei ist die Program.cs-Datei des Clientprojekts (.Client). Die Konfiguration des Blazor-Startskripts befindet sich in der App-Komponente (Components/App.razor) des Serverprojekts. Routingfähige Komponenten mit dem Rendermodus „WebAssembly“ oder „Automatisch“, die eine @page-Anweisung enthalten, werden im Ordner Pages des Clientprojekts gespeichert. Speichern Sie nicht routingfähige freigegebene Komponenten je nach Funktion im Stammverzeichnis des .Client-Projekts oder in benutzerdefinierten Ordnern.
    • Eine Blazor WebAssembly-App. Die Program-Datei ist Program.cs. Die Konfiguration des Blazor-Startskripts befindet sich in der wwwroot/index.html-Datei.
  • Server/serverseitig: Interaktives Serverrendering einer Blazor-Web-App. Die Program-Datei ist die Program.cs-Datei des Serverprojekts. Die Konfiguration des Blazor-Startskripts befindet sich in der App-Komponente (Components/App.razor). Nur routingfähige Komponenten mit dem Rendermodus „Server“, die eine @page-Anweisung enthalten, werden im Ordner Components/Pages gespeichert. Nicht routingfähige freigegebene Komponenten werden im Ordner Components des Serverprojekts gespeichert. Erstellen Sie nach Bedarf benutzerdefinierte Ordner je nach Komponentenfunktionalität.
  • Client/clientseitig
    • Das Client-Projekt einer gehosteten Blazor WebAssembly-App.
    • Eine Blazor WebAssembly-App.
    • Die Konfiguration des Blazor-Startskripts befindet sich in der wwwroot/index.html-Datei.
    • Die Program-Datei ist Program.cs.
  • Server/serverseitig
    • Das Server-Projekt einer gehosteten Blazor WebAssembly-App.
    • Eine Blazor Server-App. Die Konfiguration des Blazor-Startskripts befindet sich in Pages/_Host.cshtml.
    • Die Program-Datei ist Program.cs.
  • Client/clientseitig
    • Das Client-Projekt einer gehosteten Blazor WebAssembly-App.
    • Eine Blazor WebAssembly-App.
    • Die Konfiguration des Blazor-Startskripts befindet sich in der wwwroot/index.html-Datei.
    • Die Program-Datei ist Program.cs.
  • Server/serverseitig
    • Das Server-Projekt einer gehosteten Blazor WebAssembly-App.
    • Eine Blazor Server-App. Die Konfiguration des Blazor-Startskripts befindet sich in Pages/_Layout.cshtml.
    • Die Program-Datei ist Program.cs.
  • Client/clientseitig
    • Das Client-Projekt einer gehosteten Blazor WebAssembly-App.
    • Eine Blazor WebAssembly-App.
    • Die Konfiguration des Blazor-Startskripts befindet sich in der wwwroot/index.html-Datei.
    • Die Program-Datei ist Program.cs.
  • Server/serverseitig
    • Das Server-Projekt einer gehosteten Blazor WebAssembly-App.
    • Eine Blazor Server-App. Die Konfiguration des Blazor-Startskripts befindet sich in Pages/_Host.cshtml.
    • Die Program-Datei ist Program.cs.

Wichtig

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

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"

<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

Dieser Abschnitt gilt nur für Blazor WebAssembly-Apps. Blazor-Web-Apps verwenden die NotFound-Vorlage (<NotFound>...</NotFound>) nicht. Die Vorlage wird jedoch aus Gründen der Abwärtskompatibilität unterstützt, um Breaking Changes im Framework zu vermeiden. Blazor-Web-Apps verarbeiten in der Regel fehlerhafte URL-Anforderungen, indem entweder die integrierte 404-Benutzeroberfläche des Browsers angezeigt oder eine benutzerdefinierte 404-Seite vom ASP.NET Core-Server über ASP.NET Core Middleware zurückgegeben wird (z. B. UseStatusCodePagesWithRedirects / API-Dokumentation).

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 in der NotFound-Vorlage der Router-Komponente fest:

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

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

Weiterleiten an Komponenten aus mehreren Assemblys

Verwenden Sie den AdditionalAssemblies-Parameter, um zusätzliche Assemblys anzugeben, die die Router-Komponente bei der Suche nach für das Routing geeigneten Komponenten beachten soll. Zusätzliche Assemblys werden neben der für AppAssembly angegebenen Assembly gescannt. Im folgenden Beispiel ist Component1 eine für das Routing geeignete Komponente, die in einer Komponentenklassenbibliothek definiert ist, auf die verwiesen wird. Im folgenden AdditionalAssemblies-Beispiel wird Routing für Component1 unterstützt.

<Router
    AppAssembly="@typeof(App).Assembly"
    AdditionalAssemblies="new[] { typeof(Component1).Assembly }">
    @* ... Router component elements ... *@
</Router>
<Router
    AppAssembly="@typeof(Program).Assembly"
    AdditionalAssemblies="new[] { typeof(Component1).Assembly }">
    @* ... Router component elements ... *@
</Router>

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 der <h1>-Tags als Blazor is amazing! gerendert.

RouteParameter1.razor:

@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?}"

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

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

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

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

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

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

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

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

    protected override void OnInitialized()
    {
        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 OnInitialized()
    {
        Text = Text ?? "fantastic";
    }
}

Verwenden Sie OnParametersSet anstelle von OnInitialized{Async}, um die App-Navigation zur gleichen Komponente mit einem anderen optionalen Parameterwert zuzulassen. Verwenden Sie auf der Grundlage des vorangehenden Beispiels OnParametersSet, wenn der Benutzer in der Lage sein soll, von /route-parameter-2 zu /route-parameter-2/amazing oder von /route-parameter-2/amazing zu /route-parameter-2 zu navigieren:

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

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

<h1>User Id: @Id</h1>

@code {
    [Parameter]
    public int Id { get; set; }
}
@page "/user/{Id:int}"

<h1>User Id: @Id</h1>

@code {
    [Parameter]
    public int Id { get; set; }
}
@page "/user/{Id:int}"

<h1>User Id: @Id</h1>

@code {
    [Parameter]
    public int Id { get; set; }
}
@page "/user/{Id:int}"

<h1>User Id: @Id</h1>

@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} CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} Nein
int {id:int} 123456789, -123456789 Ja
long {ticks:long} 123456789, -123456789 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; }
}

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

Fügen Sie für eine serverseitige Konfiguration, die Anforderungen mit einem Punkt im param-Routenparameter weiterleitet, mit dem optionalen Parameter in der Datei Program eine Ausweichseiten-Routenvorlage hinzu:

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

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

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

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

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 eine erweiterte Navigation für interaktives Clientrouting verfügbar ist, durchläuft die Navigation immer den interaktiven clientseitigen Router. Dieser Punkt ist nur in einem ungewöhnlichen Szenario relevant, in dem ein interaktiver <Router> in einem serverseitigen gerenderten <Router> geschachtelt ist. In diesem Fall hat der interaktive Router Vorrang beim Verarbeiten der Navigation, sodass die erweiterte Navigation nicht verwendet wird, da es sich um ein serverseitiges Routingfeature handelt.

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

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

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/'.'

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"
@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.

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 Benutzern mit externen Identitätsanbietern. 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:

[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
[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]
    public string? Filter { get; set; }

    [SupplyParameterFromQuery]
    public int? Page { get; set; }

    [SupplyParameterFromQuery(Name = "star")]
    public 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 NavigationManager.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 NavigationManager.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.

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

Die Router-Komponente zeigt dem Benutzer, dass ein Seitenübergang erfolgt.

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

Fügen Sie der Komponente ein <Navigating>-Tag mit Markup für die Anzeige während Seitenübergangsereignissen hinzu. Weitere Informationen finden Sie unter Navigating (in der API-Dokumentation).

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 OnNavigateAsynczweimal ausgeführt:

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

Die Routes-Komponente kann das NavigationContext-Objekt zur Verwendung in OnAfterRender{Async} speichern, um zu verhindern, dass Entwicklercode in OnNavigateAsync zweimal ausgeführt wird. Dort kann das firstRender-Objekt auch überprüft werden. Weitere Informationen finden Sie unter Voarabrendering mit JavaScript-Interop im Artikel Blazor-Lebenszyklus.

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 unter Voarabrendering mit JavaScript-Interop im Artikel Blazor-Lebenszyklus.

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 mehrere Speicherortänderungshandler in ihren OnAfterRender- oder OnAfterRenderAsync-Methoden 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"
@inject NavigationManager Navigation
@implements IDisposable

<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 vorherigen Beispiel entspricht HomeNavLinkhref="" der Home-URL und empfängt nur die CSS-Klasse active im Standardbasispfad 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 = 0; c < 10; c++)
{
    var current = c;
    <li ...>
        <NavLink ... href="@c">
            <span ...></span> @current
        </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(0,10))
{
    <li ...>
        <NavLink ... href="@c">
            <span ...></span> @c
        </NavLink>
    </li>
}

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 standardmäßige Stammkomponente 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.