ASP.NET Core の Blazor ルーティングとナビゲーション
注意
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、「.NET および .NET Core サポート ポリシー」を参照してください。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 8 バージョンを参照してください。
この記事では、Blazor アプリの要求ルーティングを管理する方法と、NavLink コンポーネントを使用してナビゲーション リンクを作成する方法について説明します。
重要
この記事全体のコード例では、Navigation
で呼び出されるメソッドを示します。これはクラスとコンポーネントに挿入される NavigationManager です。
静的ルーティングと対話型ルーティング
このセクションは Blazor Web App に適用されます。
プリレンダリングが有効な場合、Blazor ルーター (Router
コンポーネント、Routes.razor
内の <Router>
) は、静的サーバー側レンダリング (静的 SSR) 中にコンポーネントへの静的ルーティングを実行します。 この種類のルーティングは、"静的ルーティング" と呼ばれます。
対話型レンダリング モードが Routes
コンポーネントに割り当てられると、Blazor ルーターは、サーバー上での静的ルーティングを使用する静的 SSR の後に対話形式になります。 この種類のルーティングは、"対話型ルーティング" と呼ばれます。
静的ルーターはエンドポイント ルーティングと HTTP 要求パスを使用して、レンダリングするコンポーネントを決定します。 ルーターは対話形式になると、ドキュメントの URL (ブラウザーのアドレス バー内の URL) を使用して、レンダリングするコンポーネントを決定します。 つまり対話型ルーターは、ドキュメントの URL が別の有効な内部 URL に動的に変更された場合、どのコンポーネントをレンダリングするかを動的に変更できます。しかもそれを、新しいページ コンテンツをフェッチする HTTP 要求を実行せずに行うことができます。
また、対話型ルーティングでは、新しいページ コンテンツが通常のページ要求でサーバーから要求されないため、プリレンダリングも防止されます。 詳細については、「ASP.NET Core Razor のプリレンダリングとコンポーネント」をご覧ください。
ルート テンプレート
Router コンポーネントは、Razor コンポーネントへのルーティングを可能にし、アプリの Routes
コンポーネント (Components/Routes.razor
) に配置されています。
@page
ディレクティブ を含む Razor コンポーネント (.razor
) がコンパイルされると、生成されたコンポーネント クラスに、コンポーネントのルート テンプレートを指定する RouteAttribute が指定されます。
アプリが起動すると、Router の AppAssembly
として指定されたアセンブリがスキャンされ、RouteAttribute を持つアプリのコンポーネントのルート情報が収集されます。
実行時に、RouteView コンポーネントは、
必要に応じて、@layout
ディレクティブ を使用してレイアウトを指定しないコンポーネントに対して、レイアウト クラスで DefaultLayout パラメーターを指定します。 フレームワークの Blazor プロジェクト テンプレートによって、MainLayout
コンポーネント (MainLayout.razor
) が、アプリの既定のレイアウトとして指定されます。 レイアウトについて詳しくは、「ASP.NET Core Blazor のレイアウト」をご覧ください。
コンポーネントにより、複数の @page
ディレクティブ を使用する複数のルート テンプレートがサポートされます。 次のコンポーネントの例では、/blazor-route
と /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>
重要
URL が正しく解決されるように、アプリには <base>
タグを含め (<head>
コンテンツの場所)、href
属性でアプリのベース パスを指定する必要があります。 詳細については、「ASP.NET Core Blazor のホストと展開」を参照してください。
ルート テンプレートを @page
ディレクティブを使用して文字列リテラルとして指定する代わりに、定数ベースのルート テンプレートを @attribute
ディレクティブと共に指定できます。
次の例では、コンポーネント内の @page
ディレクティブが @attribute
ディレクティブと Constants.CounterRoute
の定数ベースのルート テンプレートに置き換えられます。これは、アプリ内の別の場所で "/counter
" に設定されています。
- @page "/counter"
+ @attribute [Route(Constants.CounterRoute)]
メモ
ASP.NET Core 5.0.1 のリリースと、その他の 5.x リリースでは、Router
コンポーネントに @true
に設定された PreferExactMatches
パラメーターが含まれています。 詳細については、「ASP.NET Core 3.1 から 5.0 への移行」を参照してください。
ナビゲーション時に要素にフォーカスを合わせる
FocusOnNavigate コンポーネントでは、あるページから別のページに移動した後、CSS セレクターに基づいて要素に UI フォーカスを設定します。
<FocusOnNavigate RouteData="routeData" Selector="h1" />
Router コンポーネントが新しいページに移動すると、FocusOnNavigate コンポーネントによってページの最上位ヘッダー (<h1>
) にフォーカスが設定されます。 これは、スクリーン リーダーを使用する際にページ ナビゲーションが読み上げられるようにするための一般的な方法です。
コンテンツが見つからないときにカスタム コンテンツを提供する
Router コンポーネントを使用すると、要求されたルートでコンテンツが見つからない場合に、アプリでカスタム コンテンツを指定できます。
Router コンポーネントの NotFound パラメーターのカスタム コンテンツを設定します。
<Router ...>
...
<NotFound>
...
</NotFound>
</Router>
他の対話型コンポーネントなど、NotFound パラメータのコンテンツとして任意の項目がサポートされます。 NotFound コンテンツに既定のレイアウトを適用するには、「ASP.NET Core Blazor のレイアウト」をご覧ください。
重要
Blazor Web App では NotFound パラメータ (<NotFound>...</NotFound>
マークアップ) は使用しませんが、フレームワークの破壊的変更を回避するため、下位互換性の目的でこのパラメータがサポートされています。 サーバー側の ASP.NET Core ミドルウェア パイプラインは、サーバー上の要求を処理します。 サーバー側の手法を使用して、不適切な要求を処理してください。 詳細については、「ASP.NET Core Blazor レンダリング モード」を参照してください。
複数のアセンブリからコンポーネントにルーティングする
このセクションは Blazor Web App に適用されます。
Router コンポーネントのAdditionalAssemblies パラメーターとエンドポイント規則ビルダー AddAdditionalAssemblies を使用して、追加のアセンブリ内のルーティング可能なコンポーネントを検出します。 次の各サブセクションでは、各 API をいつどのように使用するかについて説明します。
静的ルーティング
静的サーバー側レンダリング (静的 SSR) 用の追加アセンブリからルーティング可能なコンポーネントを検出するには、後でルーターが対話型レンダリング用に対話形式になった場合でも、アセンブリを Blazor フレームワークに公開する必要があります。 サーバー プロジェクトの Program
ファイルで MapRazorComponents にチェーン化された追加のアセンブリを使用して、AddAdditionalAssemblies メソッドを呼び出します。
次の例では、プロジェクトの _Imports.razor
ファイルを使用して、BlazorSample.Client
プロジェクトのアセンブリ内のルーティング可能なコンポーネントを含めています。
app.MapRazorComponents<App>()
.AddAdditionalAssemblies(typeof(BlazorSample.Client._Imports).Assembly);
Note
上記のガイダンスは、コンポーネント クラス ライブラリのシナリオにも適用されます。 クラス ライブラリと静的 SSR に関するその他の重要なガイダンスについては、「ASP.NET Core の Razor クラス ライブラリ (RCL) と静的サーバー側レンダリング (静的 SSR)」を参照してください。
対話型ルーティング
対話型レンダリング モードを Routes
コンポーネント (Routes.razor
) に割り当てることで、サーバー上の静的 SSR と静的ルーティングの後に Blazor ルーターを対話形式にすることができます。 たとえば、<Routes @rendermode="InteractiveServer" />
は対話型サーバー側レンダリング (対話型 SSR) を Routes
コンポーネントに割り当てます。 Router
コンポーネントは、Routes
コンポーネントから対話型サーバー側レンダリング (対話型 SSR) を継承します。 ルーターはサーバー上の静的ルーティングの後で対話形式になります。
対話型ルーティングの内部ナビゲーションでは、サーバーに新しいページ コンテンツを要求する必要はありません。 そのため、内部ページ要求ではプリレンダリングは行われません。 詳細については、「ASP.NET Core Razor のプリレンダリングとコンポーネント」をご覧ください。
Routes
コンポーネントがサーバー プロジェクトで定義されている場合は、Router
コンポーネントの AdditionalAssemblies パラメーターに .Client
プロジェクトのアセンブリが含まれている必要があります。 これにより、ルーターは対話形式でレンダリングされたときに正しく動作します。
次の例では、Routes
コンポーネントがサーバー プロジェクト内にあり、BlazorSample.Client
プロジェクトの _Imports.razor
ファイルはルーティング可能なコンポーネントを検索するアセンブリを示しています。
<Router
AppAssembly="..."
AdditionalAssemblies="new[] { typeof(BlazorSample.Client._Imports).Assembly }">
...
</Router>
AppAssembly に指定されたアセンブリに加え、追加のアセンブリがスキャンされます。
Note
上記のガイダンスは、コンポーネント クラス ライブラリのシナリオにも適用されます。
または、ルーティング可能なコンポーネントは、グローバルな対話型 WebAssembly または自動レンダリングが適用された .Client
プロジェクトにのみ存在し、Routes
コンポーネントはサーバー プロジェクトではなく .Client
プロジェクトで定義されます。 この場合、ルーティング可能なコンポーネントを含む外部アセンブリがないため、AdditionalAssemblies の値を指定する必要はありません。
このセクションは Blazor Server アプリに適用されます。
Router コンポーネントのAdditionalAssemblies パラメーターとエンドポイント規則ビルダー AddAdditionalAssemblies を使用して、追加のアセンブリ内のルーティング可能なコンポーネントを検出します。
次の例では、Component1
は、参照されている ComponentLibrary
という名前のコンポーネント クラス ライブラリに定義されたルーティング可能なコンポーネントです。
<Router
AppAssembly="..."
AdditionalAssemblies="new[] { typeof(ComponentLibrary.Component1).Assembly }">
...
</Router>
AppAssembly に指定されたアセンブリに加え、追加のアセンブリがスキャンされます。
ルート パラメーター
ルーターでルート パラメーターを使用すれば、同じ名前の対応するコンポーネント パラメーターを設定できます。 ルート パラメーター名では大文字と小文字は区別されません。 次の例では、text
パラメーターを使用して、ルート セグメントの値をコンポーネントの Text
プロパティに割り当てます。 /route-parameter-1/amazing
に対して要求が行われると、コンテンツは Blazor is amazing!
としてレンダリングされます。
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; }
}
省略可能なパラメーターがサポートされています。 次の例では、省略可能なパラメーター text
を使用して、ルート セグメントの値をコンポーネントの Text
プロパティに割り当てます。 セグメントが存在しない場合、Text
の値は fantastic
に設定されます。
省略可能なパラメーターはサポートされていません。 以下の例では、2 つの @page
ディレクティブが適用されています。 1 つ目のディレクティブでは、パラメーターを指定せずにコンポーネントへの移動を許可します。 2 つ目のディレクティブでは、{text}
ルート パラメーターの値をコンポーネントの Text
プロパティに割り当てます。
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";
}
}
OnParametersSet{Async}
ライフサイクル メソッドの代わりに OnInitialized{Async}
ライフサイクル メソッドが使用されていると、ユーザーが同じコンポーネント内を移動した場合に、fantastic
への Text
プロパティの既定の割り当ては行われません。 たとえば、この状況は、ユーザーが /route-parameter-2/amazing
から /route-parameter-2
に移動するときに発生します。 コンポーネント インスタンスは保持され、新しいパラメーターを受け入れるので、OnInitialized
メソッドが再度呼び出されることはありません。
Note
ルート パラメーターは、クエリ文字列値では使用できません。 クエリ文字列の使用方法については、「クエリ文字列」セクションをご覧ください。
ルート制約
ルート制約は、コンポーネントへのルート セグメントに型の一致を適用します。
次の例で、User
コンポーネントへのルートは、次の場合にのみ一致します。
- 要求 URL に
Id
ルート セグメントが存在する。 Id
セグメントが整数 (int
) 型である。
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; }
}
注意
ルート制約は、クエリ文字列値では使用できません。 クエリ文字列の使用方法については、「クエリ文字列」セクションをご覧ください。
次の表に示すルート制約を使用できます。 インバリアント カルチャと一致するルート制約については、表の下の警告で詳細をご確認ください。
制約 | 例 | 一致の例 | インバリアント カルチャ 一致 |
---|---|---|---|
bool |
{active:bool} |
$ | いいえ |
datetime |
{dob:datetime} |
$ | はい |
decimal |
{price:decimal} |
$ | はい |
double |
{weight:double} |
$ | はい |
float |
{weight:float} |
$ | はい |
guid |
{id:guid} |
$ | いいえ |
int |
{id:int} |
$ | はい |
long |
{ticks:long} |
$ | はい |
nonfile |
{parameter:nonfile} |
BlazorSample.styles.css 以外、favicon.ico 以外 |
はい |
警告
URL の妥当性を検証し、CLR 型 (int
や DateTime など) に変換されるルート制約では、常にインバリアント カルチャが使用されます。 これらの制約では、URL がローカライズ不可であることが前提となります。
ルート制約は、省略可能なパラメーターでも使用できます。 次の例で、Id
は必須ですが、Option
は、省略可能なブール型のルート パラメーターです。
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; }
}
ルート パラメーターでのファイル キャプチャを回避します
次のルート テンプレートでは、オプションのルート パラメーター (Optional
) の静的アセット パスを誤ってキャプチャします。 たとえば、アプリのスタイルシート (.styles.css
) がキャプチャされ、アプリのスタイルが壊れます。
@page "/{optional?}"
...
@code {
[Parameter]
public string? Optional { get; set; }
}
ルート パラメーターをファイル以外のパスのキャプチャに制限するには、ルート テンプレートで:nonfile
制約を使用します。
@page "/{optional:nonfile?}"
ドットを含む URL によるルーティング
"サーバー側" の既定のルート テンプレートでは、ファイルが要求されているドット (.
) が要求 URL の最後のセグメントに含まれていると想定されます。 たとえば、相対 URL /example/some.thing
は、ルーターによって some.thing
という名前のファイルに対する要求として解釈されます。 追加の構成がないと、some.thing
が @page
ディレクティブ を含むコンポーネントにルーティングすることを意図しており、some.thing
がルート パラメーター値である場合に、アプリによって "404 - 見つかりません" という応答が返されます。 ドットが含まれる 1 つまたは複数のパラメーターを指定してルートを使用するには、アプリでカスタム テンプレートを使ってルートを構成する必要があります。
URL の最後のセグメントからルート パラメーターを受け取ることができる次の Example
コンポーネントについて考えてみます。
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; }
}
ホストされている Blazor WebAssembly ソリューションの Server アプリで、param
ルート パラメーターのドットを使って要求をルーティングできるようにするには、Program
ファイルで省略可能なパラメーターを指定してフォールバック ファイル ルート テンプレートを追加します。
app.MapFallbackToFile("/example/{param?}", "index.html");
param
ルート パラメーターのドットを使って要求をルーティングするように Blazor Server アプリを構成するには、Program
ファイルで省略可能なパラメーターを指定してフォールバック ページ ルート テンプレートを追加します。
app.MapFallbackToPage("/example/{param?}", "/_Host");
詳細については、「ASP.NET Core のルーティング」を参照してください。
ホストされている Blazor WebAssembly ソリューションの Server アプリで、param
ルート パラメーターのドットを使って要求をルーティングできるようにするには、Startup.Configure
で省略可能なパラメーターを指定してフォールバック ファイル ルート テンプレートを追加します。
Startup.cs
=
endpoints.MapFallbackToFile("/example/{param?}", "index.html");
param
ルート パラメーターのドットを使って要求をルーティングするように Blazor Server アプリを構成するには、Startup.Configure
で省略可能なパラメーターを指定してフォールバック ページ ルート テンプレートを追加します。
Startup.cs
=
endpoints.MapFallbackToPage("/example/{param?}", "/_Host");
詳細については、「ASP.NET Core のルーティング」を参照してください。
キャッチオールのルート パラメーター
複数のフォルダー境界にまたがるパスをキャプチャするキャッチオール ルート パラメーターが、コンポーネントでサポートされます。
キャッチオールのルート パラメーターは次のとおりです。
- ルート セグメント名と一致する名前が付けられている。 名前付けで大文字と小文字は区別されない。
string
型。 フレームワークによって自動キャストは提供されません。- 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; }
}
ルート テンプレートが /catch-all/{*pageRoute}
の URL /catch-all/this/is/a/test
の場合、PageRoute
の値は this/is/a/test
に設定されます。
キャプチャされたパスのスラッシュとセグメントはデコードされます。 /catch-all/{*pageRoute}
のルート テンプレートでは、URL /catch-all/this/is/a%2Ftest%2A
から this/is/a/test*
が生成されます。
URI およびナビゲーション状態ヘルパー
C# コード内の URI とナビゲーションを管理するには、NavigationManager を使用します。 NavigationManager には、次の表に示すイベントとメソッドがあります。
メンバー | 説明 |
---|---|
Uri | 現在の絶対 URI を取得します。 |
BaseUri | 絶対 URI を生成するために、相対 URI パスの前に付加できるベース URI (末尾のスラッシュを含む) を取得します。 通常、BaseUri はドキュメントの <base> 要素の href 属性に対応します (<head> コンテンツの場所)。 |
NavigateTo | 指定された URI に移動します。 forceLoad が false の場合:
forceLoad が true の場合:
詳しくは、「ナビゲーションとフォーム処理の強化」セクションをご覧ください。
|
LocationChanged | ナビゲーションの場所が変更されたときに発生するイベントです。 詳細については、「場所の変更」セクションを参照してください。 |
ToAbsoluteUri | 相対 URI を絶対 URI に変換します。 |
ToBaseRelativePath | アプリのベース URI に基づいて、絶対 URI をベース URI プレフィックスに対する相対 URI に変換します。 例については、「ベース URI プレフィックスに対する相対 URI を生成する」セクションを参照してください。 |
RegisterLocationChangingHandler |
受信ナビゲーション イベントを処理するハンドラーを登録します。 NavigateTo を呼び出すと、常にハンドラーが呼び出されます。 |
GetUriWithQueryParameter | 1 つのパラメーターを追加、更新、または削除して NavigationManager.Uri を更新することで構築された URI を返します。 詳細については、「クエリ文字列」セクションを参照してください。 |
メンバー | 説明 |
---|---|
Uri | 現在の絶対 URI を取得します。 |
BaseUri | 絶対 URI を生成するために、相対 URI パスの前に付加できるベース URI (末尾のスラッシュを含む) を取得します。 通常、BaseUri はドキュメントの <base> 要素の href 属性に対応します (<head> コンテンツの場所)。 |
NavigateTo | 指定された URI に移動します。 forceLoad が true の場合:
replace が true の場合、履歴スタックに新しい URI をプッシュする代わりに、ブラウザー履歴の現在の URI が置き換えられます。 |
LocationChanged | ナビゲーションの場所が変更されたときに発生するイベントです。 詳細については、「場所の変更」セクションを参照してください。 |
ToAbsoluteUri | 相対 URI を絶対 URI に変換します。 |
ToBaseRelativePath | アプリのベース URI に基づいて、絶対 URI をベース URI プレフィックスに対する相対 URI に変換します。 例については、「ベース URI プレフィックスに対する相対 URI を生成する」セクションを参照してください。 |
RegisterLocationChangingHandler |
受信ナビゲーション イベントを処理するハンドラーを登録します。 NavigateTo を呼び出すと、常にハンドラーが呼び出されます。 |
GetUriWithQueryParameter | 1 つのパラメーターを追加、更新、または削除して NavigationManager.Uri を更新することで構築された URI を返します。 詳細については、「クエリ文字列」セクションを参照してください。 |
メンバー | 説明 |
---|---|
Uri | 現在の絶対 URI を取得します。 |
BaseUri | 絶対 URI を生成するために、相対 URI パスの前に付加できるベース URI (末尾のスラッシュを含む) を取得します。 通常、BaseUri はドキュメントの <base> 要素の href 属性に対応します (<head> コンテンツの場所)。 |
NavigateTo | 指定された URI に移動します。 forceLoad が true の場合:
replace が true の場合、履歴スタックに新しい URI をプッシュする代わりに、ブラウザー履歴の現在の URI が置き換えられます。 |
LocationChanged | ナビゲーションの場所が変更されたときに発生するイベントです。 詳細については、「場所の変更」セクションを参照してください。 |
ToAbsoluteUri | 相対 URI を絶対 URI に変換します。 |
ToBaseRelativePath | アプリのベース URI に基づいて、絶対 URI をベース URI プレフィックスに対する相対 URI に変換します。 例については、「ベース URI プレフィックスに対する相対 URI を生成する」セクションを参照してください。 |
GetUriWithQueryParameter | 1 つのパラメーターを追加、更新、または削除して NavigationManager.Uri を更新することで構築された URI を返します。 詳細については、「クエリ文字列」セクションを参照してください。 |
メンバー | 説明 |
---|---|
Uri | 現在の絶対 URI を取得します。 |
BaseUri | 絶対 URI を生成するために、相対 URI パスの前に付加できるベース URI (末尾のスラッシュを含む) を取得します。 通常、BaseUri はドキュメントの <base> 要素の href 属性に対応します (<head> コンテンツの場所)。 |
NavigateTo | 指定された URI に移動します。 forceLoad が true の場合:
|
LocationChanged | ナビゲーションの場所が変更されたときに発生するイベントです。 |
ToAbsoluteUri | 相対 URI を絶対 URI に変換します。 |
ToBaseRelativePath | アプリのベース URI に基づいて、絶対 URI をベース URI プレフィックスに対する相対 URI に変換します。 例については、「ベース URI プレフィックスに対する相対 URI を生成する」セクションを参照してください。 |
場所の変更
LocationChanged イベントの場合、LocationChangedEventArgs でナビゲーション イベントに関する次の情報が提供されます。
- Location:新しい場所の URL。
- IsNavigationIntercepted:
true
の場合、Blazor によってブラウザーからナビゲーションがインターセプトされました。false
の場合、NavigationManager.NavigateTo によってナビゲーションが発生しました。
次のコンポーネント:
- NavigateTo を使用してボタンが選択されたときに、アプリの
Counter
コンポーネント (Counter.razor
) に移動します。 - NavigationManager.LocationChanged をサブスクライブすることで、場所の変更イベントを処理します。
HandleLocationChanged
メソッドは、Dispose
がフレームワークによって呼び出されると、アンフックになります。 このメソッドをアンフックすることで、コンポーネントのガベージ コレクションが許可されます。ロガーの実装では、ボタンが選択されたときに次の情報をログに記録します。
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;
}
}
コンポーネントの破棄について詳しくは、「ASP.NET Core Razor コンポーネントのライフサイクル」をご覧ください。
ナビゲーションとフォーム処理の強化
このセクションは Blazor Web App に適用されます。
Blazor Web App は、ページ ナビゲーションとフォーム処理の要求に対して 2 種類のルーティングを実行できます。
- 通常のナビゲーション (ドキュメント間のナビゲーション): 要求 URL に対してページ全体の再読み込みがトリガーされます。
- 拡張ナビゲーション (同じドキュメントのナビゲーション): Blazor は要求をインターセプトし、代わりに
fetch
要求を実行します。 その後、Blazor は応答の内容をページの DOM にパッチします。 Blazor の強化されたナビゲーションとフォーム処理により、ページ全体の再読み込みが不要になり、ページの状態が維持されるため、ページの読み込みが速くなり、通常はページ上のユーザーのスクロール位置が失われません。
拡張ナビゲーションは、次の場合に使用できます。
- Blazor Server スクリプト (
blazor.server.js
) または Blazor WebAssembly スクリプト (blazor.webassembly.js
) ではなく、Blazor Web App スクリプト (blazor.web.js
) が使われます。 - この機能が明示的に無効にされることはありません。
- 宛先 URL は、内部ベース URI 空間 (アプリのベース パス) 内にあります。
サーバー側のルーティングと拡張ナビゲーションが有効になっている場合、場所変更ハンドラーは、対話型ランタイムから開始したプログラム ナビゲーションに対してのみ呼び出されます。 今後のリリースでは、リンクをたどるなど、ナビゲーションの種類が追加されると、場所変更ハンドラーが呼び出される可能性もあります。
拡張ナビゲーションが発生すると、通常は、対話型サーバーと WebAssembly ランタイムに登録されている LocationChanged
イベント ハンドラーが呼び出されます。 場所変更ハンドラーが拡張ナビゲーションをインターセプトしない場合があります。 たとえば、対話型ランタイムが使用可能になる前に、ユーザーが別のページに切り替えることがあります。 そのため、場所変更ハンドラーが実行される保証がないため、アプリ ロジックがこのハンドラーの呼び出しに依存しないことが重要です。
NavigateTo を呼び出すとき:
forceLoad
がfalse
の場合、これが既定値です。- また、拡張ナビゲーションは現在の URL で使用でき、Blazor の拡張ナビゲーションがアクティブにされます。
- そうでない場合、Blazor は要求された URL のページ全体の再読み込みを実行します。
forceLoad
がtrue
の場合: 拡張ナビゲーションが使用可能かどうかに関係なく、Blazor は要求された URL のページ全体の再読み込みを実行します。
NavigationManager.Refresh(bool forceLoad = false)
を呼び出すことで、現在のページを更新できます。その場合、常に拡張ナビゲーションが実行されます (使用可能な場合)。 拡張ナビゲーションを使用できない場合、Blazor はページ全体の再読み込みを実行します。
Navigation.Refresh();
拡張ナビゲーションが使用可能な場合でも、true
を forceLoad
パラメーターに渡して、ページ全体の再読み込みが常に実行されるようにします。
Navigation.Refresh(true);
拡張ナビゲーションは既定で有効になっていますが、data-enhance-nav
HTML 属性を使用して階層的およびリンクごとに制御できます。
次の例では、拡張ナビゲーションを無効にします。
<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>
宛先がBlazor 以外のエンドポイントの場合、拡張ナビゲーションは適用されません。クライアント側の JavaScript は、ページ全体の読み込みとして再試行します。 これにより、既存のページに修正プログラムを適用すべきではない外部ページについて、フレームワークに混乱を招くことはありません。
拡張フォーム処理を有効にするには、EditForm フォームに Enhance パラメーターを追加するか、HTML フォーム (<form>
) に data-enhance
属性を追加します。
<EditForm ... Enhance ...>
...
</EditForm>
<form ... data-enhance ...>
...
</form>
拡張フォーム処理は階層的ではなく、次の子フォームにはフローしません。
サポート外: フォームの先祖要素に拡張ナビゲーションを設定して、フォームの拡張ナビゲーションを有効にすることはできません。
<div ... data-enhance ...>
<form ...>
<!-- NOT enhanced -->
</form>
</div>
拡張フォームの投稿は、Blazor エンドポイントでのみ機能します。 拡張フォームを Blazor 以外のエンドポイントに投稿すると、エラーが発生します。
拡張ナビゲーションを無効にするには:
- EditForm の場合は、フォーム要素から Enhance パラメーターを削除します (または、次に
false
を設定します:Enhance="false"
)。 - HTML
<form>
の場合は、フォーム要素からdata-enhance
属性を削除します (または、それをfalse
に設定します:data-enhance="false"
)。
更新された内容がサーバー レンダリングの一部でない場合、Blazor の拡張ナビゲーションとフォーム処理は DOM に対する動的な変更を元に戻す可能性があります。 要素の内容を保持するには、data-permanent
属性を使用します。
次の例では、ページが読み込まれた場合に、<div>
要素の内容がスクリプトによって動的に更新されます。
<div data-permanent>
...
</div>
クライアントで Blazor を開始したら、enhancedload
イベントを使用して拡張ページの更新をリッスンできます。 これにより、強化されたページ更新によって元に戻された可能性がある変更を DOM に再適用できます。
Blazor.addEventListener('enhancedload', () => console.log('Enhanced update!'));
拡張ナビゲーションとグローバルなフォーム処理を無効にするには、「ASP.NET Core Blazor の起動」をご覧ください。
静的サーバー側レンダリング (静的 SSR) による拡張ナビゲーションでは、JavaScript を読み込むときに特別な注意が必要です。 詳細については、「静的サーバー側レンダリング (静的 SSR) を使用した ASP.NET Core Blazor JavaScript」を参照してください。
ベース URI プレフィックスに対する相対 URI を生成する
ToBaseRelativePath は、アプリのベース URI に基づいて、絶対 URI をベース URI プレフィックスに対する相対 URI に変換します。
次に例を示します。
try
{
baseRelativePath = Navigation.ToBaseRelativePath(inputURI);
}
catch (ArgumentException ex)
{
...
}
アプリのベース URI が https://localhost:8000
の場合、次の結果が得られます。
inputURI
でhttps://localhost:8000/segment
を渡すと、segment
のbaseRelativePath
になります。inputURI
でhttps://localhost:8000/segment1/segment2
を渡すと、segment1/segment2
のbaseRelativePath
になります。
アプリのベース URI が inputURI
のベース URI と一致しない場合は、ArgumentException がスローされます。
inputURI
で https://localhost:8001/segment
を渡すと、次の例外が発生します。
System.ArgumentException: 'The URI 'https://localhost:8001/segment' is not contained by the base URI 'https://localhost:8000/'.'
ナビゲーション履歴の状態
NavigationManager では、ブラウザーの History API を使用して、アプリによって行われた各場所の変更に関連付けられているナビゲーション履歴の状態を維持します。 履歴状態の維持は、外部 identity プロバイダーを使用してユーザーを認証する場合など、外部リダイレクト シナリオで特に役立ちます。 詳細については、「ナビゲーション オプション」セクションを参照してください。
ナビゲーション オプション
NavigationOptions を NavigateTo に渡して、次の動作を制御します。
- ForceLoad: クライアント側のルーティングをバイパスし、URI がクライアント側ルーターによって処理されるかどうかにかかわらず、ブラウザーにサーバーから新しいページを読み込むよう強制します。 既定値は
false
です。 - ReplaceHistoryEntry: 履歴スタックの現在のエントリを置き換えます。
false
の場合は、履歴スタックに新しいエントリを追加します。 既定値はfalse
です。 - HistoryEntryState: 履歴エントリに追加する状態を取得または設定します。
Navigation.NavigateTo("/path", new NavigationOptions
{
HistoryEntryState = "Navigation state"
});
場所の変更の処理中にターゲット履歴エントリに関連付けられている状態を取得する方法の詳細については、「場所の変更を処理/防止する」セクション参照してください。
クエリ文字列
[SupplyParameterFromQuery]
属性を使用し、コンポーネント パラメータはクエリ文字列からのものであることを指定します。
[SupplyParameterFromQuery]
属性と共に[Parameter]
属性を使用して、ルーティング可能なコンポーネントのコンポーネント パラメーターは、クエリ文字列からのものであることを指定します。
メモ
コンポーネント パラメーターでは、@page
ディレクティブを使用したルーティング可能なコンポーネントのクエリ パラメーター値のみを受け取ることができます。
トップダウンの情報フローが妨害されないようにし、フレームワークとアプリの両方でパラメーターの処理順序を明確にするために、クエリ パラメーターを直接受け取るのはルーティング可能なコンポーネントのみです。 この設計により、特定のパラメーターの処理順序を想定して記述されたアプリ コードの特定しにくいバグを回避できます。 クエリ パラメーターの値をルーティング可能でないコンポーネントに渡すためには、自由にカスタム カスケード パラメーターを定義したり、通常のコンポーネント パラメーターに直接割り当てたりできます。
クエリ文字列から提供されるコンポーネント パラメーターでは、次の型がサポートされます。
- 上記の型の Null 許容バリアント。
- 上記の型の配列 (Null 許容、Null 非許容どちらでも)。
指定された型に対して、適切なカルチャに依存しない書式設定が適用されます (CultureInfo.InvariantCulture)。
コンポーネント パラメーター名とは異なるクエリ パラメーター名を使用するには、[SupplyParameterFromQuery]
属性の Name プロパティを指定します。 次の例では、コンポーネント パラメーターの C# 名は {COMPONENT PARAMETER NAME}
です。 {QUERY PARAMETER NAME}
プレースホルダーに対して異なるクエリ パラメーター名が指定されています。
コンポーネント パラメータ プロパティ ([Parameter]
) とは異なり、[SupplyParameterFromQuery]
プロパティは public
に加えて private
としてマークできます。
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
private string? {COMPONENT PARAMETER NAME} { get; set; }
コンポーネント パラメーター プロパティ ([Parameter]
) と同様に、[SupplyParameterFromQuery]
プロパティは常に .NET 6/7 で public
プロパティです。 .NET 8 以降では、[SupplyParameterFromQuery]
プロパティは public
または private
としてマークできます。
[Parameter]
[SupplyParameterFromQuery(Name = "{QUERY PARAMETER NAME}")]
public string? {COMPONENT PARAMETER NAME} { get; set; }
URL が /search?filter=scifi%20stars&page=3&star=LeVar%20Burton&star=Gary%20Oldman
である次の例の場合:
Filter
プロパティはscifi stars
に解決されます。Page
プロパティは3
に解決されます。- 配列
Stars
はstar
という名前 (Name = "star"
) のクエリ パラメーターから入力され、LeVar Burton
とGary Oldman
に解決されます。
メモ
次のルーティング可能なページ コンポーネントのクエリ文字列パラメーターは、@page
ディレクティブの必要なく、ルーティング不可能なコンポーネントでも機能します (たとえば、他のコンポーネントで使用されている、共有 Search
コンポーネント用の Search.razor
の場合)。
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; }
}
GetUriWithQueryParameter を使用して、現在の URL の 1 つ以上のクエリ パラメーターを追加、変更、または削除します。
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameter("{NAME}", {VALUE})
前の例の場合:
{NAME}
プレースホルダーでは、クエリ パラメーター名が指定されます。{VALUE}
プレースホルダーでは、サポートされている型として値が指定されます。 サポートされている型の一覧については、このセクションで後述します。- 1 つのパラメーターを含む現在の URL と等しい文字列が返されます。
- クエリ パラメーター名が現在の URL に存在しない場合に追加されます。
- クエリ パラメーターが現在の URL に存在する場合、指定された値に更新されます。
- 指定された値の型が Null 許容で、値が
null
の場合は、削除されます。
- 指定された型に対して、適切なカルチャに依存しない書式設定が適用されます (CultureInfo.InvariantCulture)。
- クエリ パラメーターの名前と値は URL エンコードされます。
- 型のインスタンスが複数ある場合、一致するクエリ パラメーター名を持つすべての値が置き換えられます。
GetUriWithQueryParameters を呼び出して、Uri から構築され、複数のパラメーターが追加、更新、または削除された URI を作成します。 各値について、フレームワークでは value?.GetType()
を使用して各クエリ パラメーターのランタイム型が決定され、適切なカルチャに依存しない書式設定が選択されます。 サポートされていない型に対しては、フレームワークによってエラーがスローされます。
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters({PARAMETERS})
{PARAMETERS}
プレースホルダーは IReadOnlyDictionary<string, object>
です。
URI 文字列を GetUriWithQueryParameters に渡して、指定された URI から、複数のパラメーターを追加、更新、または削除して、新しい URI を生成します。 各値について、フレームワークでは value?.GetType()
を使用して各クエリ パラメーターのランタイム型が決定され、適切なカルチャに依存しない書式設定が選択されます。 サポートされていない型に対しては、フレームワークによってエラーがスローされます。 サポートされている型の一覧については、このセクションで後述します。
@inject NavigationManager Navigation
...
Navigation.GetUriWithQueryParameters("{URI}", {PARAMETERS})
{URI}
プレースホルダーは、クエリ文字列を含む URI、または含まない URI です。{PARAMETERS}
プレースホルダーはIReadOnlyDictionary<string, object>
です。
サポートされている型は、ルート制約でサポートされている型と同じです。
bool
DateTime
decimal
double
float
Guid
int
long
string
サポートされる型には次のようなものがあります。
- 上記の型の Null 許容バリアント。
- 上記の型の配列 (Null 許容、Null 非許容どちらでも)。
警告
既定で有効になっている圧縮を使って、信頼されていないソースからのデータをレンダリングする、セキュリティで保護された (認証済み/承認済み) 対話型サーバー側コンポーネントは作成しないでください。 信頼されていないソースには、ルート パラメータ、クエリ文字列、JS 相互運用からのデータ、サードパーティのユーザーがコントロールできる他のデータ ソース (データベース、外部サービス) が含まれます。 詳細については、「ASP.NET Core BlazorSignalR ガイダンス」と「対話型サーバー側の ASP.NET Core Blazor レンダリングの脅威軽減策に関するガイダンス」を参照してください。
パラメーターが存在する場合にクエリ パラメーター値を置き換える
Navigation.GetUriWithQueryParameter("full name", "Morena Baccarin")
現在の URL | 生成された 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 |
パラメーターが存在しない場合にクエリ パラメーターと値を追加する
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin")
現在の URL | 生成された 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 |
パラメーター値が null
の場合にクエリ パラメーターを削除する
Navigation.GetUriWithQueryParameter("full name", (string)null)
現在の URL | 生成された 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/ |
クエリ パラメーターの追加、更新、削除
次に例を示します。
name
が削除されます (存在する場合)。age
が値25
(int
) で追加されます (存在しない場合)。 存在する場合、age
は値25
に更新されます。eye color
が値green
として追加または更新されます。
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["name"] = null,
["age"] = (int?)25,
["eye color"] = "green"
})
現在の URL | 生成された 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 |
列挙可能な値のサポート
次に例を示します。
full name
が単一の値Morena Baccarin
として追加または更新されます。ping
パラメーターが35
、16
、87
、240
として追加されるか置き換えられます。
Navigation.GetUriWithQueryParameters(
new Dictionary<string, object?>
{
["full name"] = "Morena Baccarin",
["ping"] = new int?[] { 35, 16, null, 87, 240 }
})
現在の URL | 生成された 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 |
追加または変更されたクエリ文字列を使用して移動する
追加または変更されたクエリ文字列を使用して移動するには、生成された URL を NavigateTo に渡します。
次の例では以下を呼び出します。
- GetUriWithQueryParameter を呼び出し、値
Morena Baccarin
を使用してname
クエリ パラメーターを追加または置き換えます。 - NavigateTo を呼び出して、新しい URL へのナビゲーションをトリガーします。
Navigation.NavigateTo(
Navigation.GetUriWithQueryParameter("name", "Morena Baccarin"));
要求のクエリ文字列は、NavigationManager.Uri プロパティから取得されます。
@inject NavigationManager Navigation
...
var query = new Uri(Navigation.Uri).Query;
クエリ文字列のパラメーターを解析するための 1 つの方法は、JavaScript (JS) 相互運用で URLSearchParams
を使用することです。
export createQueryString = (string queryString) => new URLSearchParams(queryString);
JavaScript モジュールを使用した JavaScript の分離について詳しくは、「ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す」をご覧ください。
名前付き要素へのハッシュされたルーティング
要素へのハッシュされた (#
) 参照による次の方法を使って、名前付き要素に移動します。 コンポーネント内の要素へのルートと、外部コンポーネント内の要素へのルートでは、ルート (root) 相対パスが使われます。 先頭のスラッシュ (/
) は省略できます。
次の各方法の例では、Counter
コンポーネント内の id
が targetElement
の要素への移動を示します。
アンカー要素 (
<a>
) とhref
:<a href="/counter#targetElement">
NavLink コンポーネントと
href
:<NavLink href="/counter#targetElement">
NavigationManager.NavigateTo に相対 URL を渡す:
Navigation.NavigateTo("/counter#targetElement");
次の例では、コンポーネント内の名前付きの H2 見出しと外部コンポーネントへの、ハッシュされたルーティングを示します。
Home
(Home.razor
) と Counter
(Counter.razor
) コンポーネントでは、ナビゲーション ターゲットとして機能するように、次のマークアップを既存のコンポーネント マークアップの末尾に配置します。 <div>
では、ブラウザーのスクロール動作を示すために、わざと縦方向のスペースを作成しています。
<div class="border border-info rounded bg-info" style="height:500px"></div>
<h2 id="targetElement">Target H2 heading</h2>
<p>Content!</p>
次の HashedRouting
コンポーネントをアプリに追加します。
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");
}
}
<Navigating>
コンテンツとのユーザー操作
Blazor WebAssembly アプリでのアセンブリの遅延読み込み中や、Blazor サーバー側アプリへの低速なネットワーク接続など、ナビゲーション中に大幅な遅延が発生する場合、Router コンポーネントはページ切り替えが発生していることをユーザーに示すことができます。
Router コンポーネントを指定するコンポーネントの上部に、Microsoft.AspNetCore.Components.Routing 名前空間の @using
ディレクティブを追加します。
@using Microsoft.AspNetCore.Components.Routing
ページ切り替えイベント中に表示するコンテンツを Navigating パラメータに指定します。
ルーター要素コンテンツ (<Router>...</Router>
) は、次のとおりです。
<Navigating>
<p>Loading the requested page…</p>
</Navigating>
Navigating プロパティを使う例については、「ASP.NET Core Blazor WebAssembly でのアセンブリの遅延読み込み」をご覧ください。
OnNavigateAsync
で非同期ナビゲーション イベントを処理する
Router コンポーネントは、OnNavigateAsync 機能をサポートしています。 OnNavigateAsync ハンドラーは、ユーザーが次のことを行った場合に呼び出されます。
- ブラウザー内でルートに直接移動して、初めてアクセスする。
- リンクまたは NavigationManager.NavigateTo 呼び出しを使用して新しいルートに移動する。
<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)
{
...
}
}
OnNavigateAsync を使う例については、「ASP.NET Core Blazor WebAssembly でのアセンブリの遅延読み込み」をご覧ください。
サーバー上でプリレンダリングする場合、OnNavigateAsync が "2 回" 実行されます。
- 1 回目は、要求されたエンドポイント コンポーネントが、最初に静的にレンダリングされるとき。
- 2 回目は、エンドポイント コンポーネントがブラウザーによってレンダリングされるとき。
OnNavigateAsync で開発者コードが 2 回実行されないようにするには、Routes
コンポーネントに、firstRender
をチェックできる OnAfterRender{Async}
ライフサイクル メソッドで使用する NavigationContext を格納します。 詳細については、「JavaScript 相互運用を使用したプリレンダリング」をご覧ください。
OnNavigateAsync で開発者コードが 2 回実行されないようにするには、App
コンポーネントに、OnAfterRender{Async}
で使用する NavigationContext を格納します (firstRender
がチェックされている場合)。 詳細については、「JavaScript 相互運用を使用したプリレンダリング」をご覧ください。
OnNavigateAsync
でキャンセルを処理する
OnNavigateAsync コールバックに渡される NavigationContext オブジェクトには、新しいナビゲーション イベントが発生したときに設定される CancellationToken が含まれています。 このキャンセル トークンが、古いナビゲーションに対して OnNavigateAsync コールバックを継続して実行しないように設定されている場合は、OnNavigateAsync コールバックをスローする必要があります。
ユーザーがエンドポイントに移動したものの、その後すぐに新しいエンドポイントに移動する場合、アプリで最初のエンドポイントの OnNavigateAsync コールバックを実行し続けるべきではありません。
次に例を示します。
- キャンセル トークンは、
PostAsJsonAsync
への呼び出しで渡されます。ユーザーが/about
エンドポイントから離れた場合は、POST が取り消されます。 - ユーザーが
/store
エンドポイントから移動した場合は、製品のプリフェッチ操作中にキャンセル トークンが設定されます。
@inject HttpClient Http
@inject ProductCatalog Products
<Router AppAssembly="typeof(App).Assembly"
OnNavigateAsync="OnNavigateAsync">
...
</Router>
@code {
private async Task OnNavigateAsync(NavigationContext context)
{
if (context.Path == "/about")
{
var stats = new Stats { Page = "/about" };
await Http.PostAsJsonAsync("api/visited", stats,
context.CancellationToken);
}
else if (context.Path == "/store")
{
var productIds = new[] { 345, 789, 135, 689 };
foreach (var productId in productIds)
{
context.CancellationToken.ThrowIfCancellationRequested();
Products.Prefetch(productId);
}
}
}
}
@inject HttpClient Http
@inject ProductCatalog Products
<Router AppAssembly="typeof(Program).Assembly"
OnNavigateAsync="OnNavigateAsync">
...
</Router>
@code {
private async Task OnNavigateAsync(NavigationContext context)
{
if (context.Path == "/about")
{
var stats = new Stats { Page = "/about" };
await Http.PostAsJsonAsync("api/visited", stats,
context.CancellationToken);
}
else if (context.Path == "/store")
{
var productIds = new[] { 345, 789, 135, 689 };
foreach (var productId in productIds)
{
context.CancellationToken.ThrowIfCancellationRequested();
Products.Prefetch(productId);
}
}
}
}
メモ
NavigationContext 内のキャンセル トークンが取り消された場合にスローしないと、前のナビゲーションからのコンポーネントをレンダリングするなど、意図しない動作が発生する可能性があります。
場所の変更を処理/防止する
RegisterLocationChangingHandler では、受信ナビゲーション イベントを処理するハンドラーを登録します。 LocationChangingContext によって提供されるハンドラーのコンテキストには、次のプロパティが含まれます。
- TargetLocation: ターゲットの場所を取得します。
- HistoryEntryState: ターゲット履歴エントリに関連付けられている状態を取得します。
- IsNavigationIntercepted: ナビゲーションがリンクからインターセプトされたかどうかを取得します。
- CancellationToken: ナビゲーションが取り消されたかどうかを判断する CancellationToken を取得します。たとえば、ユーザーが別のナビゲーションをトリガーしたかどうかを判断します。
- PreventNavigation: ナビゲーションが続行されないようにするために呼び出されます。
コンポーネントでは、OnAfterRender{Async}
ライフサイクル メソッドに複数の場所変更ハンドラーを登録できます。 ナビゲーションでは、(複数のコンポーネントにまたがって) アプリ全体に登録されているすべての場所変更ハンドラーを呼び出し、すべての内部ナビゲーションでそれらをすべて並列で実行します。 NavigateTo に加え、次の場合にハンドラーが呼び出されます。
- 内部リンクを選択する場合。これは、アプリのベース パスの下にある URL を指すリンクです。
- ブラウザーの [進む] ボタンと [戻る] ボタンを使用して移動する場合。
ハンドラーは、アプリ内の内部ナビゲーションに対してのみ実行されます。 ユーザーが別のサイトに移動するリンクを選択した場合、またはアドレス バーを別のサイトに手動で変更した場合、場所変更ハンドラーは実行されません。
IDisposable を実装し、登録済みハンドラーを破棄して登録を解除します。 詳しくは、「ASP.NET Core Razor コンポーネントのライフサイクル」をご覧ください。
重要
場所の変更を処理するときは、JavaScript (JS) 相互運用機能を使って DOM のクリーンアップ タスクを実行しないでください。 クライアントの JS で MutationObserver
パターンを使用します。 詳しくは、「ASP.NET Core Blazor JavaScript の相互運用性 (JS 相互運用)」をご覧ください。
次の例では、ナビゲーション イベントの場所変更ハンドラーが登録されています。
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();
}
内部ナビゲーションは非同期的に取り消すことができるため、登録されたハンドラーに対して複数の重複する呼び出しが発生する可能性があります。 たとえば、ユーザーがすぐにページの [戻る] ボタンを選択したり、ナビゲーションが実行される前に複数のリンクを選択したりすると、複数のハンドラー呼び出しが発生することがあります。 非同期ナビゲーション ロジックの概要を以下に示します。
- 場所変更ハンドラーが登録されている場合は、最初にすべてのナビゲーションが元に戻されてから、ナビゲーションが取り消されていない場合は再生されます。
- 重複するナビゲーション要求が行われた場合、最新の要求では常に以前の要求を取り消します。これは、次のことを意味します。
- アプリで、複数の [戻る] と [進む] ボタンの選択が 1 つの選択として扱われる場合があります。
- ナビゲーションが完了する前にユーザーが複数のリンクを選択した場合、最後に選択したリンクによってナビゲーションが決まります。
ナビゲーション履歴スタックのエントリと状態を制御するために NavigateTo に NavigationOptions を渡す方法の詳細については、「ナビゲーション オプション」セクションを参照してください。
その他のコード例については、「BasicTestApp
」(dotnet/aspnetcore
参照ソース) の NavigationManagerComponent
に関するページを参照してください。
注意
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
表示されている限り NavigationLock
コンポーネントはナビゲーション イベントをインターセプトし、続行またはキャンセルの決定が行われるまで、特定のナビゲーションを効果的に "ロック" します。 ナビゲーション インターセプトのスコープをコンポーネントの有効期間に設定できる場合、NavigationLock
を使用します。
NavigationLock パラメーター:
- ConfirmExternalNavigation では、外部ナビゲーションの確認またはキャンセルをユーザーに求めるブラウザー ダイアログを設定します。 既定値は
false
です。 確認ダイアログを表示するには、ブラウザーのアドレス バーの URL を使用して外部ナビゲーションをトリガーする前に、最初にユーザーがページを操作する必要があります。 操作の要件について詳しくは、「Window:beforeunload
イベント」(MDN ドキュメント) を参照してください。 - OnBeforeInternalNavigation では、内部ナビゲーション イベントのコールバックを設定します。
次の NavLock
コンポーネントでは、以下のことを行います。
https://www.microsoft.com
へのナビゲーションを成功させるには、Microsoft の Web サイトに従う試みをユーザーが確認する必要があります。- PreventNavigation は、JS
confirm
ダイアログを生成する JavaScript (JS) 相互運用機能呼び出しによるナビゲーションの確認をユーザーが拒否した場合に、ナビゲーションが発生しないようにするために呼び出されます。
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();
}
}
}
その他のコード例については、「BasicTestApp
」(dotnet/aspnetcore
参照ソース) の ConfigurableNavigationLock
コンポーネントに関するページを参照してください。
NavLink
コンポーネント
ナビゲーション リンクを作成するときは、HTML ハイパーリンク要素 (<a>
) の代わりに NavLink コンポーネントを使用します。 NavLink コンポーネントは <a>
要素のように動作しますが、href
が現在の URL と一致するかどうかに基づいて active
CSS クラスを切り替える点が異なります。 active
クラスは、表示されているナビゲーション リンクの中でどのページがアクティブ ページであるかをユーザーが理解するのに役立ちます。 必要に応じて、CSS クラス名を NavLink.ActiveClass に割り当てて、現在のルートが href
と一致したときに、レンダリングされるリンクにカスタム CSS クラスを適用します。
<NavLink>
要素の Match
属性に割り当てられる 2 つの NavLinkMatch オプションがあります。
- NavLinkMatch.All:NavLink は、現在の URL 全体に一致する場合にアクティブになります。
- NavLinkMatch.Prefix (既定値):NavLink は、現在の URL の任意のプレフィックスに一致する場合にアクティブになります。
前の例では、HomeNavLinkhref=""
は home URL と一致し、アプリの既定のベース パス (/
) でのみ active
CSS クラスを受け取ります。 2 番目の NavLink は、ユーザーが component
プレフィックスを含む任意の URL (/component
や /component/another-segment
など) にアクセスしたときに、active
クラスを受け取ります。
追加の NavLink コンポーネント属性は、レンダリングされるアンカー タグに渡されます。 次の例では、NavLink コンポーネントに target
属性が含まれています。
<NavLink href="example-page" target="_blank">Example page</NavLink>
次の HTML マークアップがレンダリングされます。
<a href="example-page" target="_blank">Example page</a>
警告
Blazor による子コンテンツのレンダリング方法により、for
ループ内の NavLink
コンポーネントのレンダリングでは、インクリメントするループ変数が NavLink
(子) コンポーネントのコンテンツ内で使用されている場合、ローカル インデックス変数が必要になります。
@for (int c = 1; c < 4; c++)
{
var ct = c;
<li ...>
<NavLink ...>
<span ...></span> Product #@ct
</NavLink>
</li>
}
このシナリオでのインデックス変数の使用は、NavLink
コンポーネントだけでなく、子コンテンツでループ変数を使用するすべての子コンポーネントで必須です。
または、Enumerable.Range と共に foreach
ループを使用します。
@foreach (var c in Enumerable.Range(1, 3))
{
<li ...>
<NavLink ...>
<span ...></span> Product #@c
</NavLink>
</li>
}
NavLink コンポーネントのエントリは、リフレクションを介してアプリのコンポーネントから動的に作成できます。 次の例では、さらにカスタマイズするための一般的なアプローチを示します。
次のデモでは、アプリのコンポーネントに一貫した標準の名前付け規則が使用されています。
- ルーティング可能なコンポーネント ファイル名では、Pascal 形式† (例:
Pages/ProductDetail.razor
) が使用されます。 - ルーティング可能なコンポーネント ファイル パスは、コンポーネントのルート テンプレート内の単語間に表示されるハイフン付きのケバブ ケース‡ の URL に一致します。 たとえば、ルート テンプレートが
/product-detail
(@page "/product-detail"
) のProductDetail
コンポーネントは、ブラウザーの相対 URL/product-detail
で要求されます。
† パスカル ケース (大文字のキャメル ケース) は、スペースと句読点を使用せず、大文字の各単語の最初の文字 (最初の単語を含む) を使用する名前付け規則です。
ケバブ ケースは、単語間の小文字とダッシュを使用するスペースと句読点のない名前付け規則です。
既定の Home
ページの NavMenu
コンポーネント (NavMenu.razor
) の Razor マークアップでは、NavLink コンポーネントがコレクションから追加されます。
<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>
@code
ブロックの GetRoutableComponents
メソッド:
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);
上記の例には、コンポーネントの表示されるリストの次のページは含まれていません。
Home
ページ: ページは、自動的に生成されたリンクとは別に一覧表示されます。これは、ページが一覧の上部に表示され、Match
パラメーターが設定される必要があるためです。Error
ページ: エラー ページはフレームワークによってのみナビゲートされ、一覧には表示されません。
ローカルで実行できるサンプル アプリの上記のコードの例については、Blazor Web App または Blazor WebAssembly サンプル アプリを取得します。
ASP.NET Core エンドポイントのルーティングの統合
このセクションは、回線上で動作する Blazor Web App に適用されます。
このセクションは Blazor Server アプリに適用されます。
Blazor Web App は ASP.NET Core エンドポイントのルーティングに統合されています。 ASP.NET Core アプリは、Program
ファイルで MapRazorComponents を使用して、対話型コンポーネントの着信接続を受け入れるように構成されています。 既定のルート コンポーネント (最初に読み込まれるコンポーネント) は、App
コンポーネント (App.razor
) です。
app.MapRazorComponents<App>();
Blazor Server は ASP.NET Core エンドポイントのルーティングに統合されています。 ASP.NET Core アプリは、Program
ファイルで MapBlazorHub を使用して、対話型コンポーネントの着信接続を受け入れるように構成されています。
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
Blazor Server は ASP.NET Core エンドポイントのルーティングに統合されています。 ASP.NET Core アプリは、Startup.Configure
で MapBlazorHub を使用して、対話型コンポーネントの着信接続を受け入れるように構成されています。
一般的な構成は、すべての要求を Razor ページにルーティングすることです。これは、Blazor Server アプリのサーバー側部分のホストとして機能します。 慣例により、"ホスト" のページは通常、アプリの Pages
フォルダーでは _Host.cshtml
という名前になります。
ホスト ファイルに指定されるルートは、ルート照合で低い優先順位で動作するため、フォールバック ルートと呼ばれます。 フォールバック ルートは、他のルートが一致しない場合に使用されます。 これにより、Blazor Server アプリのコンポーネント ルーティングに干渉することなく、他のコントローラーやページをアプリで使用できるようになります。
ルート以外の URL のサーバー ホスト用に MapFallbackToPage を構成する方法については、「ASP.NET Core Blazor のホストと展開」をご覧ください。
ASP.NET Core