次の方法で共有


ページ、ルーティング、レイアウト

ヒント

このコンテンツは電子ブック、Azure の「ASP.NET Web Forms 開発者向け Blazor」からの抜粋です。これは .NET Docs から閲覧するか、オフラインで読める無料ダウンロードの PDF としても入手できます。

Blazor-for-ASP-NET-Web-Forms-Developers 電子ブックのカバー サムネイル。

ASP.NET Web フォーム アプリは、 .aspx ファイルで定義されたページで構成されます。 各ページのアドレスは、プロジェクト内の物理ファイル パスに基づいています。 ブラウザーがページに対して要求を行うと、ページの内容がサーバーに動的にレンダリングされます。 レンダリングは、ページの HTML マークアップとそのサーバー コントロールの両方を占めます。

Blazorでは、アプリ内の各ページはコンポーネントであり、通常は 1 つ以上の指定されたルートを持つ .razor ファイルで定義されます。 ルーティングは、ほとんどの場合、特定のサーバー要求を伴わずにクライアント側で行われます。 ブラウザーはまず、アプリのルート アドレスに対して要求を行います。 その後、Router アプリのルート Blazor コンポーネントは、ナビゲーション要求のインターセプトを処理し、正しいコンポーネントに転送します。

Blazor では、 ディープ リンクもサポートされています。 ディープ リンクは、ブラウザーがアプリのルート以外の特定のルートに対して要求を行うときに発生します。 サーバーに送信されたディープ リンクの要求は、 Blazor アプリにルーティングされ、要求クライアント側が正しいコンポーネントにルーティングされます。

ASP.NET Web フォームの単純なページには、次のマークアップが含まれている場合があります。

Name.aspx

<%@ Page Title="Name" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Name.aspx.cs" Inherits="WebApplication1.Name" %>

<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
    <div>
        What is your name?<br />
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Submit" OnClick="Button1_Click" />
    </div>
    <div>
        <asp:Literal ID="Literal1" runat="server" />
    </div>
</asp:Content>

Name.aspx.cs

public partial class Name : System.Web.UI.Page
{
    protected void Button1_Click1(object sender, EventArgs e)
    {
        Literal1.Text = "Hello " + TextBox1.Text;
    }
}

Blazor アプリの同等のページは次のようになります。

Name.razor

@page "/Name"
@layout MainLayout

<div>
    What is your name?<br />
    <input @bind="text" />
    <button @onclick="OnClick">Submit</button>
</div>
<div>
    @if (name != null)
    {
        @:Hello @name
    }
</div>

@code {
    string text;
    string name;

    void OnClick() {
        name = text;
    }
}

ページを作成する

Blazorでページを作成するには、コンポーネントを作成し、コンポーネントのルートを指定する @page Razor ディレクティブを追加します。 @page ディレクティブは 1 つのパラメーターを受け取ります。これは、そのコンポーネントに追加するルート テンプレートです。

@page "/counter"

ルート テンプレート パラメーターが必要です。 ASP.NET Web フォームとは異なり、 Blazor コンポーネントへのルートはファイルの場所から推測 されません (ただし、将来的に追加される機能になる可能性があります)。

ルート テンプレートの構文は、ASP.NET Web フォームでのルーティングに使用されるのと同じ基本構文です。 ルートパラメータはテンプレート内で中かっこを使用して指定されます。 Blazor では、ルート値が同じ名前のコンポーネント パラメーターにバインドされます (大文字と小文字は区別されません)。

@page "/product/{id}"

<h1>Product @Id</h1>

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

ルート パラメーターの値に制約を指定することもできます。 たとえば、製品 ID を intに制限するには、次のようにします。

@page "/product/{id:int}"

<h1>Product @Id</h1>

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

Blazorでサポートされているルート制約の完全な一覧については、「ルート制約」を参照してください。

ルーター コンポーネント

Blazorでのルーティングは、Router コンポーネントによって処理されます。 Router コンポーネントは、通常、アプリのルート コンポーネント (App.razor) で使用されます。

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

Router コンポーネントは、指定したAppAssemblyおよび必要に応じて指定したAdditionalAssemblies内のルーティング可能なコンポーネントを検出します。 ブラウザーが移動すると、Routerはナビゲーションをインターセプトし、ルートがアドレスと一致する場合は抽出されたFoundRouteData パラメーターの内容をレンダリングします。それ以外の場合、RouterNotFound パラメーターをレンダリングします。

RouteView コンポーネントは、RouteDataで指定された一致するコンポーネントをレイアウトと共にレンダリングします (存在する場合)。 一致したコンポーネントにレイアウトがない場合は、必要に応じて指定された DefaultLayout が使用されます。

LayoutView コンポーネントは、指定したレイアウト内でその子コンテンツをレンダリングします。 レイアウトについては、この章の後半で詳しく説明します。

ASP.NET Web フォームでは、ブラウザーにリダイレクト応答を返すことで、別のページへのナビゲーションをトリガーします。 例えば次が挙げられます。

protected void NavigateButton_Click(object sender, EventArgs e)
{
    Response.Redirect("Counter");
}

通常、 Blazorではリダイレクト応答を返すことはできません。 Blazor は要求/応答モデルを使用しません。 ただし、JavaScript の場合と同様に、ブラウザーのナビゲーションを直接トリガーすることもできます。

Blazor には、次の NavigationManager に使用できるサービスが用意されています。

  • 現在のブラウザー アドレスを取得する
  • ベース アドレスを取得する
  • ナビゲーションをトリガーする
  • アドレスが変更されたときに通知を受け取る

別のアドレスに移動するには、 NavigateTo メソッドを使用します。

@page "/"
@inject NavigationManager NavigationManager

<button @onclick="Navigate">Navigate</button>

@code {
    void Navigate() {
        NavigationManager.NavigateTo("counter");
    }
}

すべての NavigationManager メンバーの説明については、 URI とナビゲーション状態ヘルパーに関するページを参照してください。

ベース URL

Blazor アプリがベース パスの下にデプロイされている場合は、<base> タグを使用してページ メタデータのベース URL を指定して作業プロパティにルーティングする必要があります。 アプリのホスト ページが Razor を使用してサーバーレンダリングされる場合は、 ~/ 構文を使用してアプリのベース アドレスを指定できます。 ホスト ページが静的 HTML の場合は、ベース URL を明示的に指定する必要があります。

<base href="~/" />

ページのレイアウト

ASP.NET Web フォームのページ レイアウトはマスター ページによって処理されます。 マスター ページでは、1 つ以上のコンテンツ プレースホルダーを含むテンプレートを定義します。このプレースホルダーは、個々のページから提供できます。 マスター ページは .master ファイルで定義され、 <%@ Master %> ディレクティブで始まります。 .master ファイルのコンテンツは、.aspx ページと同様にコード化されますが、ページがコンテンツを提供できる場所をマークする<asp:ContentPlaceHolder> コントロールが追加されています。

Site.master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="WebApplication1.SiteMaster" %>

<!DOCTYPE html>
<html lang="en">
<head runat="server">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%: Page.Title %> - My ASP.NET Application</title>
    <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
</head>
<body>
    <form runat="server">
        <div class="container body-content">
            <asp:ContentPlaceHolder ID="MainContent" runat="server">
            </asp:ContentPlaceHolder>
            <hr />
            <footer>
                <p>&copy; <%: DateTime.Now.Year %> - My ASP.NET Application</p>
            </footer>
        </div>
    </form>
</body>
</html>

Blazorでは、レイアウト コンポーネントを使用してページ レイアウトを処理します。 レイアウト コンポーネントは、LayoutComponentBaseから継承されます。Body型の単一のRenderFragment プロパティを定義します。これは、ページの内容をレンダリングするために使用できます。

MainLayout.razor

@inherits LayoutComponentBase
<h1>Main layout</h1>
<div>
    @Body
</div>

レイアウトを含むページがレンダリングされると、指定したレイアウトのコンテンツ内で、レイアウトが Body プロパティをレンダリングする場所にページがレンダリングされます。

ページにレイアウトを適用するには、 @layout ディレクティブを使用します。

@layout MainLayout

_Imports.razor ファイルを使用して、フォルダーとサブフォルダー内のすべてのコンポーネントのレイアウトを指定できます。 Router コンポーネントを使用して、すべてのページの既定のレイアウトを指定することもできます。

マスター ページでは複数のコンテンツ プレースホルダーを定義できますが、 Blazor のレイアウトには 1 つの Body プロパティしかありません。 Blazorレイアウト コンポーネントのこの制限は、将来のリリースで解決される予定です。

ASP.NET Web フォームのマスター ページは入れ子にすることができます。 つまり、マスター ページでマスター ページを使用することもできます。 Blazorのレイアウト コンポーネントも入れ子になっている可能性があります。 レイアウト コンポーネントをレイアウト コンポーネントに適用できます。 内側のレイアウトの内容は、外側のレイアウト内にレンダリングされます。

ChildLayout.razor

@layout MainLayout
<h2>Child layout</h2>
<div>
    @Body
</div>

Index.razor

@page "/"
@layout ChildLayout
<p>I'm in a nested layout!</p>

ページのレンダリングされた出力は次のようになります。

<h1>Main layout</h1>
<div>
    <h2>Child layout</h2>
    <div>
        <p>I'm in a nested layout!</p>
    </div>
</div>

Blazorのレイアウトでは、通常、ページのルート HTML 要素 (<html><body><head>など) は定義されません。 ルート HTML 要素は、代わりに Blazor アプリのホスト ページで定義されます。これは、アプリの初期 HTML コンテンツをレンダリングするために使用されます ( ブートストラップ Blazorを参照)。 ホスト ページは、周囲のマークアップを含むアプリの複数のルート コンポーネントをレンダリングできます。

Blazor内のコンポーネント (ページを含む) では、<script>タグをレンダリングできません。 このレンダリング制限は、 <script> タグが 1 回読み込まれてから変更できないために存在します。 Razor 構文を使用してタグを動的にレンダリングしようとすると、予期しない動作が発生する可能性があります。 代わりに、すべての <script> タグをアプリのホスト ページに追加する必要があります。