ASP.NET Core MVCを初心者目線で解説するチュートリアルの第7回目です。
▼目次はこちら▼
今回はRazor文について解説します。ASP.NET Core MVCが開発される少し前、ASP.NET MVC Ver3ではじめて公開されたのがRazor文です。Razorは、「C#でHTML側のコーディングをする方法」と理解してもらえばOKです。つまり、フロントエンドとサーバーサイドの言語をC#でまとめることで、開発者の学習コストや保守コストを下げることが狙いです。
目次
なぜRazor文を使用するか
Razor文の最大の強みは、クライアント側のマークアップ(HTML)とサーバー側のコード(C#やVBなど)を混在させられることです。Razorでは、「@」を前に付けるだけで、サーバー側の変数などを参照できます。
@{
var name = "ちひろ";
}
<p>こんにちは、@name さん。今日は @DateTime.Now.ToString()です。</p>
他にも、Viewでif文を書く、foreachループをしてテーブルを作成するなど、様々な場面で活用します。
@if(Model.Title != null)
{
<h3>Controllerから @Model.Title が渡されました。</h3>
}
出力は以下のようになります。
Razor文はフロントエンド(HTML)にサーバーサイド言語(C#)で書くことでスマートにコーディングする方法です。ここでは、Razor文の基本から使用頻度の高いRazor文を学習していきましょう。
Razor文の前提
Razor文の基本は、変数名または関数名の前に「@」を付けることです。Visual Studioは「@」の有無でRazor文かどうかを認識します。また、複数行のRazor文を書けるコードブロック「@{ }」も便利です。Razor文を使用することでHTML要素、テキスト、Razor変数を次のように単純に組み合わせることができます。
@{ var name = "ちひろ"; } <p>こんにちは、@name さん。今日は @DateTime.Now.ToString()です。</p>
上記の式は、name変数と混合されたテキストを出力し、 DateTime構造体のNowプロパティから現在の日付にアクセスします。HTML要素とC#が混合しているのが分かると思います。
しかし、@は変数やクラスのプロパティにアクセスするためだけのものではありません。次の例に示すように、HTMLエンコーディング、コードブロック、コメントなど、Razorのほとんどすべてに使用されます。
HTMLエンコーディング
HTMLエンコーディングとは文字列内の「<」「>」「”」「&」などの予約文字を読み込む際、HTMLとして正しく表示させる方法です。
@{
var name= "<b>ちひろ</b>";
}
<p>こんにちは、@name さん。今日は @DateTime.Now.ToString()です。</p>
<p>こんにちは、@Html.Raw(name) さん。今日は @DateTime.Now.ToString()です。</p>
<b></b>は文字列を太字に設定するタグです。上記を実行すると、以下のようになります。
HTMLを文字列として出力するのではなく、太字でブラウザに解釈させるには、 HtmlクラスでRaw()メソッドを使います。
複数行のコードブロック
変数などに単にアクセスする以上のことを行う必要がある場合、Razorでは、@演算子の後に開始中括弧を入力することにより、専用の複数行のコードブロックを入力できます。次に例を示します。
@{
var sum = 32 + 10;
var greeting = "こんにちは!";
var text = "";
for(int i = 0; i < 3; i++)
{
if(i % 2 == 0){
sum += i;
}
text += greeting + " 計算結果: " + sum + "\n";
}
}
メッセージ: @text
結果は以下のようになります。
Razorサーバー側のコメント
コード内にコメントを残したり、一時的にコメントアウトしたりする際、Razor文では2種類のコメントを書く方法があります。HTMLでのコメント「@**@」とC#でのコメント「//と/* */」です。
HTMLコメントはブラウザにレンダリングされるため、[ソースの表示]、[要素の検証]で確認できてしまいます。一方で、C#のコメントはブラウザに表示されず、レンダリング時に無視されます。
Razor文の基本
上記の前提を踏まえた上で、Razor文の基本的な記述の仕方を確認していきます。
Razor変数
C#コードと同様に、Razorで変数を定義して、様々な場所で使用できます。コードスコープ内やif文内ではすぐに定義できます。名前を参照することで、コードブロック内外、HTMLのidやclassといった属性にも簡単に出力できます。また、C#の場合と同じように、変数を使って、ロジックを適用できます。
@{
int msgID = 1;
string Msg = "こんにちは";
if(DateTime.Now.Hour > 17)
{
Msg = "こんばんは";
}
Msg += "、みなさん";
Msg = Msg.ToUpper();
}
<div id="@msgID">
@Msg
</div>
Razorで変数を宣言して使用することは、非常に簡単で強力です。
if文
前例から何度も出ているため、詳しい解説は不要かと思いますが、Razorのif文はC#のif文と1点だけ違う点があります。それはif文の中に書く処理が1行しかない場合でも中括弧で囲む必要がある点です。つまり、下記のような書き方は出来ません。
//誤った記述方法
@if(Model.Title == "千と千尋の神隠し")
<p>映画のタイトルは千と千尋の神隠しです。</p>
正しい記述方法は以下となります。
//正しい記述方法
@if(Model.Title == "千と千尋の神隠し"){
<p>映画のタイトルは千と千尋の神隠しです。</p>
}
補足ですが、if-else文を書くこともできます。書き方はC#と同様です。
@if(Model.Title == "千と千尋の神隠し"){
<p>映画のタイトルは千と千尋の神隠しです。</p>
}else{
<p>映画のタイトルは千と千尋の神隠しではありません。</p>
}
else文も中括弧無しで書くことは出来ませんので、注意が必要です。
ループ文
RazorはC#と同様にループ処理を行えます。ループの方法は以下の4種類です。
- for
- foreach
- while
- do…while
ループ処理を確認するために、ループ用のリストを作成しますが、実際はControllerがDBからリストデータをViewに渡し、使用することがほとんどです。
@{
List<string> names = new List<string>()
{
"佐藤一郎",
"佐藤次郎",
"佐藤三郎",
"佐藤四郎",
"佐藤五郎"
};
}
「for」
forループは、カウント変数を用いてループ処理を記述します。
<ul>
@for (int i = 0; i < names.Count; i++)
{
<li>@names[i]</li>
}
</ul>
「foreach」
foreachループは、Listの要素すべてを1つずつ取得し、ループ処理してくれます。
<ul>
@foreach (string name in names)
{
<li>@name</li>
}
</ul>
「while」
whileループは、前置判定でループ処理を行います。つまり、一度もループ内の処理を経由しない場合もあります。
<ul>
@{
int counter = 0;
}
@while(counter < names.Count)
{
<li>@names[counter++]</li>
}
</ul>
「do…while」
do…whileループは、後置判定でループ処理を行います。つまり、必ず1度はループ内の処理を経由します。
<ul>
@{
counter = 0;
}
@do
{
<li>@names[counter++]</li>
} while (counter < names.Count);
</ul>
中断/続行
すべてのループに共通するのは、中断(break)と続行(continue)する機能です。これは、最大3つの名前を出力した後にループを確実に停止するforループの変更例です。
<ul>
@for (int i = 0; i < names.Count; i++)
{
<li>@names[i]</li>
@if(i >= 2)
{
<li>...など</li>
break;
}
}
</ul>
switch…case文
前述のRazor文ではif分を使用して条件分岐していましたが、Razor文を作成するときに使用できる条件式はif文だけではありません。それは、 switch…case文です。すでにC#や他のプログラミング言語で学んでいるかもしれませんが、Razor文での使い方を確認していきましょう。
switchステートメントは、評価する条件を定義してから、条件の1つまたは複数の可能な結果を定義することによって機能します。例えば、変数に指定した数値があり、その値に応じて処理を変更する場合、switchステートメントを使用すると次のようになります。
@switch(number)
{
case 0:
// 0の時にする処理
break;
case 1:
// 1の時にする処理
break;
case 2:
// 2の時にする処理
break;
}
Razorのswitch文はC#の場合と同じように見えますが、重大な違いもあります。それは、case内にHTMLを直接含めることができる点です。各caseではHTMLマークアップとテキストを簡単に出力できます。また、すでにRazorコードブロック内にいる場合以外では、前の例で見たように、switch-keywordの前に@文字を付ける必要があります。完全なスイッチの例を次に示します。
@switch(DateTime.Now.DayOfWeek)
{
case DayOfWeek.Monday:
<span>憂鬱な月曜日...</span>
break;
case DayOfWeek.Friday:
<span>華の金曜日!</span>
break;
case DayOfWeek.Saturday:
case DayOfWeek.Sunday:
<span>土日です。</span>
break;
default:
<span>平日です。</span>
break;
}
この例では、DateTime.NowのDayOfWeekプロパティを判定します。コードを見ると、月曜日と金曜日で処理が分岐しており、現在の曜日によって表示文字列が変わります。次に、同じcaseを使用する土曜日と日曜日があります。caseの判定を複数に増やすことができます。最後にdefaultを使用して、その他すべての条件を処理します。
ローカル関数
コードブロック内では、C#で実行できるほぼすべてのコーディングが可能です。それにはローカル関数を定義することも含まれます。ローカルのRazor関数を使用するとHTMLマークアップを含めることができるため、非常に便利です。例えば、同じマークアップを複数回生成する必要がある状況で役立ちます。ローカル関数は、アクセス修飾子(public、privateなど)がないことを除いて、クラスメソッドと同じです。例を見てみましょう。
@model HelloWorld.Models.Movie @{ void GetMovieInfo() { <div class="movie-info"> @Model.Title, @Model.ReleaseDate </div> } } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@Model.Title</title> </head> <body> @{ GetMovieInfo(); GetMovieInfo(); } </body> </html>
上記のコードを実行すると、以下のような出力結果が得られます。
ローカル関数(GetMovieInfo)のおかげで、同じHTMLマークアップを2回出力できるようになりました。同じHTMLマークアップを複数回書き込む必要はありません。また、ローカル関数に引数を渡すこともできます。
@model HelloWorld.Models.Movie @{ void GetMovieInfo() { <div class="movie-info"> @Model.Title, @Model.ReleaseDate </div> } void SetMovieInfo(string title, DateTime date) { ViewData["Title"] = title; ViewData["ReleaseDate"] = date; } } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@Model.Title</title> </head> <body> @{ GetMovieInfo(); SetMovieInfo("となりのトトロ", DateTime.Parse("1988-04-16")); } <p>@ViewData["Title"]</p> <p>@ViewData["ReleaseDate"]</p> </body> </html>>
ViewDataは後の章で詳しく説明しますが、ViewData[“任意の文字列”]とすることで、object型の変数として扱える記法です。それはさておき、SetMovieInfoに注目してください。string型のtitle、DateTime型のdateを引数にとり、ViewDataに渡します。つまり、<body>タグ内のSetMovieInfoで渡されたテキストと日付を渡すことで、ViewDataに値がセットされ、<p>タグ内のViewDataで値が返されます。
出力結果は以下のようになります。
戻り値のあるローカル関数
GetMovieInfoとSetMovieInfoは値を何も返さない(戻り値がvoidで宣言されている)ことに気付くでしょうが、戻り値のあるローカル関数を作成することも可能です。例文を見てみましょう。
@{
int SumFunc(int x, int y)
{
return x + y;
}
}
<div>
15 + 7 = @SumFunc(15, 7);
</div>
実際に足し算をするだけなら関数にする必要はなく、以下で十分です。
<div>15 + 7 = @{ var i = 15 + 7; }@i </div>
ローカルRazor関数を使用すると、現在のビューで使用できる関数を簡単に定義できます。
まとめ
以上でRazor文の基本的な使い方についての説明は終わりです。HTMLマークアップとC#コードを合わせてかける非常に便利な記法ですので、慣れていってくださいね。
次は、前記事でも説明したControllerについての詳細です。
コメント