ASP.NET Core Razor コンポーネントを MVC または Razor Pages と統合する
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
Razor コンポーネントは、 Razor Pages または MVC アプリに統合できます。 ページまたはビューがレンダリングされるときには、コンポーネントを同時に事前レンダリングすることができます。
重要
ASP.NET Core リリース間でのフレームワークの変更により、この記事のさまざまな手順セットが作成されました。 この記事のガイダンスを使用する前に、この記事の上部にあるドキュメント バージョン セレクターが、アプリに使用する ASP.NET Core のバージョンと一致していることを確認します。
プリレンダリングにより、検索エンジンがページ ランクの計算に使える最初の HTTP 応答の内容がレンダリングされることで、検索エンジンの最適化 (SEO) が向上します。
プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。
- ユーザー要求から直接ルーティング可能なコンポーネント。 訪問者が
@page
ディレクティブを含むコンポーネントのブラウザーで HTTP 要求を行うことができる必要がある場合は、このガイダンスに従ってください。 - ユーザー要求から直接ルーティングできないコンポーネントについては、「ページまたはビューからコンポーネントをレンダリングする」セクションを参照してください。 Component タグ ヘルパーを使用して、アプリが既存のページまたはビューにコンポーネントを埋め込む場合は、このガイダンスに従。
構成
既存の Razor Pages または MVC アプリのページまたはビューにRazor コンポーネントを統合するには、次のガイダンスを使用します。
次の内容の imports ファイルをプロジェクトのルート フォルダーに追加します。
{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に変更します。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using {APP NAMESPACE}
プロジェクトのレイアウト ファイル (Razor Pages アプリの
Pages/Shared/_Layout.cshtml
、または MVC アプリのViews/Shared/_Layout.cshtml
):<head>
要素に次の<base>
タグと HeadOutlet コンポーネント タグ ヘルパーを追加します。<base href="~/" /> <component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" render-mode="ServerPrerendered" />
前の例の
href
値 (アプリ ベースのパス) は、アプリがルート URL パス (/
) に置かれていることを前提としています。 アプリがサブアプリケーションになっている場合は、「ASP.NET Core Blazor のホストと展開」記事の「アプリのベース パス」セクションのガイダンスに従ってください。HeadOutlet コンポーネントは、Razor コンポーネントによって設定されたページタイトル (PageTitle コンポーネント) とその他の head 要素 (HeadContent コンポーネント) の head (
<head>
) コンテンツをレンダリングするために使用されます。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。blazor.server.js
スクリプトの<script>
タグを、Scripts
レンダリング セクション (@await RenderSectionAsync(...)
) の直前に追加します。<script src="_framework/blazor.server.js"></script>
フレームワークによって
blazor.server.js
スクリプトがアプリに追加されます。blazor.server.js
スクリプト ファイルをアプリに手動で追加する必要はありません。
Note
通常、レイアウトは
_ViewStart.cshtml
ファイルを介して読み込まれます。Blazor Server サービスを、サービスの登録先である
Program.cs
に登録します。builder.Services.AddServerSideBlazor();
Blazor ハブ エンドポイントを、ルートがマップされる
Program.cs
のエンドポイントに追加します。MapRazorPages
(Razor Pages) またはMapControllerRoute
(MVC) の呼び出しの後に、次の行を配置します。app.MapBlazorHub();
コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの
Shared
フォルダーにCounter
コンポーネントを追加します。Pages/Shared/Counter.razor
(Razor Pages) またはViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
Razor Pages アプリのプロジェクトの
Index
ページで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをページに埋め込みます。Index
ページが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
MVC:
MVC アプリのプロジェクトの
Index
ビューで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをビューに埋め込みます。Index
ビューが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
詳細については、「ページまたはビューからコンポーネントをレンダリングする」セクションを参照してください。
Razor Pages アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
Razor Pages アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
次の内容の
_Host
ページをプロジェクトに追加します。{APP NAMESPACE}
プレースホルダーをアプリの名前空間に置き換えます。Pages/_Host.cshtml
:@page @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <component type="typeof(App)" render-mode="ServerPrerendered" />
注意
前の例では、HeadOutlet コンポーネントと Blazor スクリプト (
_framework/blazor.server.js
) がアプリのレイアウトによってレンダリングされることを前提としています。 詳細については、「構成」セクションを参照してください。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Program.cs
エンドポイントで、_Host
ページの優先度の低いルートを最後のエンドポイントとして追加します。app.MapFallbackToPage("/_Host");
ルーティング可能なコンポーネントをプロジェクトに追加します。 次の例は、Blazor プロジェクト テンプレート内の
Counter
コンポーネントに基づくRoutableCounter
コンポーネントです。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
MVC アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
次の内容の
_Host
ビューをプロジェクトに追加します。{APP NAMESPACE}
プレースホルダーをアプリの名前空間に置き換えます。Views/Home/_Host.cshtml
:@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <component type="typeof(App)" render-mode="ServerPrerendered" />
注意
前の例では、HeadOutlet コンポーネントと Blazor スクリプト (
_framework/blazor.server.js
) がアプリのレイアウトによってレンダリングされることを前提としています。 詳細については、「構成」セクションを参照してください。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Home コントローラーにアクションを追加します。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
Program.cs
エンドポイントに、_Host
ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。app.MapFallbackToController("Blazor", "Home");
MVC アプリに
Pages
フォルダーを作成し、ルーティング可能なコンポーネントを追加します。 次の例は、Blazor プロジェクト テンプレート内のCounter
コンポーネントに基づくRoutableCounter
コンポーネントです。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
ページまたはビューからコンポーネントをレンダリングする
これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。
ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。
ステートフル対話型コンポーネントをレンダリングする
Razor ページまたはビューには、ステートフル対話型コンポーネントを追加できます。
ページまたはビューがレンダリングされると、次の処理が行われます。
- ページまたはビューと共にコンポーネントがプリレンダリングされます。
- プリレンダリングに使用された初期のコンポーネント状態は失われます。
- SignalR 接続が確立されると、新しいコンポーネント状態が作成されます。
次の Razor ページには、Counter
コンポーネントがレンダリングされます。
<h1>Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
非対話型コンポーネントをレンダリングする
次の Razor ページには、フォームを使用して指定された初期値を使用して、Counter
コンポーネントが静的にレンダリングされます。 コンポーネントは静的にレンダリングされるため、コンポーネントは対話型ではありません。
<h1>Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
コンポーネントの名前空間
カスタム フォルダーを使用してプロジェクトの Razor コンポーネントを保持する場合は、フォルダーを表す名前空間を、ページまたはビューのいずれかに追加するか、_ViewImports.cshtml
ファイルに追加します。 次に例を示します。
- コンポーネントはプロジェクトの
Components
フォルダーに格納されます。 {APP NAMESPACE}
プレースホルダーはロジェクトの名前空間です。Components
はフォルダーの名前を表します。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
ファイルは、Razor Pages アプリの Pages
フォルダーまたは MVC アプリの Views
フォルダーにあります。
詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。
プリレンダリングされた状態を保持する
プリレンダリングされた状態を保持しないと、プリレンダリング中に使用された状態は失われ、アプリが完全に読み込まれたときに再作成する必要があります。 いずれかの状態が非同期でセットアップされている場合、プリレンダリングされた UI は一時的なプレースホルダーに置き換えられてから再度完全にレンダリングされるため、UI がちらつくことがあります。
プリレンダリング済みコンポーネントの状態を保持するには、コンポーネントの状態保持タグ ヘルパー (参照ソース) を使用します。 コンポーネントをプリレンダリングするアプリの _Host
ページの </body>
の終了タグの内側に、タグ ヘルパのタグ <persist-component-state />
を追加します。
Note
通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。
Blazor Server アプリにServerPrerendered
BlazorアプリのPages/_Host.cshtml
:
<body>
...
<persist-component-state />
</body>
PersistentComponentState サービスを使用してどの状態を永続化するか決定します。 アプリが一時停止される前に、PersistentComponentState.RegisterOnPersisting
によってコールバックが登録され、コンポーネントの状態が保持されます。 状態は、アプリケーションの再開時に取得されます。
次に例を示します。
{TYPE}
プレースホルダーは、(WeatherForecast[]
など) 永続化するデータの種類を表します。{TOKEN}
プレースホルダーは、(fetchdata
など) 状態識別子の文字列です。
@implements IDisposable
@inject PersistentComponentState ApplicationState
...
@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
次の例は、Blazor プロジェクト テンプレートに基づくFetchData
コンポーネントの更新バージョンです。 WeatherForecastPreserveState
コンポーネントでは、プリレンダリング中に天気予報の状態を保持し、コンポーネントを初期化するために状態が取得されます。 永続コンポーネントの状態タグ ヘルパーでは、すべてのコンポーネントの呼び出しの後で、コンポーネントの状態を保持します。
Pages/WeatherForecastPreserveState.razor
:
@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@implements IDisposable
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistForecasts);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
"fetchdata", out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateOnly.FromDateTime(DateTime.Now));
}
else
{
forecasts = restored!;
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
プリレンダリング中に使用されたのと同じ状態でコンポーネントを初期化することにより、負荷の高い初期化ステップが 1 回だけ実行されます。 レンダリングされた UI もプリレンダリングされた UI に一致するので、ブラウザーでちらつきは発生しません。
永続化されたプリレンダリングされた状態はクライアントに転送され、そこでコンポーネントの状態を復元するために使用されます。 コア データ保護 ASP.NETBlazor Serverアプリでデータが安全に転送されるようにします。
プリレンダリングされた状態サイズと SignalR メッセージ サイズの制限
プリレンダリングされた状態サイズが大きい場合、 Blazorの SignalR 回線メッセージ サイズの制限を超える可能性があり、その結果、次のようになります。
- この SignalR 回線は、クライアントで次のエラーで初期化に失敗します: Circuit host not initialized.
- 回線が失敗状態になると、クライアント側に再接続 UI が表示されます。 復旧はできません。
この問題を解決するには、次の "いずれかの" 方法を使用します。
- プリレンダリングされた状態に入れるデータの量を減らします。
- SignalR メッセージ サイズの制限を増やします。 警告: 上限を引き上げると、サービス拒否 (DoS) 攻撃のリスクが高まる可能性があります。
Blazor Server のその他のリソース
- 状態管理: プリレンダリングを処理する
- プリレンダリングに関連する Razor コンポーネント ライフサイクルの話題
- 認証と認可: 一般的な側面
- エラーを処理する: プリレンダリング
- ホストと展開: Blazor Server
- 脅威の緩和: クロスサイト スクリプティング (XSS)
- OnNavigateAsync は、プリレンダリング時に 2 回実行されます。
OnNavigateAsync
で非同期ナビゲーション イベントを処理する
プリレンダリングにより、検索エンジンがページ ランクの計算に使える最初の HTTP 応答の内容がレンダリングされることで、検索エンジンの最適化 (SEO) が向上します。
プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。
- ルーティング可能なコンポーネント:ユーザー要求から直接ルーティング可能なコンポーネント。 訪問者が
@page
ディレクティブを含むコンポーネントのブラウザーで HTTP 要求を行うことができる必要がある場合は、このガイダンスに従ってください。 - ページまたはビューからコンポーネントをレンダリングする:ユーザー要求から直接ルーティングできないコンポーネント。 Component タグ ヘルパーを使用して、アプリが既存のページまたはビューにコンポーネントを埋め込む場合は、このガイダンスに従。
構成
既存の Razor Pages または MVC アプリのページまたはビューにRazor コンポーネントを統合するには、次のガイダンスを使用します。
重要
ページのタイトル (PageTitle コンポーネント) や他の head 要素 (HeadContent コンポーネント) などの <head>
コンテンツを制御するには、HeadOutlet コンポーネントのコンポーネント タグ ヘルパーでレイアウト ページ (_Layout.cshtml
) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。
プロジェクトのレイアウト ファイルで、次のようにします。
Pages/Shared/_Layout.cshtml
(Razor Pages) またはViews/Shared/_Layout.cshtml
(MVC) の<head>
要素に次の<base>
タグと HeadOutlet コンポーネント タグ ヘルパーを追加します。<base href="~/" /> <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
前の例の
href
値 (アプリ ベースのパス) は、アプリがルート URL パス (/
) に置かれていることを前提としています。 アプリがサブアプリケーションになっている場合は、「ASP.NET Core Blazor のホストと展開」記事の「アプリのベース パス」セクションのガイダンスに従ってください。HeadOutlet コンポーネントは、Razor コンポーネントによって設定されたページタイトル (PageTitle コンポーネント) とその他の head 要素 (HeadContent コンポーネント) の head (
<head>
) コンテンツをレンダリングするために使用されます。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。blazor.server.js
スクリプトの<script>
タグを、アプリのレイアウトのScripts
レンダリング セクション (@await RenderSectionAsync(...)
) の直前に追加します。Pages/Shared/_Layout.cshtml
(Razor Pages) またはViews/Shared/_Layout.cshtml
(MVC):<script src="_framework/blazor.server.js"></script>
フレームワークによって
blazor.server.js
スクリプトがアプリに追加されます。blazor.server.js
スクリプト ファイルをアプリに手動で追加する必要はありません。
次の内容の imports ファイルをプロジェクトのルート フォルダーに追加します。
{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に変更します。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop @using {APP NAMESPACE}
Blazor Server サービスを、サービスの登録先である
Program.cs
に登録します。builder.Services.AddServerSideBlazor();
Blazor ハブ エンドポイントを、ルートがマップされる
Program.cs
のエンドポイントに追加します。MapRazorPages
(Razor Pages) またはMapControllerRoute
(MVC) の呼び出しの後に、次の行を配置します。app.MapBlazorHub();
コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの
Shared
フォルダーにCounter
コンポーネントを追加します。Pages/Shared/Counter.razor
(Razor Pages) またはViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
Razor Pages アプリのプロジェクトの
Index
ページで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをページに埋め込みます。Index
ページが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
MVC:
MVC アプリのプロジェクトの
Index
ビューで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをビューに埋め込みます。Index
ビューが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <component type="typeof(Counter)" render-mode="ServerPrerendered" />
詳細については、「ページまたはビューからコンポーネントをレンダリングする」セクションを参照してください。
Razor Pages アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
Razor Pages アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
次の内容の
_Host
ページをプロジェクトに追加します。Pages/_Host.cshtml
:@page "/blazor" @namespace {APP NAMESPACE}.Pages.Shared @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } <component type="typeof(App)" render-mode="ServerPrerendered" />
このシナリオのコンポーネントでは、そのレイアウトで共有される
_Layout.cshtml
ファイルが使用されます。重要
ページのタイトル (PageTitle コンポーネント) や他の head 要素 (HeadContent コンポーネント) などの
<head>
コンテンツを制御するには、HeadOutlet コンポーネントのコンポーネント タグ ヘルパーでレイアウト ページ (_Layout.cshtml
) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Program.cs
エンドポイントで、_Host
ページの優先度の低いルートを最後のエンドポイントとして追加します。app.MapFallbackToPage("/_Host");
ルーティング可能なコンポーネントをプロジェクトに追加します。 次の例は、Blazor プロジェクト テンプレート内の
Counter
コンポーネントに基づくRoutableCounter
コンポーネントです。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
MVC アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <PageTitle>Not found</PageTitle> <p role="alert">Sorry, there's nothing at this address.</p> </NotFound> </Router>
次の内容の
_Host
ビューをプロジェクトに追加します。Views/Home/_Host.cshtml
:@namespace {APP NAMESPACE}.Views.Shared @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } <component type="typeof(App)" render-mode="ServerPrerendered" />
コンポーネントでは、そのレイアウトで共有される
_Layout.cshtml
ファイルが使用されます。重要
ページのタイトル (PageTitle コンポーネント) や他の head 要素 (HeadContent コンポーネント) などの
<head>
コンテンツを制御するには、HeadOutlet コンポーネントのコンポーネント タグ ヘルパーでレイアウト ページ (_Layout.cshtml
) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Home コントローラーにアクションを追加します。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
Program.cs
エンドポイントに、_Host
ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。app.MapFallbackToController("Blazor", "Home");
MVC アプリに
Pages
フォルダーを作成し、ルーティング可能なコンポーネントを追加します。 次の例は、Blazor プロジェクト テンプレート内のCounter
コンポーネントに基づくRoutableCounter
コンポーネントです。Pages/RoutableCounter.razor
:@page "/routable-counter" <PageTitle>Routable Counter</PageTitle> <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
ページまたはビューからコンポーネントをレンダリングする
これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。
ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。
ステートフル対話型コンポーネントをレンダリングする
Razor ページまたはビューには、ステートフル対話型コンポーネントを追加できます。
ページまたはビューがレンダリングされると、次の処理が行われます。
- ページまたはビューと共にコンポーネントがプリレンダリングされます。
- プリレンダリングに使用された初期のコンポーネント状態は失われます。
- SignalR 接続が確立されると、新しいコンポーネント状態が作成されます。
次の Razor ページには、Counter
コンポーネントがレンダリングされます。
<h1>Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
重要
ページのタイトル (PageTitle コンポーネント) や他の head 要素 (HeadContent コンポーネント) などの <head>
コンテンツを制御するには、HeadOutlet コンポーネントのコンポーネント タグ ヘルパーでレイアウト ページ (_Layout.cshtml
) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。
非対話型コンポーネントをレンダリングする
次の Razor ページには、フォームを使用して指定された初期値を使用して、Counter
コンポーネントが静的にレンダリングされます。 コンポーネントは静的にレンダリングされるため、コンポーネントは対話型ではありません。
<h1>Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
重要
ページのタイトル (PageTitle コンポーネント) や他の head 要素 (HeadContent コンポーネント) などの <head>
コンテンツを制御するには、HeadOutlet コンポーネントのコンポーネント タグ ヘルパーでレイアウト ページ (_Layout.cshtml
) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。
コンポーネントの名前空間
カスタム フォルダーを使用してプロジェクトの Razor コンポーネントを保持する場合は、フォルダーを表す名前空間を、ページまたはビューのいずれかに追加するか、_ViewImports.cshtml
ファイルに追加します。 次に例を示します。
- コンポーネントはプロジェクトの
Components
フォルダーに格納されます。 {APP NAMESPACE}
プレースホルダーはロジェクトの名前空間です。Components
はフォルダーの名前を表します。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
ファイルは、Razor Pages アプリの Pages
フォルダーまたは MVC アプリの Views
フォルダーにあります。
詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。
プリレンダリングされた状態を保持する
プリレンダリングされた状態を保持しないと、プリレンダリング中に使用された状態は失われ、アプリが完全に読み込まれたときに再作成する必要があります。 いずれかの状態が非同期でセットアップされている場合、プリレンダリングされた UI は一時的なプレースホルダーに置き換えられてから再度完全にレンダリングされるため、UI がちらつくことがあります。
これらの問題を解決するために、Blazor では、永続コンポーネントの状態タグ ヘルパーを使用して、プリレンダリングされたページ内での状態の永続化をサポートしています。 終了 </body>
タグの内側にタグ ヘルパーのタグ <persist-component-state />
を追加します。
Pages/_Layout.cshtml
:
<body>
...
<persist-component-state />
</body>
PersistentComponentState サービスを使用してどの状態を永続化するか決定します。 アプリが一時停止される前に、PersistentComponentState.RegisterOnPersisting
によってコールバックが登録され、コンポーネントの状態が保持されます。 状態は、アプリケーションの再開時に取得されます。
次の例は、Blazor プロジェクト テンプレートに基づくFetchData
コンポーネントの更新バージョンです。 WeatherForecastPreserveState
コンポーネントでは、プリレンダリング中に天気予報の状態を保持し、コンポーネントを初期化するために状態が取得されます。 永続コンポーネントの状態タグ ヘルパーでは、すべてのコンポーネントの呼び出しの後で、コンポーネントの状態を保持します。
Pages/WeatherForecastPreserveState.razor
:
@page "/weather-forecast-preserve-state"
@implements IDisposable
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService
@inject PersistentComponentState ApplicationState
<PageTitle>Weather Forecast</PageTitle>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[] forecasts = Array.Empty<WeatherForecast>();
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistForecasts);
if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
"fetchdata", out var restored))
{
forecasts =
await WeatherForecastService.GetForecastAsync(DateTime.Now);
}
else
{
forecasts = restored!;
}
}
private Task PersistForecasts()
{
ApplicationState.PersistAsJson("fetchdata", forecasts);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
プリレンダリング中に使用されたのと同じ状態でコンポーネントを初期化することにより、負荷の高い初期化ステップが 1 回だけ実行されます。 レンダリングされた UI もプリレンダリングされた UI に一致するので、ブラウザーでちらつきは発生しません。
永続化されたプリレンダリングされた状態はクライアントに転送され、そこでコンポーネントの状態を復元するために使用されます。 コア データ保護 ASP.NETBlazor Serverアプリでデータが安全に転送されるようにします。
プリレンダリングされた状態サイズと SignalR メッセージ サイズの制限
プリレンダリングされた状態サイズが大きい場合、 Blazorの SignalR 回線メッセージ サイズの制限を超える可能性があり、その結果、次のようになります。
- この SignalR 回線は、クライアントで次のエラーで初期化に失敗します: Circuit host not initialized.
- 回線が失敗状態になると、クライアント側に再接続 UI が表示されます。 復旧はできません。
この問題を解決するには、次の "いずれかの" 方法を使用します。
- プリレンダリングされた状態に入れるデータの量を減らします。
- SignalR メッセージ サイズの制限を増やします。 警告: 上限を引き上げると、サービス拒否 (DoS) 攻撃のリスクが高まる可能性があります。
Blazor Server のその他のリソース
プリレンダリングにより、検索エンジンがページ ランクの計算に使える最初の HTTP 応答の内容がレンダリングされることで、検索エンジンの最適化 (SEO) が向上します。
プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。
- ルーティング可能なコンポーネント:ユーザー要求から直接ルーティング可能なコンポーネント。 訪問者が
@page
ディレクティブを含むコンポーネントのブラウザーで HTTP 要求を行うことができる必要がある場合は、このガイダンスに従ってください。 - ページまたはビューからコンポーネントをレンダリングする:ユーザー要求から直接ルーティングできないコンポーネント。 Component タグ ヘルパーを使用して、アプリが既存のページまたはビューにコンポーネントを埋め込む場合は、このガイダンスに従。
構成
既存の Razor Pages または MVC アプリは、 Razor コンポーネントをページまたはビューに統合できます。
プロジェクトのレイアウト ファイルで、次のようにします。
Pages/Shared/_Layout.cshtml
(Razor Pages) またはViews/Shared/_Layout.cshtml
(MVC) の<head>
要素に次の<base>
タグを追加します。<base href="~/" />
前の例の
href
値 (アプリ ベースのパス) は、アプリがルート URL パス (/
) に置かれていることを前提としています。 アプリがサブアプリケーションになっている場合は、「ASP.NET Core Blazor のホストと展開」記事の「アプリのベース パス」セクションのガイダンスに従ってください。blazor.server.js
スクリプトの<script>
タグをScripts
レンダリング セクションの直前に追加します。Pages/Shared/_Layout.cshtml
(Razor Pages) またはViews/Shared/_Layout.cshtml
(MVC):... <script src="_framework/blazor.server.js"></script> @await RenderSectionAsync("Scripts", required: false) </body>
フレームワークによって
blazor.server.js
スクリプトがアプリに追加されます。blazor.server.js
スクリプト ファイルをアプリに手動で追加する必要はありません。
次の内容の imports ファイルをプロジェクトのルート フォルダーに追加します。
{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に変更します。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using {APP NAMESPACE}
Blazor Server サービスを
Startup.ConfigureServices
に登録します。Startup.cs
:services.AddServerSideBlazor();
Blazor ハブ エンドポイントを
Startup.Configure
のエンドポイント (app.UseEndpoints
) に追加します。Startup.cs
:endpoints.MapBlazorHub();
コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの
Shared
フォルダーにCounter
コンポーネントを追加します。Pages/Shared/Counter.razor
(Razor Pages) またはViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
Razor Pages アプリのプロジェクトの
Index
ページで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをページに埋め込みます。Index
ページが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
前の例では、
{APP NAMESPACE}
プレースホルダーをアプリの名前空間に置き換えます。MVC:
MVC アプリのプロジェクトの
Index
ビューで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをビューに埋め込みます。Index
ビューが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
詳細については、「ページまたはビューからコンポーネントをレンダリングする」セクションを参照してください。
Razor Pages アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
Razor Pages アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
注意
ASP.NET Core 5.0.1 のリリースと、その他の 5.x リリースでは、
Router
コンポーネントに@true
に設定されたPreferExactMatches
パラメーターが含まれています。 詳細については、「ASP.NET Core 3.1 から 5.0 への移行」を参照してください。次の内容の
_Host
ページをプロジェクトに追加します。Pages/_Host.cshtml
:@page "/blazor" @{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
コンポーネントでは、そのレイアウトで共有される
_Layout.cshtml
ファイルが使用されます。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Startup.cs
のStartup.Configure
エンドポイントで、_Host
ページの優先度の低いルートを最後のエンドポイントとして追加します。endpoints.MapFallbackToPage("/_Host");
次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
ルーティング可能なコンポーネントをプロジェクトに追加します。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
MVC アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
注意
ASP.NET Core 5.0.1 のリリースと、その他の 5.x リリースでは、
Router
コンポーネントに@true
に設定されたPreferExactMatches
パラメーターが含まれています。 詳細については、「ASP.NET Core 3.1 から 5.0 への移行」を参照してください。次の内容の
_Host
ビューをプロジェクトに追加します。Views/Home/_Host.cshtml
:@{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
コンポーネントでは、そのレイアウトで共有される
_Layout.cshtml
ファイルが使用されます。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Home コントローラーにアクションを追加します。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
Startup.cs
のStartup.Configure
エンドポイントに、_Host
ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。endpoints.MapFallbackToController("Blazor", "Home");
次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapBlazorHub(); endpoints.MapFallbackToController("Blazor", "Home"); });
ルーティング可能なコンポーネントをプロジェクトに追加します。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
ページまたはビューからコンポーネントをレンダリングする
これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。
ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。
ステートフル対話型コンポーネントをレンダリングする
Razor ページまたはビューには、ステートフル対話型コンポーネントを追加できます。
ページまたはビューがレンダリングされると、次の処理が行われます。
- ページまたはビューと共にコンポーネントがプリレンダリングされます。
- プリレンダリングに使用された初期のコンポーネント状態は失われます。
- SignalR 接続が確立されると、新しいコンポーネント状態が作成されます。
次の Razor ページには、Counter
コンポーネントがレンダリングされます。
<h1>My Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
非対話型コンポーネントをレンダリングする
次の Razor ページには、フォームを使用して指定された初期値を使用して、Counter
コンポーネントが静的にレンダリングされます。 コンポーネントは静的にレンダリングされるため、コンポーネントは対話型ではありません。
<h1>My Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
コンポーネントの名前空間
カスタム フォルダーを使用してプロジェクトの Razor コンポーネントを保持する場合は、フォルダーを表す名前空間を、ページまたはビューのいずれかに追加するか、_ViewImports.cshtml
ファイルに追加します。 次に例を示します。
- コンポーネントはプロジェクトの
Components
フォルダーに格納されます。 {APP NAMESPACE}
プレースホルダーはロジェクトの名前空間です。Components
はフォルダーの名前を表します。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
ファイルは、Razor Pages アプリの Pages
フォルダーまたは MVC アプリの Views
フォルダーにあります。
詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。
プリレンダリングされた状態サイズと SignalR メッセージ サイズの制限
プリレンダリングされた状態サイズが大きい場合、 Blazorの SignalR 回線メッセージ サイズの制限を超える可能性があり、その結果、次のようになります。
- この SignalR 回線は、クライアントで次のエラーで初期化に失敗します: Circuit host not initialized.
- 回線が失敗状態になると、クライアント側に再接続 UI が表示されます。 復旧はできません。
この問題を解決するには、次の "いずれかの" 方法を使用します。
- プリレンダリングされた状態に入れるデータの量を減らします。
- SignalR メッセージ サイズの制限を増やします。 警告: 上限を引き上げると、サービス拒否 (DoS) 攻撃のリスクが高まる可能性があります。
Blazor Server のその他のリソース
Razor コンポーネントは、 Razor Pages または MVC アプリに統合できます。 ページまたはビューがレンダリングされるときには、コンポーネントを同時に事前レンダリングすることができます。
プリレンダリングにより、検索エンジンがページ ランクの計算に使える最初の HTTP 応答の内容がレンダリングされることで、検索エンジンの最適化 (SEO) が向上します。
プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。
- ルーティング可能なコンポーネント:ユーザー要求から直接ルーティング可能なコンポーネント。 訪問者が
@page
ディレクティブを含むコンポーネントのブラウザーで HTTP 要求を行うことができる必要がある場合は、このガイダンスに従ってください。 - ページまたはビューからコンポーネントをレンダリングする:ユーザー要求から直接ルーティングできないコンポーネント。 Component タグ ヘルパーを使用して、アプリが既存のページまたはビューにコンポーネントを埋め込む場合は、このガイダンスに従。
構成
既存の Razor Pages または MVC アプリは、 Razor コンポーネントをページまたはビューに統合できます。
プロジェクトのレイアウト ファイルで、次のようにします。
Pages/Shared/_Layout.cshtml
(Razor Pages) またはViews/Shared/_Layout.cshtml
(MVC) の<head>
要素に次の<base>
タグを追加します。+ <base href="~/" />
前の例の
href
値 (アプリ ベースのパス) は、アプリがルート URL パス (/
) に置かれていることを前提としています。 アプリがサブアプリケーションになっている場合は、「ASP.NET Core Blazor のホストと展開」記事の「アプリのベース パス」セクションのガイダンスに従ってください。blazor.server.js
スクリプトの<script>
タグをScripts
レンダリング セクションの直前に追加します。Pages/Shared/_Layout.cshtml
(Razor Pages) またはViews/Shared/_Layout.cshtml
(MVC):... <script src="_framework/blazor.server.js"></script> @await RenderSectionAsync("Scripts", required: false) </body>
フレームワークによって
blazor.server.js
スクリプトがアプリに追加されます。blazor.server.js
スクリプト ファイルをアプリに手動で追加する必要はありません。
次の内容の imports ファイルをプロジェクトのルート フォルダーに追加します。
{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に変更します。_Imports.razor
:@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using Microsoft.AspNetCore.Components.Authorization @using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Routing @using Microsoft.AspNetCore.Components.Web @using Microsoft.JSInterop @using {APP NAMESPACE}
Blazor Server サービスを
Startup.ConfigureServices
に登録します。Startup.cs
:services.AddServerSideBlazor();
Blazor ハブ エンドポイントを
Startup.Configure
のエンドポイント (app.UseEndpoints
) に追加します。Startup.cs
:endpoints.MapBlazorHub();
コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの
Shared
フォルダーにCounter
コンポーネントを追加します。Pages/Shared/Counter.razor
(Razor Pages) またはViews/Shared/Counter.razor
(MVC):<h1>Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
Razor Pages:
Razor Pages アプリのプロジェクトの
Index
ページで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをページに埋め込みます。Index
ページが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Pages/Index.cshtml
:@page @using {APP NAMESPACE}.Pages.Shared @model IndexModel @{ ViewData["Title"] = "Home page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
前の例では、
{APP NAMESPACE}
プレースホルダーをアプリの名前空間に置き換えます。MVC:
MVC アプリのプロジェクトの
Index
ビューで、Counter
コンポーネントの名前空間を追加し、そのコンポーネントをビューに埋め込みます。Index
ビューが読み込まれるとき、Counter
コンポーネントはページにプリレンダリングされます。 次の例では、{APP NAMESPACE}
プレースホルダーをプロジェクトの名前空間に置き換えます。Views/Home/Index.cshtml
:@using {APP NAMESPACE}.Views.Shared @{ ViewData["Title"] = "Home Page"; } <div> <component type="typeof(Counter)" render-mode="ServerPrerendered" /> </div>
詳細については、「ページまたはビューからコンポーネントをレンダリングする」セクションを参照してください。
Razor Pages アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
Razor Pages アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
次の内容の
_Host
ページをプロジェクトに追加します。Pages/_Host.cshtml
:@page "/blazor" @{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
コンポーネントでは、そのレイアウトで共有される
_Layout.cshtml
ファイルが使用されます。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Startup.cs
のStartup.Configure
エンドポイントで、_Host
ページの優先度の低いルートを最後のエンドポイントとして追加します。endpoints.MapFallbackToPage("/_Host");
次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); endpoints.MapBlazorHub(); endpoints.MapFallbackToPage("/_Host"); });
ルーティング可能なコンポーネントをプロジェクトに追加します。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
MVC アプリでルーティング可能なコンポーネントを使用する
ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。
MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。
「構成」セクションのガイダンスに従います。
次の内容の
App
コンポーネントをプロジェクト ルートに追加します。App.razor
:@using Microsoft.AspNetCore.Components.Routing <Router AppAssembly="typeof(Program).Assembly"> <Found Context="routeData"> <RouteView RouteData="routeData" /> </Found> <NotFound> <h1>Page not found</h1> <p>Sorry, but there's nothing here!</p> </NotFound> </Router>
次の内容の
_Host
ビューをプロジェクトに追加します。Views/Home/_Host.cshtml
:@{ Layout = "_Layout"; } <app> <component type="typeof(App)" render-mode="ServerPrerendered" /> </app>
コンポーネントでは、そのレイアウトで共有される
_Layout.cshtml
ファイルが使用されます。RenderMode によって、
App
コンポーネントに対して以下の構成が行われます。- ページに事前レンダリングするかどうか。
- ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。
パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
Home コントローラーにアクションを追加します。
Controllers/HomeController.cs
:public IActionResult Blazor() { return View("_Host"); }
Startup.cs
のStartup.Configure
エンドポイントに、_Host
ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。endpoints.MapFallbackToController("Blazor", "Home");
次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapBlazorHub(); endpoints.MapFallbackToController("Blazor", "Home"); });
ルーティング可能なコンポーネントをプロジェクトに追加します。
Pages/RoutableCounter.razor
:@page "/routable-counter" <h1>Routable Counter</h1> <p>Current count: @currentCount</p> <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> @code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }
プロジェクトを実行し、
/routable-counter
のルーティング可能なRoutableCounter
コンポーネントに移動します。
名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。
ページまたはビューからコンポーネントをレンダリングする
これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。
ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。
ステートフル対話型コンポーネントをレンダリングする
Razor ページまたはビューには、ステートフル対話型コンポーネントを追加できます。
ページまたはビューがレンダリングされると、次の処理が行われます。
- ページまたはビューと共にコンポーネントがプリレンダリングされます。
- プリレンダリングに使用された初期のコンポーネント状態は失われます。
- SignalR 接続が確立されると、新しいコンポーネント状態が作成されます。
次の Razor ページには、Counter
コンポーネントがレンダリングされます。
<h1>My Razor Page</h1>
<component type="typeof(Counter)" render-mode="ServerPrerendered"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
非対話型コンポーネントをレンダリングする
次の Razor ページには、フォームを使用して指定された初期値を使用して、Counter
コンポーネントが静的にレンダリングされます。 コンポーネントは静的にレンダリングされるため、コンポーネントは対話型ではありません。
<h1>My Razor Page</h1>
<form>
<input type="number" asp-for="InitialValue" />
<button type="submit">Set initial value</button>
</form>
<component type="typeof(Counter)" render-mode="Static"
param-InitialValue="InitialValue" />
@functions {
[BindProperty(SupportsGet=true)]
public int InitialValue { get; set; }
}
詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。
コンポーネントの名前空間
カスタム フォルダーを使用してプロジェクトの Razor コンポーネントを保持する場合は、フォルダーを表す名前空間を、ページまたはビューのいずれかに追加するか、_ViewImports.cshtml
ファイルに追加します。 次に例を示します。
- コンポーネントはプロジェクトの
Components
フォルダーに格納されます。 {APP NAMESPACE}
プレースホルダーはロジェクトの名前空間です。Components
はフォルダーの名前を表します。
@using {APP NAMESPACE}.Components
_ViewImports.cshtml
ファイルは、Razor Pages アプリの Pages
フォルダーまたは MVC アプリの Views
フォルダーにあります。
詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。
プリレンダリングされた状態サイズと SignalR メッセージ サイズの制限
プリレンダリングされた状態サイズが大きい場合、 Blazorの SignalR 回線メッセージ サイズの制限を超える可能性があり、その結果、次のようになります。
- この SignalR 回線は、クライアントで次のエラーで初期化に失敗します: Circuit host not initialized.
- 回線が失敗状態になると、クライアント側に再接続 UI が表示されます。 復旧はできません。
この問題を解決するには、次の "いずれかの" 方法を使用します。
- プリレンダリングされた状態に入れるデータの量を減らします。
- SignalR メッセージ サイズの制限を増やします。 警告: 上限を引き上げると、サービス拒否 (DoS) 攻撃のリスクが高まる可能性があります。
Blazor Server のその他のリソース
ASP.NET Core