📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の3版が非表示) | |||
| 60行目: | 60行目: | ||
<br> | <br> | ||
なお、<code>@page</code>ディレクティブで明示的にルートを指定した場合は、この規約が上書きされる。<br> | なお、<code>@page</code>ディレクティブで明示的にルートを指定した場合は、この規約が上書きされる。<br> | ||
<br><br> | |||
== レンダーフラグメント == | |||
レンダーフラグメントは、UIの一部を表すデリゲート型であり、コンポーネント間でコンテンツを受け渡すための仕組みである。<br> | |||
これは、JSXのchildren propやReactのprops.childrenに相当する概念である。<br> | |||
<br> | |||
また、<code>@Body</code>は、このレンダーフラグメントの特別な実装である。<br> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
[Parameter] | |||
public RenderFragment CustomContent { get; set; } | |||
// 使用例 | |||
<div> | |||
@CustomContent | |||
</div> | |||
</syntaxhighlight> | |||
<br> | |||
レンダーフラグメントは、Blazorにおける重要な型であり、以下に示す用途で使用される。<br> | |||
<syntaxhighlight lang="c#"> | |||
// LayoutComponentBaseクラスでの定義 | |||
public RenderFragment Body { get; set; } | |||
// カスタムコンポーネントでの使用例 | |||
[Parameter] | |||
public RenderFragment ChildContent { get; set; } | |||
// テンプレート用途での使用例 | |||
[Parameter] | |||
public RenderFragment<TItem> ItemTemplate { get; set; } | |||
</syntaxhighlight> | |||
<br> | |||
==== @Body ==== | |||
<code>@Body</code>は、レイアウトコンポーネント内でページコンテンツを表示する場所を指定するプレースホルダーである。<br> | |||
<br> | |||
@Bodyは、レイアウトを使用する各ページのコンテンツが配置される場所を示す。<br> | |||
<br> | |||
例えば、以下に示すようなページコンポーネントが存在する場合<br> | |||
<syntaxhighlight lang="c#"> | |||
// MainLayout.razorファイル | |||
<div class="page"> | |||
<div class="sidebar"> | |||
<NavMenu /> | |||
</div> | |||
<main> | |||
<div class="content"> | |||
@Body | |||
</div> | |||
</main> | |||
</div> | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// Pages/Counter.razorファイル | |||
@page "/counter" | |||
<h1>Counter</h1> | |||
<p>Current count: @currentCount</p> | |||
<button @onclick="IncrementCount">Click me</button> | |||
@code { | |||
private int currentCount = 0; | |||
private void IncrementCount() => currentCount++; | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
上記のCounter.razorファイルの内容が、MainLayout.razorファイルの@Body部分に展開されて表示される。<br> | |||
<syntaxhighlight lang="c#"> | |||
// MainLayout.razorファイル | |||
<div class="page"> | |||
<div class="sidebar"> | |||
<NavMenu /> | |||
</div> | |||
<main> | |||
<div class="content"> | |||
// ここに、Counter.razorファイルの内容が展開される | |||
<h1>Counter</h1> | |||
<p>Current count: 0</p> | |||
<button>Click me</button> | |||
</div> | |||
</main> | |||
</div> | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
| 291行目: | 377行目: | ||
== レイアウトの適用 == | == レイアウトの適用 == | ||
Blazorのルーティングでは、レイアウト機能も重要である。<br> | |||
レイアウト機能により、共通のUIパーツを効率的に管理でき、ページごとに異なるレイアウトを適用することができる。<br> | |||
<br> | |||
_Imports.razorファイルにおいて、デフォルトレイアウトを指定して、必要に応じて個別のコンポーネントで<code>@layout</code>指示子を使用して上書きすることができる。<br> | _Imports.razorファイルにおいて、デフォルトレイアウトを指定して、必要に応じて個別のコンポーネントで<code>@layout</code>指示子を使用して上書きすることができる。<br> | ||
<br> | |||
==== 基本的なレイアウトファイルの構造 ==== | |||
<syntaxhighlight lang="c#"> | |||
// MainLayout.razorファイル | |||
@inherits LayoutComponentBase | |||
<div class="page"> | |||
<div class="sidebar"> | |||
<NavMenu /> | |||
</div> | |||
<main> | |||
<div class="content"> | |||
@Body | |||
</div> | |||
</main> | |||
</div> | |||
</syntaxhighlight> | |||
<br> | |||
==== _Imports.razorでのデフォルトレイアウト指定 ==== | |||
<syntaxhighlight lang="c#"> | |||
@using System.Net.Http | |||
@using Microsoft.AspNetCore.Components.Forms | |||
@using Microsoft.AspNetCore.Components.Routing | |||
@using Microsoft.AspNetCore.Components.Web | |||
@layout MainLayout // デフォルトレイアウトの指定 | |||
</syntaxhighlight> | |||
<br> | |||
==== 個別コンポーネントでのレイアウト上書き ==== | |||
<syntaxhighlight lang="c#"> | |||
// Pages/AdminPage.razorファイル | |||
@layout AdminLayout // このコンポーネントのみ異なるレイアウトを使用 | |||
@page "/admin" | |||
<h1>管理画面</h1> | |||
</syntaxhighlight> | |||
<br> | |||
==== 入れ子レイアウトの例 ==== | |||
<syntaxhighlight lang="c#"> | |||
// AdminLayout.razorファイル | |||
@inherits LayoutComponentBase | |||
<div class="admin-layout"> | |||
<nav class="admin-nav"> | |||
<AdminMenu /> | |||
</nav> | |||
<div class="admin-content"> | |||
@Body | |||
</div> | |||
</div> | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
| 298行目: | 441行目: | ||
404エラー等のルーティングエラーは、App.razorで設定したNotFoundテンプレートによって処理される。<br> | 404エラー等のルーティングエラーは、App.razorで設定したNotFoundテンプレートによって処理される。<br> | ||
これにより、ユーザフレンドリーなエラー画面を表示することが可能である。<br> | これにより、ユーザフレンドリーなエラー画面を表示することが可能である。<br> | ||
<br> | |||
例えば、NotFoundセクションをカスタマイズすることにより、より使用しやすいエラー画面を提供することができる。<br> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// App.razorファイル | |||
<Router AppAssembly="@typeof(App).Assembly"> | |||
<Found Context="routeData"> | |||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> | |||
</Found> | |||
<NotFound> | |||
<PageTitle>Not found</PageTitle> | |||
<LayoutView Layout="@typeof(MainLayout)"> | |||
<div class="alert alert-danger"> | |||
<h3>ページが見つかりません</h3> | |||
<p>申し訳ありません。要求されたページは存在しません。</p> | |||
<a href="/" class="btn btn-primary">ホームに戻る</a> | |||
</div> | |||
</LayoutView> | |||
</NotFound> | |||
</Router> | |||
</syntaxhighlight> | |||
<br> | |||
==== カスタム404ページ ==== | |||
<syntaxhighlight lang="c#"> | |||
// Pages/CustomNotFound.razorファイル | |||
@inject NavigationManager NavigationManager | |||
<div class="error-container"> | |||
<h2>404 - ページが見つかりません</h2> | |||
<p>リクエストされたURL: @NavigationManager.Uri</p> | |||
<div class="error-actions"> | |||
<button @onclick="GoBack">前のページに戻る</button> | |||
<a href="/" class="btn">ホームページへ</a> | |||
</div> | |||
</div> | |||
@code { | |||
private void GoBack() | |||
{ | |||
NavigationManager.NavigateTo(NavigationManager.Uri); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
上記のファイルをApp.razorファイルで使用する。<br> | |||
<syntaxhighlight lang="c#"> | |||
// App.razorファイル | |||
<NotFound> | |||
<LayoutView Layout="@typeof(MainLayout)"> | |||
<CustomNotFound /> | |||
</LayoutView> | |||
</NotFound> | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
== 認証 / 認可 == | == 認証 / 認可 == | ||
<code>[Authorize]</code>属性を使用することにより、特定のルートへのアクセスを制限することができる。<br> | <code>[Authorize]</code>属性を使用することにより、特定のルートへのアクセスを制限することができる。<br> | ||
<br> | |||
==== 基本的な認証要求 ==== | |||
<syntaxhighlight lang="c#"> | |||
@page "/secured-page" | |||
[Authorize] | |||
public class SecuredPageBase : ComponentBase | |||
{ | |||
// このページは認証済みユーザーのみアクセス可能 | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 特定のロールに基づく認証 ==== | |||
<syntaxhighlight lang="c#"> | |||
@page "/admin-page" | |||
[Authorize(Roles = "Admin")] | |||
public class AdminPageBase : ComponentBase | |||
{ | |||
// 管理者ロールを持つユーザーのみアクセス可能 | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 複数のロールの指定 ==== | |||
<syntaxhighlight lang="c#"> | |||
[Authorize(Roles = "Admin,Manager")] | |||
// ポリシーベースの認証 | |||
[Authorize(Policy = "RequireAdminRole")] | |||
// カスタム認証要件 | |||
[Authorize(Policy = "MinimumAgeRequirement")] | |||
</syntaxhighlight> | |||
<br> | |||
==== Program.csでの認証サービスの設定 ==== | |||
<syntaxhighlight lang="c#"> | |||
builder.Services.AddAuthentication().AddCookie(); | |||
builder.Services.AddAuthorization(options => | |||
{ | |||
options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin")); | |||
options.AddPolicy("MinimumAgeRequirement", policy => policy.Requirements.Add(new MinimumAgeRequirement(18))); | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
==== 認証状態の確認と処理 ==== | |||
<syntaxhighlight lang="c#"> | |||
@inject AuthenticationStateProvider AuthenticationStateProvider | |||
@code { | |||
private async Task<bool> IsUserAuthenticated() | |||
{ | |||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); | |||
return authState.User.Identity.IsAuthenticated; | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||