SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

.NET最新版でASP.NET Core

C#でSPAを実現! .NET 6でASP.NET CoreのBlazorアプリケーションの基本「Blazor Server」を理解しよう

.NET最新版でASP.NET Core 第7回


  • X ポスト
  • このエントリーをはてなブックマークに追加

BlazorServerプロジェクトの構成を理解する

 ここで、BlazorServerSampleプロジェクトがどのような構成になっているか、VSCodeのエクスプローラーで見てみましょう(図6)。

図07-06:BlazorServerSampleの初期プロジェクト構成
図6:BlazorServerSampleの初期プロジェクト構成

プロジェクトの構成

 プロジェクトには、Data、Pages、Shared、wwwrootなどのフォルダと、_Imports.razor、App.razor、Program.csなどのファイルがあります。wwwrootフォルダはRazor Pagesと共通ですので、第2回の該当箇所を参照してください。

Pagesフォルダ

 Blazorでは、ページを構成する要素はPagesフォルダに集約されています。Pagesフォルダには、Error.cshtml(.cs)といったRazorページと、Index.razorといったRazorコンポーネントの2種類のファイルが格納されます。

 Razorページは、Razor Pagesと同様にアプリケーションの各ページに対応するファイルです。このうち_Host.cshtmlと_Layout.cshtmlは、ファイル名がアンダースコア( _ )で始まることからもわかるように、特別な役割を持っています。前者は、フォールバックのためのページ、後者は各ページで共有するレイアウトです。

 Razorコンポーネントも、アプリケーションの各ページに対応するファイルですが、ページ遷移を伴わないBlazorでは、ページの一部を構成する部品という位置付けになっています。Razorコンポーネントは、それぞれがURLのパス情報を持ち、要求されたURLに対応するRazorコンポーネントでページを書き換えるといった処理が行われます。

[NOTE]RazorページはBlazor WebAssemblyには存在しない

 2つのRazorページはBlazor WebAssemblyには存在しません。Blazor WebAssemblyでは、たとえば共有レイアウトはwwwroot/index.htmlファイルが受け持っています。

Sharedフォルダ

 Sharedフォルダには、各ページで共有するRazorコンポーネントが置かれています。デフォルトレイアウトのためのMainLayout.razor、ナビゲーションメニューのためのNavMenu.razor、そしてindex.razorで読み込むコンポーネントであるSurveyPrompt.razorが既定で置かれます。

Dataフォルダ

 Dataフォルダは、データソースのためのフォルダです。データの入れ物としてのPOCO(WeatherForecast.cs)と、サービスの処理が書かれたクラスファイル(WeatherForecastService.cs)が置かれています。

Razorコンポーネントを見る

 Razorコンポーネントについて、具体的に見てみます。Razorコンポーネントでは、Razorページと同様にRazor構文を用いて内容を記述します。以下のリストは、サイドバーで[Counter]をクリックした際に呼び出されるCounterコンポーネントの内容です。

リスト Pages/Counter.razor
@page "/counter"	(1)

<PageTitle>Counter</PageTitle>	(2)

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>	(3)

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>	(4)

@code {		(5)
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}

 (1)は@pageディレクティブですが、Razorページと異なり値がパスとなっています。これは、Blazorにおけるルーティングの指定で、/counterがURLに指定された場合、このコンポーネントを呼び出すことを指定しています。(2)はページのタイトルの指定です。コンポーネントの呼び出しで、このタイトルでページのタイトルを書き換えます。

 (3)はモデル変数currentCountを参照してp要素で表示しています。(4)はボタンの指定ですが、onclick属性の指定でクリック時にIncrementCountメソッドを呼び出すことを指定しています。@onclickとなっているように、サーバーサイドの指定であることに注意してください。

 (5)以降は、@codeディレクティブで囲まれたコードブロックです。変数currentCountを初期化し、IncrementCountメソッドを実装しています。

 クライアントサイドで、JavaScriptを使って同様のコードを書けますが、ここではC#でサーバーサイドのコードを書いていることに注目してください。これなら、C#でサーバーサイドの開発経験があれば、無理なく入っていけることを理解していただけるのではないでしょうか?

データソースを見る

 FetchDataコンポーネント(Pages/FetchData.razorファイル)も上記と同様の構造です。ただし、こちらは表示するデータを外部から取得している点が異なります。以下のリストは、FetchData.razorでデータを取得している部分の抜粋です。

リスト Pages/FetchData.razor
private WeatherForecast[]? forecasts;

protected override async Task OnInitializedAsync()
{
    forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}

 OnInitializedAsyncという初期化メソッドの呼び出しにおいて、ForecastService.GetForecastAsyncメソッドを呼び出して、データを取得しています。このメソッドがどこで定義されているかというと、データソースであるData/WeatherForecastService.csファイルです。

リスト Data/WeatherForecastService.cs
public class WeatherForecastService
{
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"	(1)

    public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)		(2)
    {
        return Task.FromResult(Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = startDate.AddDays(index),
            TemperatureC = Random.Shared.Next(-20, 55),
            Summary = Summaries[Random.Shared.Next(Summaries.Length)]
        }).ToArray());
    }
}

 (1)は天気の概要の文字列です。(2)が、ForecastService.GetForecastAsyncメソッドの定義で、日付、乱数からなる気温、同じく乱数からなる天気の概要という、5個の要素を持つ配列を作成して返しています。この配列の内容を、Pages/FetchData.razorでは表示しているというわけです。

[NOTE]Blazor WebAssemblyではDataフォルダは存在しない

 Blazor WebAssemblyでは、データは外部サービスから取得するという前提です。そのため、Blazor WebAssemblyアプリケーションの既定では静的に用意されたダミーのデータを読み込んで表示するだけ、という動作になっています。

App.razor

 App.razorは、ルーティングのためのファイルです。ルーティング先があるときとないときの処理が既定で記述されています。

リスト App.razor
<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">		(1)
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>				(2)
        <PageTitle>Not found</PageTitle>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

 指定されたパスに一致するコンポーネントがあれば、(1)の記述に従ってレイアウトにMainLayoutコンポーネントを使用してレンダリングして表示します。一致するコンポーネントがない場合には、(2)の記述に従ってレイアウトにMainLayoutを使用した上でエラーメッセージ「Sorry, there's nothing at this address.」を表示します。MainLayoutは、Shared/MainLayout.cshtmlに記述されるレイアウトを意味します。

Program.cs

 最後のProgram.csは、アプリケーションの基点となるファイルです。Razor Pages、MVCと同様に、アプリケーションの起動ロジックを受け持ちます。リストはその抜粋です。

リスト Program.cs
…略…
builder.Services.AddSingleton<WeatherForecastService>();	(1)
…略…
app.MapFallbackToPage("/_Host");	(2)
app.Run();

 (1)は、Pages/FetchData.razorで使用されていたWeatherForecastServiceクラスを、シングルトンオブジェクトとして生成しています。(2)は、Pages/_Host.cshtmlをフォールバックページとしてマップしています。

 Blazorは、とにかく関連するファイルの種類や数が多いのですが、①App.razorでルーティングが合致した場合のレイアウト(MainLayoutコンポーネント)を指定、②MainLayoutコンポーネントでルートに対応するRazorコンポーネントを読み込み、③最終的なレンダリングは_layout.cshtmlに基づいて行う、という流れを理解しておけばよいでしょう。

まとめ

 今回は、対話型のWeb UI開発のためのフレームワークであるBlazorを、Blazor Serverを中心に見てきました。次回は、Blazorのバックエンドとも言えるWeb APIの開発を見ていきます。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
.NET最新版でASP.NET Core連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 山内 直(WINGSプロジェクト ヤマウチ ナオ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook <個人紹介> WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/16848 2023/05/26 17:13

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング