次の方法で共有


ASP.NET Core Razor コンポーネントを MVC または Razor Pages と統合する

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .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) が向上します。

プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。

設定

既存の Razor Pages または MVC アプリのページまたはビューにRazor コンポーネントを統合するには、次のガイダンスを使用します。

  1. 次の内容の 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}
    
  2. プロジェクトのレイアウト ファイル (Pages/Shared/_Layout.cshtml Pages アプリの Razor、または MVC アプリの Views/Shared/_Layout.cshtml):

    • <base> 要素に次の HeadOutlet タグと <head> コンポーネント タグ ヘルパーを追加します。

      <base href="~/" />
      <component type="typeof(Microsoft.AspNetCore.Components.Web.HeadOutlet)" 
          render-mode="ServerPrerendered" />
      

      前の例の href 値 (アプリ ベースのパス) は、アプリがルート URL パス (/) に置かれていることを前提としています。 アプリがサブアプリケーションの場合は、 Core Blazor アプリのベース パス ASP.NET 参照してください。

      HeadOutlet コンポーネントは、<head> コンポーネントによって設定されたページタイトル (PageTitle コンポーネント) とその他の head 要素 (HeadContent コンポーネント) の head (Razor) コンテンツをレンダリングするために使用されます。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

    • <script> スクリプトの blazor.server.js タグを、Scripts レンダリング セクション (@await RenderSectionAsync(...)) の直前に追加します。

      <script src="_framework/blazor.server.js"></script>
      

      フレームワークによって blazor.server.js スクリプトがアプリに追加されます。 blazor.server.js スクリプト ファイルをアプリに手動で追加する必要はありません。

    通常、レイアウトは _ViewStart.cshtml ファイルを介して読み込まれます。

  3. Blazor Server サービスを、サービスの登録先である Program.cs に登録します。

    builder.Services.AddServerSideBlazor();
    
  4. Blazor ハブ エンドポイントを、ルートがマップされる Program.cs のエンドポイントに追加します。 MapRazorPages (Razor Pages) または MapControllerRoute (MVC) の呼び出しの後に、次の行を配置します。

    app.MapBlazorHub();
    
  5. コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの Counter フォルダーに Shared コンポーネントを追加します。

    Pages/Shared/Counter.razor (Razor ページ) または 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 ページ:

    Index Pages アプリのプロジェクトの Razor ページで、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 コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    
  3. 次の内容の _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 のコンポーネント タグ ヘルパー」を参照してください。

  4. Program.cs エンドポイントで、_Host ページの優先度の低いルートを最後のエンドポイントとして追加します。

    app.MapFallbackToPage("/_Host");
    
  5. ルーティング可能なコンポーネントをプロジェクトに追加します。 次の例は、RoutableCounter プロジェクト テンプレート内の Counter コンポーネントに基づく Blazor コンポーネントです。

    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++;
        }
    }
    
  6. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

MVC アプリでルーティング可能なコンポーネントを使用する

ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。

MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    
  3. 次の内容の _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 のコンポーネント タグ ヘルパー」を参照してください。

  4. Home コントローラーにアクションを追加します。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Program.cs エンドポイントに、_Host ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。

    app.MapFallbackToController("Blazor", "Home");
    
  6. MVC アプリに Pages フォルダーを作成し、ルーティング可能なコンポーネントを追加します。 次の例は、RoutableCounter プロジェクト テンプレート内の Counter コンポーネントに基づく Blazor コンポーネントです。

    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++;
        }
    }
    
  7. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

ページまたはビューからコンポーネントをレンダリングする

これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。

ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。

ステートフル対話型コンポーネントをレンダリングする

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 ファイルは、Pages Pages アプリの Razor フォルダーまたは MVC アプリの Views フォルダーにあります。

詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

プリレンダリングされた状態を保持する

プリレンダリングされた状態を保持しないと、プリレンダリング中に使用された状態は失われ、アプリが完全に読み込まれたときに再作成する必要があります。 いずれかの状態が非同期でセットアップされている場合、プリレンダリングされた UI は一時的なプレースホルダーに置き換えられてから再度完全にレンダリングされるため、UI がちらつくことがあります。

プリレンダリング済みコンポーネントの状態を保持するには、コンポーネントの状態保持タグ ヘルパー (参照ソース) を使用します。 コンポーネントをプリレンダリングするアプリの <persist-component-state /> ページの </body> の終了タグの内側に、タグ ヘルパのタグ _Host を追加します。

通常、.NET 参照ソースへのドキュメント リンクを使用すると、リポジトリの既定のブランチが読み込まれます。このブランチは、.NET の次回リリースに向けて行われている現在の開発を表します。 特定のリリースのタグを選択するには、[Switch branches or tags](ブランチまたはタグの切り替え) ドロップダウン リストを使います。 詳細については、「ASP.NET Core ソース コードのバージョン タグを選択する方法」 (dotnet/AspNetCore.Docs #26205) を参照してください。

Pages/_Host.cshtml アプリのBlazor にある ServerPrerendered アプリの Blazor Server 内:

<body>
    ...

    <persist-component-state />
</body>

PersistentComponentState サービスを使用してどの状態を永続化するか決定します。 プロパティに適用される [PersistentState] 属性は、プリレンダリング中に状態を保持するためのコールバックを登録し、コンポーネントが対話形式でレンダリングされるか、サービスがインスタンス化されたときにそれを読み込みます。

次の例では、 {TYPE} プレースホルダーは、永続化するデータの種類 (たとえば、 WeatherForecast[]) を表します。

@code {
    [PersistentState]
    public {TYPE} Data { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Data ??= await ...;
    }
}

次の例では、 WeatherForecastPreserveState コンポーネントは、プリレンダリング中に天気予報の状態を保持し、コンポーネントを初期化する状態を取得します。 永続コンポーネントの状態タグ ヘルパーでは、すべてのコンポーネントの呼び出しの後で、コンポーネントの状態を保持します。

WeatherForecastPreserveState.razor:

@page "/weather-forecast-preserve-state"
@using BlazorSample.Shared
@inject IWeatherForecastService WeatherForecastService

<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 {
    [PersistentState]
    public WeatherForecast[]? Forecasts { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Forecasts ??= await WeatherForecastService.GetForecastAsync(
            DateOnly.FromDateTime(DateTime.Now));
    }
}

PersistentComponentState サービスを使用してどの状態を永続化するか決定します。 アプリが一時停止される前に、PersistentComponentState.RegisterOnPersisting によってコールバックが登録され、コンポーネントの状態が保持されます。 状態は、アプリケーションの再開時に取得されます。 アプリのシャットダウン中に競合状態になる可能性を回避するために、初期化コードの最後に呼び出しを行います。

次に例を示します。

  • {TYPE} プレースホルダーは、(WeatherForecast[] など) 永続化するデータの種類を表します。
  • {TOKEN} プレースホルダーは、(fetchdata など) 状態識別子の文字列です。
@implements IDisposable
@inject PersistentComponentState ApplicationState

...

@code {
    private {TYPE} data;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<{TYPE}>(
            "{TOKEN}", out var restored))
        {
            data = await ...;
        }
        else
        {
            data = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson("{TOKEN}", data);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose()
    {
        persistingSubscription.Dispose();
    }
}

次の例では、 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()
    {
        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            nameof(forecasts), out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(
                    DateOnly.FromDateTime(DateTime.Now));
        }
        else
        {
            forecasts = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), 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) が向上します。

プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。

設定

既存の Razor Pages または MVC アプリのページまたはビューにRazor コンポーネントを統合するには、次のガイダンスを使用します。

重要

ページのタイトル (_Layout.cshtml コンポーネント) や他の head 要素 ( コンポーネント) などの HeadOutlet コンテンツを制御するには、<head> コンポーネントのPageTitleでレイアウト ページ (HeadContent) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

  1. プロジェクトのレイアウト ファイルで、次のようにします。

    • <base> (HeadOutlet Pages) または <head> (MVC) の Pages/Shared/_Layout.cshtml 要素に次の Razor タグと Views/Shared/_Layout.cshtml コンポーネントタグヘルパーを追加します。

      <base href="~/" />
      <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
      

      前の例の href 値 (アプリ ベースのパス) は、アプリがルート URL パス (/) に置かれていることを前提としています。 アプリがサブアプリケーションの場合は、 Core Blazor アプリのベース パス ASP.NET 参照してください。

      HeadOutlet コンポーネントは、<head> コンポーネントによって設定されたページタイトル (PageTitle コンポーネント) とその他の head 要素 (HeadContent コンポーネント) の head (Razor) コンテンツをレンダリングするために使用されます。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

    • <script> スクリプトの blazor.server.js タグを、アプリのレイアウトの Scripts レンダリング セクション (@await RenderSectionAsync(...)) の直前に追加します。

      Pages/Shared/_Layout.cshtml (Razor ページ) または Views/Shared/_Layout.cshtml (MVC):

      <script src="_framework/blazor.server.js"></script>
      

      フレームワークによって blazor.server.js スクリプトがアプリに追加されます。 blazor.server.js スクリプト ファイルをアプリに手動で追加する必要はありません。

  2. 次の内容の 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}
    
  3. Blazor Server サービスを、サービスの登録先である Program.cs に登録します。

    builder.Services.AddServerSideBlazor();
    
  4. Blazor ハブ エンドポイントを、ルートがマップされる Program.cs のエンドポイントに追加します。

    MapRazorPages (Razor Pages) または MapControllerRoute (MVC) の呼び出しの後に、次の行を配置します。

    app.MapBlazorHub();
    
  5. コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの Counter フォルダーに Shared コンポーネントを追加します。

    Pages/Shared/Counter.razor (Razor ページ) または 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 ページ:

    Index Pages アプリのプロジェクトの Razor ページで、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 コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    
  3. 次の内容の _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 ファイルが使用されます。

    重要

    ページのタイトル (_Layout.cshtml コンポーネント) や他の head 要素 ( コンポーネント) などの HeadOutlet コンテンツを制御するには、<head> コンポーネントのPageTitleでレイアウト ページ (HeadContent) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

    RenderMode によって App コンポーネントが構成されるかどうかを決定します。

    • ページに事前レンダリングするかどうか。
    • ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。

    パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。

  4. Program.cs エンドポイントで、_Host ページの優先度の低いルートを最後のエンドポイントとして追加します。

    app.MapFallbackToPage("/_Host");
    
  5. ルーティング可能なコンポーネントをプロジェクトに追加します。 次の例は、RoutableCounter プロジェクト テンプレート内の Counter コンポーネントに基づく Blazor コンポーネントです。

    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++;
        }
    }
    
  6. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

MVC アプリでルーティング可能なコンポーネントを使用する

ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。

MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    
  3. 次の内容の _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 ファイルが使用されます。

    重要

    ページのタイトル (_Layout.cshtml コンポーネント) や他の head 要素 ( コンポーネント) などの HeadOutlet コンテンツを制御するには、<head> コンポーネントのPageTitleでレイアウト ページ (HeadContent) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

    RenderMode によって App コンポーネントが構成されるかどうかを決定します。

    • ページに事前レンダリングするかどうか。
    • ページに静的 HTML としてレンダリングするかどうか。または、ユーザー エージェントから Blazor アプリをブートストラップするために必要な情報が含まれているかどうか。

    パラメーターの渡し方や RenderMode の構成などのコンポーネント タグ ヘルパーの詳細については、「ASP.NET Core のコンポーネント タグ ヘルパー」を参照してください。

  4. Home コントローラーにアクションを追加します。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Program.cs エンドポイントに、_Host ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。

    app.MapFallbackToController("Blazor", "Home");
    
  6. MVC アプリに Pages フォルダーを作成し、ルーティング可能なコンポーネントを追加します。 次の例は、RoutableCounter プロジェクト テンプレート内の Counter コンポーネントに基づく Blazor コンポーネントです。

    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++;
        }
    }
    
  7. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

ページまたはビューからコンポーネントをレンダリングする

これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。

ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。

ステートフル対話型コンポーネントをレンダリングする

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 のコンポーネント タグ ヘルパー」を参照してください。

重要

ページのタイトル (_Layout.cshtml コンポーネント) や他の head 要素 ( コンポーネント) などの HeadOutlet コンテンツを制御するには、<head> コンポーネントのPageTitleでレイアウト ページ (HeadContent) を使用する必要があります。 詳しくは、「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 のコンポーネント タグ ヘルパー」を参照してください。

重要

ページのタイトル (_Layout.cshtml コンポーネント) や他の head 要素 ( コンポーネント) などの HeadOutlet コンテンツを制御するには、<head> コンポーネントのPageTitleでレイアウト ページ (HeadContent) を使用する必要があります。 詳しくは、「ASP.NET Core Blazor アプリで コンテンツを制御する」をご覧ください。

コンポーネントの名前空間

カスタム フォルダーを使用してプロジェクトの Razor コンポーネントを保持する場合は、フォルダーを表す名前空間を、ページまたはビューのいずれかに追加するか、_ViewImports.cshtml ファイルに追加します。 次に例を示します。

  • コンポーネントはプロジェクトの Components フォルダーに格納されます。
  • {APP NAMESPACE} プレースホルダーはロジェクトの名前空間です。 Components はフォルダーの名前を表します。
@using {APP NAMESPACE}.Components

_ViewImports.cshtml ファイルは、Pages Pages アプリの Razor フォルダーまたは MVC アプリの Views フォルダーにあります。

詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

プリレンダリングされた状態を保持する

プリレンダリングされた状態を保持しないと、プリレンダリング中に使用された状態は失われ、アプリが完全に読み込まれたときに再作成する必要があります。 いずれかの状態が非同期でセットアップされている場合、プリレンダリングされた UI は一時的なプレースホルダーに置き換えられてから再度完全にレンダリングされるため、UI がちらつくことがあります。

これらの問題を解決するために、Blazor では、永続コンポーネントの状態タグ ヘルパーを使用して、プリレンダリングされたページ内での状態の永続化をサポートしています。 終了 <persist-component-state /> タグの内側にタグ ヘルパーのタグ </body> を追加します。

Pages/_Layout.cshtml:

<body>
    ...

    <persist-component-state />
</body>

PersistentComponentState サービスを使用してどの状態を永続化するか決定します。 アプリが一時停止される前に、PersistentComponentState.RegisterOnPersisting によってコールバックが登録され、コンポーネントの状態が保持されます。 状態は、アプリケーションの再開時に取得されます。 アプリのシャットダウン中に競合状態になる可能性を回避するために、初期化コードの最後に呼び出しを行います。

次の例では、 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()
    {
        if (!ApplicationState.TryTakeFromJson<WeatherForecast[]>(
            nameof(forecasts), out var restored))
        {
            forecasts = 
                await WeatherForecastService.GetForecastAsync(DateTime.Now);
        }
        else
        {
            forecasts = restored!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), 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) が向上します。

プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。

設定

既存の Razor Pages または MVC アプリは、 Razor コンポーネントをページまたはビューに統合できます。

  1. プロジェクトのレイアウト ファイルで、次のようにします。

    • <base> (<head> Pages) または Pages/Shared/_Layout.cshtml (MVC) のRazor 要素に次の Views/Shared/_Layout.cshtml タグを追加します。

      <base href="~/" />
      

      前の例の href 値 (アプリ ベースのパス) は、アプリがルート URL パス (/) に置かれていることを前提としています。 アプリがサブアプリケーションの場合は、 Core Blazor アプリのベース パス ASP.NET 参照してください。

    • <script> スクリプトの blazor.server.js タグを Scripts レンダリング セクションの直前に追加します。

      Pages/Shared/_Layout.cshtml (Razor ページ) または Views/Shared/_Layout.cshtml (MVC):

          ...
          <script src="_framework/blazor.server.js"></script>
      
          @await RenderSectionAsync("Scripts", required: false)
      </body>
      

      フレームワークによって blazor.server.js スクリプトがアプリに追加されます。 blazor.server.js スクリプト ファイルをアプリに手動で追加する必要はありません。

  2. 次の内容の 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}
    
  3. Blazor Server サービスを Startup.ConfigureServices に登録します。

    Startup.csの場合:

    services.AddServerSideBlazor();
    
  4. Blazor ハブ エンドポイントを app.UseEndpoints のエンドポイント (Startup.Configure) に追加します。

    Startup.cs:

    endpoints.MapBlazorHub();
    
  5. コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの Counter フォルダーに Shared コンポーネントを追加します。

    Pages/Shared/Counter.razor (Razor ページ) または 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 ページ:

    Index Pages アプリのプロジェクトの Razor ページで、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 コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    

    .NET 5.0.1 のリリースおよび追加の 5.x リリースでは、Router コンポーネントには、PreferExactMatchesに設定された @true パラメーターが含まれます。 詳細については、「 ASP.NET Core 3.1 から .NET 5 への移行」を参照してください。

  3. 次の内容の _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 のコンポーネント タグ ヘルパー」を参照してください。

  4. Startup.ConfigureStartup.cs エンドポイントで、_Host ページの優先度の低いルートを最後のエンドポイントとして追加します。

    endpoints.MapFallbackToPage("/_Host");
    

    次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    
  5. ルーティング可能なコンポーネントをプロジェクトに追加します。

    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++;
        }
    }
    
  6. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

MVC アプリでルーティング可能なコンポーネントを使用する

ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。

MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    

    .NET 5.0.1 のリリースおよび追加の 5.x リリースでは、Router コンポーネントには、PreferExactMatchesに設定された @true パラメーターが含まれます。 詳細については、「 ASP.NET Core 3.1 から .NET 5 への移行」を参照してください。

  3. 次の内容の _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 のコンポーネント タグ ヘルパー」を参照してください。

  4. Home コントローラーにアクションを追加します。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Startup.ConfigureStartup.cs エンドポイントに、_Host ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。

    endpoints.MapFallbackToController("Blazor", "Home");
    

    次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToController("Blazor", "Home");
    });
    
  6. ルーティング可能なコンポーネントをプロジェクトに追加します。

    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++;
        }
    }
    
  7. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

ページまたはビューからコンポーネントをレンダリングする

これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。

ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。

ステートフル対話型コンポーネントをレンダリングする

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 ファイルは、Pages Pages アプリの Razor フォルダーまたは 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) が向上します。

プロジェクトを構成した後、プロジェクトの要件に応じて、次のセクションのガイダンスを使用します。

設定

既存の Razor Pages または MVC アプリは、 Razor コンポーネントをページまたはビューに統合できます。

  1. プロジェクトのレイアウト ファイルで、次のようにします。

    • <base> (<head> Pages) または Pages/Shared/_Layout.cshtml (MVC) のRazor 要素に次の Views/Shared/_Layout.cshtml タグを追加します。

      + <base href="~/" />
      

      前の例の href 値 (アプリ ベースのパス) は、アプリがルート URL パス (/) に置かれていることを前提としています。 アプリがサブアプリケーションの場合は、 Core Blazor アプリのベース パス ASP.NET 参照してください。

    • <script> スクリプトの blazor.server.js タグを Scripts レンダリング セクションの直前に追加します。

      Pages/Shared/_Layout.cshtml (Razor ページ) または Views/Shared/_Layout.cshtml (MVC):

          ...
          <script src="_framework/blazor.server.js"></script>
      
          @await RenderSectionAsync("Scripts", required: false)
      </body>
      

      フレームワークによって blazor.server.js スクリプトがアプリに追加されます。 blazor.server.js スクリプト ファイルをアプリに手動で追加する必要はありません。

  2. 次の内容の 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}
    
  3. Blazor Server サービスを Startup.ConfigureServices に登録します。

    Startup.cs:

    services.AddServerSideBlazor();
    
  4. Blazor ハブ エンドポイントを app.UseEndpoints のエンドポイント (Startup.Configure) に追加します。

    Startup.cs:

    endpoints.MapBlazorHub();
    
  5. コンポーネントを任意のページまたはビューに統合します。 たとえば、プロジェクトの Counter フォルダーに Shared コンポーネントを追加します。

    Pages/Shared/Counter.razor (Razor ページ) または 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 ページ:

    Index Pages アプリのプロジェクトの Razor ページで、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 コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    
  3. 次の内容の _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 のコンポーネント タグ ヘルパー」を参照してください。

  4. Startup.ConfigureStartup.cs エンドポイントで、_Host ページの優先度の低いルートを最後のエンドポイントとして追加します。

    endpoints.MapFallbackToPage("/_Host");
    

    次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });
    
  5. ルーティング可能なコンポーネントをプロジェクトに追加します。

    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++;
        }
    }
    
  6. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

MVC アプリでルーティング可能なコンポーネントを使用する

ここは、ユーザー要求から直接ルーティング可能なコンポーネントを追加することに関係のあるセクションです。

MVC アプリでルーティング可能な Razor コンポーネントをサポートするには、次のようにします。

  1. 構成」セクションのガイダンスに従います。

  2. 次の内容の 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>
    
  3. 次の内容の _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 のコンポーネント タグ ヘルパー」を参照してください。

  4. Home コントローラーにアクションを追加します。

    Controllers/HomeController.cs:

    public IActionResult Blazor()
    {
       return View("_Host");
    }
    
  5. Startup.ConfigureStartup.cs エンドポイントに、_Host ビューを返すコントローラー アクションのために、優先度が低いルートを追加します。

    endpoints.MapFallbackToController("Blazor", "Home");
    

    次の例は、一般的なアプリのエンドポイント構成に追加された行を示しています。

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToController("Blazor", "Home");
    });
    
  6. ルーティング可能なコンポーネントをプロジェクトに追加します。

    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++;
        }
    }
    
  7. プロジェクトを実行し、RoutableCounter のルーティング可能な /routable-counter コンポーネントに移動します。

名前空間の詳細については、「コンポーネントの名前空間」セクションを参照してください。

ページまたはビューからコンポーネントをレンダリングする

これは、コンポーネントをユーザー要求から直接ルーティングできないページまたはビューにコンポーネントを追加することに関係するセクションです。

ページまたはビューからコンポーネントをレンダリングするには、コンポーネント タグ ヘルパーを使用します。

ステートフル対話型コンポーネントをレンダリングする

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 ファイルは、Pages Pages アプリの Razor フォルダーまたは MVC アプリの Views フォルダーにあります。

詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

プリレンダリングされた状態サイズと SignalR メッセージ サイズの制限

プリレンダリングされた状態サイズが大きい場合、 Blazorの SignalR 回線メッセージ サイズの制限を超える可能性があり、その結果、次のようになります。

  • この SignalR 回線は、クライアントで次のエラーで初期化に失敗します: Circuit host not initialized.
  • 回線が失敗状態になると、クライアント側に再接続 UI が表示されます。 復旧はできません。

この問題を解決するには、次の "いずれかの" 方法を使用します。

  • プリレンダリングされた状態に入れるデータの量を減らします。
  • SignalR メッセージ サイズの制限を増やします。 警告: 上限を引き上げると、サービス拒否 (DoS) 攻撃のリスクが高まる可能性があります。

Blazor Server のその他のリソース