お米 is ライス

C#やらUnityやらを勉強していて、これはメモっといたほうがええやろ、ということを書くつもりです

「ASP.NET Core Blazor」入門ハンドブック(を目指す)その2(Razor構文編)

前回の記事

spi8823.hatenablog.com

さて、前回はBlazor用のテンプレートプロジェクトを作成してデバッグ実行してみるというところまでやりました。
しかしこれだけでは何のありがたみも面白味もありません。
この記事では「BlazorによってどのようにHTML内にコードを埋め込むことができるのか」を説明します。

得られる知識

  • 「Razor構文」についての初歩的な知識
  • ボタンのイベントをC#によって記述する方法
  • C#の繰り返し文を利用してHTML要素を複数表示させる方法

前提知識

こういう技術的記事は前提とする知識をあらかじめ言っておくのがいいらしい。

  • C#で「for文」とか「if文」とか基本的なロジックを書くことができる
  • HTMLで文字列を表示したりボタンを表示することができる
  • JavaScriptでHTMLで表示したボタン押下時の処理を書くことができる
  • Webアプリケーションを作りかけたことがある

これくらいでしょうか。
この記事に興味がある人ならばだいたい大丈夫だと思います。

Razor構文

HTML内にC#を埋め込むための文法を「Razor構文」と呼びます。
この「Razor構文」というものはもともとかなり前からC#のWEBアプリケーションフレームワークである「ASP.NET」というものに含まれていたものです。
ただしこの時はRazor構文をあらかじめサーバー側で解釈してHTML+javascriptとしたものをブラウザに送っていたという程度のものだったようです(詳しくは知らないがまあ今となってはどうでもいいでしょう)

普通のHTML文書の中に「@」で始まるコードを書くとそれがC#のプログラムだと解釈されていろいろやってくれます。
例えば以下のように書くことができます。

@for(var i = 0;i < count;i++)
{
    <p>@i 番目の文字列</p>
}

このコードを見てもらうとだいたい雰囲気をつかんでもらえると思いますが、「@for」から始まる文がC#の繰り返し文で、その中に「<p>@i 番目の文字列</p>」といったようにHTMLを記述することができます。
さらにそのHTML要素の中でもC#の変数である「@i」という書き方ができるのもわかります。

このように、BlazorではRazor構文を使ってHTMLの中にC#コードを埋め込むことができます。
ちなみにBlazorというのも「Web」+「Razor」から来た造語らしいです。

Razorファイル

Razor構文はRazorファイルという「*.razor」という拡張子のついたファイルに記述する必要があります。
(「*.cshtml」というファイルも存在しますがこれはレガシーだという話をどこかで見た気がする)
この「*.razor」というファイルを一つのクラスとして考え、Razor構文ではそのメンバ関数やメンバ変数などを記述していくという解釈をすると考えやすいでしょう。

以下にこの記事で説明したい事項を詰め込んだRazorファイルを記述します。

例文

f:id:spi_8823:20191101010338p:plain
Sample.razor

見ての通りなんの感情も入っていないコードですが、以下ではこの例文をもとにしてRazor構文を見ていきます。

1行目「@page "/sample"」

「@page」で始まる記述のことを「pageディレクティブ」と呼んでいるようです。
このように書いて実行すると、例えば「localhost:12345/sample」というアドレスからこのRazorファイルによって記述されたページにアクセスすることができます。(12345の部分は環境に応じて変化します)
すなわち、pageディレクティブではページのルーティングを設定することができます。

2行目「@using System.Collections.Generic」

この行は通常のC#の「using」と同じことをしています。

4~13行目「@code { ~~ }」

この部分のように先頭に「@code」と記述し波かっこでくくったブロックによってメンバ変数やメンバ関数を定義することができます。

13行目で「StateHasChanged();」としていますが、これはもとからRazor構文内で利用することのできる関数で、ページ内の変数などが書き換えられたことを明示的に通知しページの再描画を促します。
これを記述せずとも自動で更新されることもありますが、どのようなタイミングで更新されるのかは把握できていないです。(おそらくボタンクリック時に更新するようになってる?)

15行目「

この部分ではHTMLのbutton要素を表示しています。
そして「@onclick = "AddText"」という部分ではボタンがクリックされた時のイベントにあらかじめ定義しておいた「AddText」という関数を設定しています。

17~20行目「@foreach { ~~ }」

この部分ではC#のforeach文を使ってメンバ変数である「Texts」の要素をそれぞれpタグによって出力しています。
「Texts」の中身はボタンクリック時に「AddText」関数で追加されていきますから、それと同時に行数が増えていきます。

実行結果

このファイルがある状態でデバッグ実行し、「~~/sample」へアクセスすると以下のようなページが表示されます。
f:id:spi_8823:20191101013322p:plain

ボタンを数回クリックすると以下のようになります。
f:id:spi_8823:20191101013056p:plain


次の記事ではRazor構文によって記述したものを別のRazorページから利用するRazorコンポーネントについて触れる予定です。

「ASP.NET Core Blazor」入門ハンドブック(を目指す)(インストール編)

Blazorとは

とにかくBlazorで「Hallo World」まで

この記事ではインストールから初めのデバッグ実行までを順を追って案内します。

Visual Studio 2019の最新版をインストール

visualstudio.microsoft.com
こことかからダウンロードしてインストールしましょう。
同じVS2019でもバージョンが古いものは対応していないので最新版に更新しましょう。
下の図のように「ASP.NETとWeb開発」の項目を含めてインストールすることに注意してください。
というかこの際「.NET Core」に関連するものは全部入れちゃったらどうよ?
f:id:spi_8823:20191024232914p:plain

「.NET Core 3.0」をインストール

dotnet.microsoft.com
.NET Core 3.0のランタイムをこことかからダウンロードしてインストールしましょう。
Visual Studioが正式に対応した今は必要ないかもしれません(未確認)。

「Blazor」プロジェクトを作成する

Visual Studio 2019を起動し、新しいプロジェクトの作成を選択
f:id:spi_8823:20191025000324p:plain

「新しいプロジェクトの作成」画面で「Blazorアプリ」を選択
f:id:spi_8823:20191025000545p:plain

プロジェクトの保存場所を指定する画面が表示されるので適当なプロジェクト名をつけて作成
f:id:spi_8823:20191025000656p:plain

「新しいBlazorアプリを作成します」と表示されるので、「Blazorサーバーアプリ」を選択して作成。
下の「Blazor WebAssembly」と書かれた2つはこの記事が執筆された時点では正式なリリースではないので無視してかまいません。
f:id:spi_8823:20191025000845p:plain


ここまですれば自動的に実行できるプロジェクトが作成されます。

デバッグ実行

いよいよ実行して動いているのを見て感動しましょう!
図で示した「IIS Express」と書かれたボタンをクリックしましょう。
f:id:spi_8823:20191025001412p:plain

すると……?ブラウザが立ち上がり、見事「Hallo, world!」と出力されたページが表示されています。
f:id:spi_8823:20191025001710p:plain

さて、このページがどこで書かれているかを少し覗いてみましょう。
プロジェクトの「Pages」というフォルダを見ると「Index.razor」というファイルが作られています。
f:id:spi_8823:20191025001850p:plain
このファイルに先ほど出力されていた文字列が記入されています。

これがブラウザで表示された「Hallo, world!」の正体、というわけです。
しかしこれだけではまだC#らしいことは何もしていません。
次の記事ではHTML内にC#を記述するための「Razor構文」について見ていきたいと思います。

次の記事
spi8823.hatenablog.com

EntityFrameworkCoreで整数とか日付とか以外のオブジェクトをフィールドに持つクラスをデータベースで管理したいときにやること

やりたいこと

例えば商品(Product)をデータベースで管理したくてかつ商品が会社(Company)の情報を持っていて欲しいとき。
つまりはクラスの入れ子になっているクラスをデータベース管理したいとき。
具体的に書くとこんなの

//商品クラス
public class Product
{
    public int ID { get; set; }
    public Company Maker { get; set; }
}

//会社クラス
public class Company
{
    public string Name { get; set; }
    public string Location { get; set; }
}

できない理由

これをこのままデータベースにマイグレーション(dotnet-ef migrations add hogehoge)しようとしても次のように怒られると思う。

The entity type 'Company' requires a primary key to be defined.
// Companyに主キーが無いぞ!出直してこい!!

これはCompanyというクラスを別のテーブルに突っ込んで管理しようとしてるからだ(と思う)が、わざわざそんなことしてくれんでもええのに……となる。

解決方法

要は別のテーブルにではなくProductのテーブルに突っ込んでくれればすむ話である。
EntityFrameworkCoreにはそのように指定する方法があって、次のようにすればよい

using Microsoft.EntityFrameworkCore;

public class Product
{
    public int ID { get; set; }
    public Company Maker { get; set; }
}

//この属性をつける
[Owned]
public class Company
{
    public string Name { get; set; }
    public string Location { get; set; }
}

親のテーブルに突っ込みたいクラスに「Owned」という属性をつけているだけである。
これを使うにはNugetとかでMicrosoft.EntityFrameworkCoreを入れておく必要がある。
こうすることによってProductのテーブルに「Maker_Name」とか「Maker_Location」とかのカラムが追加されてそこからMakerが読み取られるようになる。
Makerを別のテーブルに突っ込んでたりもしないので「Companyに主キーが必要だ!」とかも言われずにデータベースを作ることができる。

ASP.NET Core 3.0でRazorコンポーネントを使う方法

Razorコンポーネントとは

Windows Formsでいうコントロールみたいなものだと思う。
詳しくはこのページに書いてある。
docs.microsoft.com

Razorコンポーネントの作成

例えばHoge.razorというファイルを作成して次のように書く

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

//テキストボックスで表示
<input type="text" @bind="Text" />

こうすることでHogeというコンポーネントが作られたことになる。
[Parameter]という属性を付けた変数はこのコンポーネントを使用するときに外部からアクセスすることができる。
このコンポーネントは外部からTextという値に代入された文字列をテキストボックスに表示して編集できるようにしている。

Razorコンポーネントの使用

作成したHogeというコンポーネントを使用するには以下のようにすればよい。

@{
    //適当な文字列のリスト
    var texts = new List<string>();
    for(var i = 0;i < 5;i++)
    {
        texts.Add(i.ToString());
    }
}

@foreach(var text in texts)
{
    //Hogeというコンポーネントを使って文字列を入れたテキストボックスを表示
    <Hoge Text="text" />
}

見ればわかる通り、作成したRazorコンポーネントのファイル名を普通のHTMLタグと同じ感じで書くことでRazorコンポーネントを使うことができる。

ASP.NET Core 3.0ではこういう風にしてWEBアプリケーションを作っていくことになるのだと思う。
ちゃんと試したわけではないので多々間違っているところもあると思うが許してほしい。

WSL2(Windows Subsystem for Linux 2)に対応したDocker Desktopのプレビューが公開されたので使ってみる

はじめに

公式ブログのリンクだけ貼っておく
blog.docker.com

導入方法

1. Windows Insider Programに登録する

このあたりを見るヨロシ。
insider.windows.com
insider.windows.com

2. Windowsのビルドバージョンを最新のものにしてWSL2を有効にする

build versionが最低でも18932でないとダメだよ。
WSL2のインストール方法はこの辺りをみれ。
yukituna.com

3. Miscrosoft StoreからWSL用のUbuntu 18.04をインストールする

ここからインストールするだけ
www.microsoft.com

4. Docker Desktopをダウンロードしてインストールする!!!

https://download.docker.com/win/edge/36883/Docker%20Desktop%20Installer.exe

結果

って……、Windows Proじゃないといかんのか~~い!!!!
Hyper-VじゃなくてWSL2でLinuxカーネル使ってDockerが動かせるから家のWindows Homeでも動くじゃん!!って思ってたので肩透かしを喰らった感。
今後Windows Home向けに来ると信じて待つか……。

追記

この記事書いてから3カ月ほど経ったけどまだWindows Homeにインストールすることはできない模様。
どっかのgit issueとかで「WSL2で動いてるLinux上でDockerを動かすのがいいよ」って言ってたのでおとなしくそれに従いましょう。

ASP.NET Core 3.0+RazorでHTMLを描画する関数を作る方法

@helperとかHtmlHelperとかIHtmlContentとかいろいろ惑わされたのだけど、次のようにするとよさそう。

hoge.razor

@{
    //Hogeを表示する関数を定義する
    void Display(Hoge hoge)
    {
        <p>@hoge.Fuga</p>
    }
}

<p>Hello world</p>
<p>following is hoge list</p>
@{
    //定義した関数を使う側
    foreach(var hoge in hogeList)
    {
        Display(hoge);
    }
}

この書き方は以下のgithubのissueに書いてあった。
github.com

問題はこれをよそのrazorファイルから呼び出せるかだが、まあ大丈夫でしょう(まだ試してない)

追記

試しにDisplay関数をpublicにしたりpublic static にしたりしましたがエラーが出てコンパイルできないようです。
privateやprotectedでも同じことを言われるのでそもそもこれはrazor独特の書き方であり普通のC#と一緒には考えられなさそうです。

プライバシーポリシー

なんか書けって言われた

当サイトに掲載されている広告について

当サイトでは、第三者配信の広告サービス(Googleアドセンス)を利用しています。
このような広告配信事業者は、ユーザーの興味に応じた商品やサービスの広告を表示するため、当サイトや他サイトへのアクセスに関する情報 『Cookie』(氏名、住所、メール アドレス、電話番号は含まれません) を使用することがあります。

当サイトが使用しているアクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。
このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。
このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。