ASP.NET Core の Razor 構文リファレンス

作成者: Rick AndersonTaylor MullenDan Vicarel

Razor は、Web ページに .NET ベースのコードを埋め込むためのマークアップ構文です。 Razor 構文は、Razor マークアップ、C#、HTML で構成されます。 通常、Razor を含むファイルには、ファイル拡張子 .cshtml が付いています。 Razor は、Razorコンポーネント ファイル (.razor) にも含まれています。 Razor の構文は、Angular、React、VueJs、Svelte などのさまざまな JavaScript シングルページ アプリケーション (SPA) フレームワークのテンプレート エンジンに似ています。 詳細については、「JavaScript Services を使用して ASP.NET Core でシングル ページ アプリケーションを作成する」を参照してください。

Razor 構文を使用した ASP.NET Web プログラミングの概要」では、Razor 構文を使用したプログラミングのサンプルが多数提供されています。 このトピックは ASP.NET Coreではなく ASP.NET 用に記述されていますが、ほとんどのサンプルは ASP.NET Coreに適用されます。

HTML のレンダリング

既定の Razor 言語は、HTML です。 Razor マークアップからの HTML のレンダリングは、HTML ファイルからの HTML のレンダリングと同じです。 ファイル内の .cshtmlRazor HTML マークアップは、サーバーによって変更されずにレンダリングされます。

Razor の構文

Razor では、C# がサポートされており、@ シンボルを使用して HTML を C# に移行します。 Razor では、C# の式を評価し、それらを HTML 出力にレンダリングします。

@ シンボルの後に Razor予約キーワードが続いている場合は、Razor 固有のマークアップに移行します。 それ以外の場合は、プレーン HTML に移行します。

@ マークアップで @ シンボルをエスケープするには、2 つ目の Razor シンボルを使用します。

<p>@@Username</p>

HTML では、コードは 1 つの @ 記号でレンダリングされます。

<p>@Username</p>

メール アドレスを含む HTML の属性とコンテンツは、@ 記号を遷移文字として扱いません。 次の例のメール アドレスは、Razor の解析ではそのまま残ります。

<a href="mailto:Support@contoso.com">Support@contoso.com</a>

スケーラブル ベクター グラフィックス (SVG)

SVGforeignObject 要素がサポートされています。

@{
    string message = "foreignObject example with Scalable Vector Graphics (SVG)";
}

<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
    <rect x="0" y="0" rx="10" ry="10" width="200" height="200" stroke="black" 
        fill="none" />
    <foreignObject x="20" y="20" width="160" height="160">
        <p>@message</p>
    </foreignObject>
</svg>

暗黙的な Razor 式

暗黙的な Razor 式は、@ で始まり、その後に C# コードが続きます。

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>

C# の await キーワードを除き、暗黙的な式にスペースを含めることはできません。 C# のステートメントに明確な終わりがある場合は、スペースを混在させることができます。

<p>@await DoSomething("hello", "world")</p>

暗黙的な式では、山かっこ (<>) の内側の文字は HTML タグとして解釈されるため、C# ジェネリックを含めることはできません。 次のコードは有効ではありません

<p>@GenericMethod<int>()</p>

上記のコードでは、次のいずれかのようなコンパイラ エラーが生成されます。

  • The "int" element wasn't closed. All elements must be either self-closing or have a matching end tag. ("int" 要素が閉じられませんでした。すべての要素は、自己終了するか、対応する終了タグが存在する必要があります。)
  • メソッド グループ 'GenericMethod' を非デリゲート型 'object' に変換することはできません。 このメソッドを呼び出しますか?

ジェネリック メソッド呼び出しは、明示的な Razor 式またはRazorコード ブロックでラップする必要があります。

明示的な Razor 式

明示的な Razor 式は、@ シンボルと、バランスの取れたかっこで構成されます。 1 週間前の時刻を表示するには、次の Razor マークアップを使用します。

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

@() のかっこ内の内容が評価されて、出力にレンダリングされます。

前のセクションで説明した暗黙的な式は、一般に、スペースを含むことはできません。 次のコードでは、現在時刻から 1 週間は減算されません。

<p>Last week: @DateTime.Now - TimeSpan.FromDays(7)</p>

このコードでは、次のような HTML がレンダリングされます。

<p>Last week: 7/7/2016 4:39:52 PM - TimeSpan.FromDays(7)</p>

明示的な式を使うと、テキストと式の結果を連結できます。

@{
    var joe = new Person("Joe", 33);
}

<p>Age@(joe.Age)</p>

明示的な式を使わないと、<p>Age@joe.Age</p> はメール アドレスとして扱われ、<p>Age@joe.Age</p> がレンダリングされます。 明示的な式として記述すると、<p>Age33</p> がレンダリングされます。

明示的な式を使用して、ジェネリック メソッドの出力を .cshtml ファイルにレンダリングできます。 次のマークアップは、C# ジェネリックの山かっこによって発生した前述のエラーを修正する方法について示します。 コードは明示的な式として書き込まれます。

<p>@(GenericMethod<int>())</p>

式のエンコード

文字列として評価される C# の式は、HTML でエンコードされます。 IHtmlContent として評価される C# の式は、IHtmlContent.WriteTo によって直接レンダリングされます。 IHtmlContent として評価されない C# の式は、ToString によって文字列に変換され、レンダリングされる前にエンコードされます。

@("<span>Hello World</span>")

上記のコードにより、次の HTML がレンダリングされます。

&lt;span&gt;Hello World&lt;/span&gt;

この HTML は、ブラウザーでプレーンテキストとして表示されます。

<span>Hello World</span>

HtmlHelper.Raw の出力はエンコードされませんが、HTML マークアップとしてレンダリングされません。

警告

サニタイズされていないユーザー入力で HtmlHelper.Raw を使うと、セキュリティ上のリスクがあります。 ユーザー入力には、悪意のある JavaScript または他の攻撃が含まれる可能性があります。 ユーザー入力をサニタイズすることは困難です。 ユーザー入力では HtmlHelper.Raw を使わないでください。

@Html.Raw("<span>Hello World</span>")

このコードでは、次のような HTML がレンダリングされます。

<span>Hello World</span>

Razor コード ブロック

RazorRazor コード ブロックは、@ で始まり、{} で囲まれます。 式とは異なり、コード ブロック内の C# コードはレンダリングされません。 ビュー内のコード ブロックと式は同じスコープを共有し、次の順序で定義されます。

@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>

@{
    quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
}

<p>@quote</p>

このコードでは、次のような HTML がレンダリングされます。

<p>The future depends on what you do today. - Mahatma Gandhi</p>
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>

コード ブロックで、るローカル関数をマークアップで宣言し、テンプレート メソッドとしてのサービスを提供します。

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

このコードでは、次のような HTML がレンダリングされます。

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

暗黙の移行

コード ブロックの既定の言語は C# ですが、Razor Page は、HTML に移行されて戻る場合があります。

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

明示的に区切られた遷移

HTML をレンダリングする必要があるコード ブロックのサブセクションを定義するには、レンダリングする文字をタグで Razor<text> 囲みます。

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

HTML タグによって囲まれていない HTML をレンダリングするには、この方法を使います。 HTML または Razor タグがない場合、Razor ランタイム エラーが発生します。

<text> タグは、内容をレンダリングするときに空白文字を制御するのに便利です。

  • <text> タグの間の内容だけがレンダリングされます。
  • <text> タグの前後にある空白文字は HTML の出力には表示されません。

明示的な行の遷移

残りの行全体をコード ブロック内に HTML としてレンダリングするには、@: 構文を使います。

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}

コードに @: がない場合、Razor ランタイム エラーが生成されます。

Razor ファイルに余分な @ 文字があると、ブロックの後続のステートメントでコンパイラ エラーが発生することがあります。 これらのコンパイラ エラーは、実際のエラーは報告されたエラーより前で発生しているため、理解するのが難しい場合があります。 このエラーは、複数の暗黙的/明示的な式を 1 つのコード ブロックに結合した後で発生することがよくあります。

制御構造

制御構造は、コード ブロックの拡張機能です。 コード ブロックのすべての側面 (マークアップへの遷移、インライン C# ) が、次の構造にも適用されます。

条件 @if, else if, else, and @switch

@if は、いつコードを実行するかを制御します。

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}

else および else if には、@ 記号は必要ありません。

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}

次のマークアップでは、switch ステートメントの使い方を示します。

@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

ループ @for, @foreach, @while, and @do while

ループ制御ステートメントを使って、テンプレート化された HTML をレンダリングできます。 人の一覧をレンダリングするには:

@{
    var people = new Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}

以下のループ ステートメントがサポートされています。

@for

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@foreach

@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}

@while

@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
}

@do while

@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
} while (i < people.Length);

複合 @using

C# では、オブジェクトを確実に破棄するために using オブジェクトが使われています。 Razor では、追加コンテンツを含む HTML ヘルパーを作成するために同じメカニズムが使用されます。 次のコードの HTML ヘルパーは、@using ステートメントを含む <form> タグをレンダリングします。

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

@try, catch, finally

例外処理は C# に似ています。

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock

Razor には、重要なセクションを lock ステートメントで保護する機能があります。

@lock (SomeLock)
{
    // Do critical section work
}

説明

Razor では、C# と HTML のコメントがサポートされます。

@{
    /* C# comment */
    // Another C# comment
}
<!-- HTML comment -->

このコードでは、次のような HTML がレンダリングされます。

<!-- HTML comment -->

Razor のコメントは、Web ページがレンダリングされる前に、サーバーによって削除されます。 Razor では、@* *@ を使用してコメントを区切ります。 次のコードはコメント化されているため、サーバーはどのマークアップもレンダリングしません。

@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

ディレクティブ

Razor のディレクティブは、@ シンボルの後の予約キーワードによる暗黙的な式によって表されます。 通常、ディレクティブは、ビューの解析方法を変更したり、異なる機能を有効にしたりします。

Razor でビューのコードが生成される方法を理解すると、ディレクティブの動作を理解しやすくなります。

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

上のコードでは、次のようなクラスが生成されます。

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

この記事で後述する「ビューに対して生成された Razor C# クラスを検査する」セクションでは、この生成されたクラスを表示する方法について説明します。

@attribute

@attribute ディレクティブでは、指定された属性が生成されたページまたはビューのクラスに追加されます。 次の例では、[Authorize] 属性が追加されます。

@attribute [Authorize]

@code

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@code ブロックにより、Razor コンポーネントでは、C# メンバー (フィールド、プロパティ、メソッド) をコンポーネントに追加できます。

@code {
    // C# members (fields, properties, and methods)
}

Razor コンポーネントの場合、@code@functions のエイリアスであり、@functions よりも優先されます。 複数の @code ブロックが許容されます。

@functions

@functions ディレクティブでは、生成されたクラスに C# メンバー (フィールド、プロパティ、メソッド) を追加できます。

@functions {
    // C# members (fields, properties, and methods)
}

Razor コンポーネントでは、@functions ではなく @code を使用して C# メンバーを追加します。

次に例を示します。

@functions {
    public string GetHello()
    {
        return "Hello";
    }
}

<div>From method: @GetHello()</div> 

このコードは、次の HTML マークアップを生成します。

<div>From method: Hello</div>

次のコードは、生成された Razor C# クラスです。

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Razor;

public class _Views_Home_Test_cshtml : RazorPage<dynamic>
{
    // Functions placed between here 
    public string GetHello()
    {
        return "Hello";
    }
    // And here.
#pragma warning disable 1998
    public override async Task ExecuteAsync()
    {
        WriteLiteral("\r\n<div>From method: ");
        Write(GetHello());
        WriteLiteral("</div>\r\n");
    }
#pragma warning restore 1998

@functions メソッドは、マークアップが与えられているとき、テンプレート メソッドとしてサービスを提供します。

@{
    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

@functions {
    private void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }
}

このコードでは、次のような HTML がレンダリングされます。

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

@implements

@implements ディレクティブでは、生成されたクラスのインターフェイスが実装されます。

次の例では、Dispose メソッドを呼び出せるように、System.IDisposable が実装されます。

@implements IDisposable

<h1>Example</h1>

@functions {
    private bool _isDisposed;

    ...

    public void Dispose() => _isDisposed = true;
}

@inherits

@inherits ディレクティブは、ビューが継承するクラスの完全な制御を提供します。

@inherits TypeNameOfClassToInheritFrom

次のコードは、カスタム Razor ページ型です。

using Microsoft.AspNetCore.Mvc.Razor;

public abstract class CustomRazorPage<TModel> : RazorPage<TModel>
{
    public string CustomText { get; } = 
        "Gardyloo! - A Scottish warning yelled from a window before dumping" +
        "a slop bucket on the street below.";
}

CustomText がビューに表示されます。

@inherits CustomRazorPage<TModel>

<div>Custom text: @CustomText</div>

このコードでは、次のような HTML がレンダリングされます。

<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@model@inherits は同じビューで使うことができます。 @inherits は、ビューでインポートされる _ViewImports.cshtml ファイルに含めることができます。

@inherits CustomRazorPage<TModel>

次のコードは、厳密に型指定されたビューの例です。

@inherits CustomRazorPage<TModel>

<div>The Login Email: @Model.Email</div>
<div>Custom text: @CustomText</div>

モデルに rick@contoso.com が渡された場合、ビューは次の HTML マークアップを生成します。

<div>The Login Email: rick@contoso.com</div>
<div>
    Custom text: Gardyloo! - A Scottish warning yelled from a window before dumping
    a slop bucket on the street below.
</div>

@inject

@inject ディレクティブを使用すると、Razor Page でサービスをサービス コンテナーからビューに挿入できます。 詳しくは、「ビューへの依存関係の挿入」をご覧ください。

@layout

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@layout ディレクティブでは、@page ディレクティブを含むルーティング可能な Razor コンポーネントのレイアウトを指定します。 レイアウト コンポーネントは、コードの重複や不整合を回避するために使用されます。 詳細については、「ASP.NET CoreBlazorレイアウト」を参照してください。

@model

"このシナリオは、MVC ビューと Razor Page (.cshtml) にのみ適用されます。 "

@model ディレクティブにより、ビューまたはページに渡されるモデルの型が指定されます。

@model TypeNameOfModel

個々のユーザー アカウントを使用して作成された ASP.NET Core MVC または Razor Pages アプリでは、Views/Account/Login.cshtml に次のモデル宣言が含まれています。

@model LoginViewModel

生成されるクラスは、RazorPage<LoginViewModel> を継承します。

public class _Views_Account_Login_cshtml : RazorPage<LoginViewModel>

Razor では、ビューに渡されるモデルにアクセスするための Model プロパティが公開されています。

<div>The Login Email: @Model.Email</div>

@model ディレクティブにより、Model プロパティの型が指定されます。 ディレクティブでは、ビューが派生する生成されたクラスの TRazorPage<T> で指定します。 @model ディレクティブが指定されていない場合、Model プロパティは dynamic 型になります。 詳細については、「Strongly typed models and the @model keyword」を参照してください。

@namespace

@namespace ディレクティブ:

  • 生成された Razor ページ、MVC ビュー、または Razor コンポーネントのクラスの名前空間を設定します。
  • ディレクトリ ツリー、(ビューまたはページ) または (コンポーネント) 内の最も近いインポート ファイルから、ページ、ビュー、 _ViewImports.cshtml または_Imports.razorRazorコンポーネント クラスのルート派生名前空間を設定します。
@namespace Your.Namespace.Here

次の表に示す Razor Pages の例の場合:

  • 各ページでは、Pages/_ViewImports.cshtml がインポートされます。
  • Pages/_ViewImports.cshtml には、@namespace Hello.World が含まれます。
  • 各ページには、その名前空間のルートとして Hello.World が含まれます。
ページ 名前空間
Pages/Index.cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Hello.World.MorePages.EvenMorePages

前述のリレーションシップは、MVC ビューおよび Razor コンポーネントで使用されるインポート ファイルに適用されます。

複数のインポート ファイルに @namespace ディレクティブがあるとき、ディレクトリ ツリーでページ、ビュー、またはコンポーネントに最も近いファイルがルート名前空間の設定に使用されます。

前述の例の EvenMorePages フォルダーに、@namespace Another.Planet が含まれたインポート ファイルがある場合 (または Pages/MorePages/EvenMorePages/Page.cshtml ファイルに @namespace Another.Planet が含まれている場合) の結果を次の表に示します。

ページ 名前空間
Pages/Index.cshtml Hello.World
Pages/MorePages/Page.cshtml Hello.World.MorePages
Pages/MorePages/EvenMorePages/Page.cshtml Another.Planet

@page

@page ディレクティブには、それが表示されるファイルの型によって、さまざまな効果があります。 ディレクティブ:

@preservewhitespace

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

false (既定) に設定すると、Razor コンポーネント (.razor) からレンダリングされたマークアップ内の空白は、次の場合に削除されます。

  • 要素内の先頭または末尾。
  • RenderFragment パラメーター内の先頭または末尾。 別のコンポーネントに渡される子コンテンツなどです。
  • @if または @foreach のような、C# コード ブロックの前か後にある。

@section

"このシナリオは、MVC ビューと Razor Page (.cshtml) にのみ適用されます。 "

@section ディレクティブを MVC および Razor Pages レイアウトと組み合わせて使用すると、HTML ページのさまざまな部分のコンテンツをビューやページでレンダリングできます。 詳細については、「ASP.NET Core でのレイアウト」をご覧ください。

@using

@using ディレクティブは、生成されるビューに C# の using ディレクティブを追加します。

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

Razor コンポーネントでは、@using により、スコープ内のコンポーネントも制御されます。

ディレクティブ属性

Razor のディレクティブ属性は、@ シンボルの後に予約キーワードが続く暗黙的な式によって表されます。 通常、ディレクティブ属性を使用して、要素の解析方法の変更や、さまざまな機能の有効化を行います。

@attributes

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@attributes では、非宣言属性のレンダリングがコンポーネントに許可されます。 詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

@bind

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

コンポーネントのデータ バインドは、@bind 属性によって実現されます。 詳細については、データ バインディングの ASP.NET CoreにBlazor関する説明を参照してください。

@bind:culture

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@bind:culture 属性を @bind 属性と共に使用して、値の解析や書式設定を行うための System.Globalization.CultureInfo を提供します。 詳細については、「ASP.NET Core Blazor のグローバリゼーションおよびローカライズ」を参照してください。

@on{EVENT}

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

Razor では、コンポーネントのイベント処理機能が提供されます。 詳細については、「ASP.NET Core Blazor のイベント処理」を参照してください。

@on{EVENT}:preventDefault

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

イベントの既定のアクションを禁止します。

@on{EVENT}:stopPropagation

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

イベントのイベント伝達を停止します。

@key

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@key ディレクティブ属性により、コンポーネントの比較アルゴリズムは、キーの値に基づいて要素またはコンポーネントの保存を保証します。 詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

@ref

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

コンポーネント参照 (@ref) からは、コンポーネント インスタンスにコマンドを発行できるように、そのインスタンスを参照する方法が与えられます。 詳細については、「ASP.NET Core Razor コンポーネント」を参照してください。

@typeparam

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@typeparam ディレクティブによって、生成されるコンポーネント クラスのジェネリック型パラメーターを宣言します。

@typeparam TEntity

where 型制約のあるジェネリック型がサポートされています。

@typeparam TEntity where TEntity : IEntity

詳細については、次の記事を参照してください。

@typeparam

"このシナリオは、Razor コンポーネント (.razor) のみに適用されます。 "

@typeparam ディレクティブによって、生成されるコンポーネント クラスのジェネリック型パラメーターを宣言します。

@typeparam TEntity

詳細については、次の記事を参照してください。

テンプレート化された Razor デリゲート

Razor テンプレートを使用すると、UI スニペットを次の形式で定義できます。

@<tag>...</tag>

次の例では、テンプレート化された Razor デリゲートを Func<T,TResult> として指定する方法を示します。 デリゲートによってカプセル化されるメソッドのパラメーターに対しては、dynamic 型を指定します。 デリゲートの戻り値としては、object 型を指定します。 テンプレートは、Name プロパティを持つ PetList<T> で使用されます。

public class Pet
{
    public string Name { get; set; }
}
@{
    Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;

    var pets = new List<Pet>
    {
        new Pet { Name = "Rin Tin Tin" },
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "K-9" }
    };
}

テンプレートは、foreach ステートメントによって提供される pets で表示されます。

@foreach (var pet in pets)
{
    @petTemplate(pet)
}

表示される出力:

<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>
<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

インライン Razor テンプレートをメソッドへの引数として指定することもできます。 次の例では、Repeat メソッドは Razor テンプレートを受け取ります。 メソッドは、テンプレートを使用して、リストから提供される項目の繰り返しで HTML コンテンツを生成します。

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}

前の例のペットのリストを使用して、次のように Repeat メソッドを呼び出します。

  • List<T>Pet
  • 各ペットを繰り返す回数。
  • 順不同のリストのリスト項目に対して使用するインライン テンプレート。
<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

表示される出力:

<ul>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>K-9</li>
    <li>K-9</li>
    <li>K-9</li>
</ul>

タグ ヘルパー

"このシナリオは、MVC ビューと Razor Page (.cshtml) にのみ適用されます。 "

タグ ヘルパーに関する 3 つのディレクティブがあります。

ディレクティブ 機能
@addTagHelper ビューでタグ ヘルパーを使えるようにします。
@removeTagHelper 前に追加したタグ ヘルパーをビューから削除します。
@tagHelperPrefix タグ プレフィックスを指定して、タグ ヘルパーのサポートを有効にしたり、タグ ヘルパーの使用を明示的にしたりします。

Razor 予約キーワード

Razor キーワード

  • page
  • namespace
  • functions
  • inherits
  • model
  • section
  • helper (現在 ASP.NET Core ではサポートされていません)

Razor キーワードは、@(Razor Keyword) でエスケープされます (例: @(functions))。

C# Razor キーワード

  • case
  • do
  • default
  • for
  • foreach
  • if
  • else
  • lock
  • switch
  • try
  • catch
  • finally
  • using
  • while

C# Razor キーワードは、@(@C# Razor Keyword) で二重にエスケープする必要があります (例: @(@case))。 最初の @ は、Razor パーサーをエスケープします。 2 番目の @ は、C# パーサーをエスケープします。

Razor で使用されない予約キーワード

  • class

ビューに対して生成された Razor C# クラスを検査する

Razor SDK では、Razor ファイルのコンパイルを処理します。 プロジェクトをビルドすると、Razor SDK によって、プロジェクト ルートに obj/<build_configuration>/<target_framework_moniker>/Razor ディレクトリが生成されます。 Razor ディレクトリ内のディレクトリ構造は、プロジェクトのディレクトリ構造をミラー化します。

ASP.NET Core Razor Pages プロジェクトの次のディレクトリ構造について考えてみましょう。

 Areas/
   Admin/
     Pages/
       Index.cshtml
       Index.cshtml.cs
 Pages/
   Shared/
     _Layout.cshtml
   _ViewImports.cshtml
   _ViewStart.cshtml
   Index.cshtml
   Index.cshtml.cs

Debug 構成でプロジェクトをビルドすると、次の obj ディレクトリが生成されます。

 obj/
   Debug/
     netcoreapp2.1/
       Razor/
         Areas/
           Admin/
             Pages/
               Index.g.cshtml.cs
         Pages/
           Shared/
             _Layout.g.cshtml.cs
           _ViewImports.g.cshtml.cs
           _ViewStart.g.cshtml.cs
           Index.g.cshtml.cs

Pages/Index.cshtml の生成されたクラスを表示するには、obj/Debug/netcoreapp2.1/Razor/Pages/Index.g.cshtml.cs を開きます。

ビューの参照と大文字/小文字の区別

Razor ビュー エンジンによるビューの参照では、大文字と小文字が区別されます。 ただし、実際の参照は、基になるファイル システムによって決定されます。

  • ファイル ベースのソース:
    • 大文字と小文字が区別されないファイル システムを使っているオペレーティング システム (Windows など) では、物理的なファイル プロバイダーの参照は大文字と小文字を区別しません。 たとえば、return View("Test") を実行すると、/Views/Home/Test.cshtml/Views/home/test.cshtml、大文字と小文字の使い分けのその他のバリエーションを一致させます。
    • 大文字と小文字が区別されるファイル システム (たとえば、Linux、OSX、および EmbeddedFileProvider) では、参照は大文字と小文字を区別します。 具体的には、たとえば、return View("Test")/Views/Home/Test.cshtmlを一致させます。
  • プリコンパイル済みのビュー: ASP.NET Core 2.0 以降では、プリコンパイル済みのビューの参照は、すべてのオペレーティング システムで大文字と小文字を区別しません。 動作は、Windows での物理ファイル プロバイダーの動作と同じです。 2 つのプリコンパイル済みビューの相違点が大文字と小文字の使い分けだけの場合、参照の結果はどちらになるかわかりません。

開発者には、ファイル名とディレクトリ名の大文字/小文字の使い分けを、次のものと一致させることをお勧めします。

  • 領域、コントローラー、アクションの名前。
  • Razor Pages。

大文字と小文字の使い分けを一致させると、展開は基になっているファイル システムに関係なくビューを検索できます。

Razor で使用されるインポート

次のインポートは、Razor ファイルをサポートする ASP.NET Core Web テンプレートによって生成されます。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;

その他の技術情報

Razor 構文を使用した ASP.NET Web プログラミングの概要」では、Razor 構文を使用したプログラミングのサンプルが多数提供されています。