Razor ページのチュートリアル シリーズのパート 8

Note

これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

重要

この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。

現在のリリースについては、この記事の .NET 8 バージョンを参照してください。

作成者: Rick Anderson

ここでは、Movie モデルに検証ロジックを追加します。 検証規則は、ユーザーがムービーを作成または編集するときに、いつでも適用できます。

検証

ソフトウェア開発には、DRY ("Don't Repeat Yourself" (繰り返しを避けること)) という重要な理念があります。 Razor ページでは、機能を一度規定したら、それをアプリ全体に反映する開発を推奨しています。 DRY は次の場合に役立ちます。

  • アプリのコード量を減らす。
  • コードのエラーが発生する可能性を低くし、テストと保守を簡単にする。

Razor Pages と Entity Framework によって提供される検証のサポートは、DRY 原則の好例です。

  • 検証規則は、1 つの場所 (モデル クラス内) に宣言的に指定されます。
  • 規則は、アプリ内のあらゆる場所に適用されます。

検証規則をムービー モデルに追加する

System.ComponentModel.DataAnnotations 名前空間では以下が提供されます。

  • クラスまたはプロパティに宣言的に適用される一連の組み込みの検証属性。
  • 書式設定に役立つ、検証を行わない [DataType] のような書式設定属性。

組み込みの [Required][StringLength][RegularExpression]、および [Range] 検証属性を利用するように、Movie クラスを更新します。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; } = string.Empty;

    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; } = string.Empty;
}

検証属性では、適用対象のモデル プロパティに適用する動作が指定されます。

  • [Required][MinimumLength] の属性は、プロパティに値が必要なことを示します。 この検証に対応するためにユーザーが空白を入力することを妨げるものは何もありません。

  • [RegularExpression] 属性は、入力できる文字を制限するために使用されます。 前のコードの Genre では:

    • 文字のみを使用する必要があります。
    • 最初の文字は大文字にする必要があります。 空白は使用できますが、数字と特殊文字は使用できません。
  • RegularExpressionRating:

    • 最初の文字が大文字である必要があります。
    • 後続のスペースでは、特殊文字と数字が使用できます。 "PG-13" は Rating では有効ですが、Genre ではエラーになります。
  • [Range] 属性は、値を指定された範囲内に制限します。

  • [StringLength] 属性では、文字列プロパティの最大長を設定できます。任意で最小長も設定できます。

  • 値の型 (decimalintfloatDateTime など) はもともと必須であり、[Required] 属性を必要としません。

前の検証規則はデモンストレーションのために使用されており、実稼働システムには適していません。 たとえば、前の例では、2 文字のみのムービーを入力することはできず、Genre で特殊文字は許可されません。

ASP.NET Core によって自動的に適用される検証規則を設定すると、以下のために役立ちます。

  • アプリの堅牢性を高めます。
  • 無効なデータがデータベースに保存される可能性を減らします。

Razor ページの検証エラー UI

アプリを実行し、[Pages/Movies]/(ページ/ムービー/) に移動します。

[Create New](新規作成) リンクを選択します。 いくつか無効な値を入力してフォームを設定します。 jQuery クライアント側検証がエラーを検出すると、エラー メッセージが表示されます。

複数 jQuery クライアント側検証エラーが表示されたムービー ビュー フォーム

Note

小数フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマを追加する手順については、こちらの GitHub コメント 4076 を参照してください

無効な値を含む各フィールドに、検証エラー メッセージが自動的に表示されることがわかります。 エラーは、JavaScript と jQuery を使用しているクライアント側で発生し、ユーザーが JavaScript を無効にしている場合はサーバー側でも発生します。

大きな利点は、[Create]/(作成/) ページまたは [Edit]/(編集/) ページの変更が必要ないことです。 データ注釈がモデルに適用された後、検証 UI が有効になりました。 このチュートリアルで作成した Razor Pages では、Movie モデル クラスのプロパティの検証属性を使用して、検証規則が自動的に選択されました。 [Edit]/(編集/) ページを使用して検証をテストすると、同じ検証が適用されます。

クライアント側の検証エラーがなくなるまで、フォーム データはサーバーにポストされません。 次のうち 1 つまたは複数の方法で、フォーム データがポストされていないことを確認します。

  • OnPostAsync メソッドにブレークポイントを設定します。 フォームを送信するには、 [Create]/(作成/) または [Save]/(保存/) を選択します。 ブレークポイントがヒットすることはありません。
  • Fiddler ツールを使用します。
  • ブラウザー開発者向けツールを使用して、ネットワーク トラフィックを監視します。

サーバー側の検証

ブラウザーで JavaScript が無効にされている場合、エラーがあるフォームを送信すると、サーバーにポストされます。

必要に応じて、サーバー側の検証をテストします。

  1. ブラウザーで JavaScript を無効にします。 ブラウザーの開発者ツールを使用して JavaScript を無効にすることができます。 ブラウザーで JavaScript を無効にすることができない場合は、別のブラウザーを試してください。

  2. [Create] または [Edit] ページの OnPostAsync メソッドにブレークポイントを設定します。

  3. 無効なデータを含むフォームを送信します。

  4. モデルの状態が無効であることを確認します。

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

または、サーバーでクライアント側の検証を無効にします

次のコードは、チュートリアルで前にスキャフォールディング処理した Create.cshtml ページの一部を示しています。 これは、[Create]/(作成/) ページと [Edit]/(編集/) ページで以下を行うために使用されます。

  • 最初のフォームを表示する。
  • エラーが発生した場合にフォームを再表示する。
<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Movie.Title" class="control-label"></label>
        <input asp-for="Movie.Title" class="form-control" />
        <span asp-validation-for="Movie.Title" class="text-danger"></span>
    </div>

入力タグ ヘルパーDataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。 検証タグ ヘルパーには検証エラーが表示されます。 詳しくは、検証に関する記事をご覧ください。

[Create] ページと [Edit] ページ内に検証規則はありません。 検証規則とエラー文字列は、Movie クラスでのみ指定されています。 これらの検証規則は、Movie モデルを編集する Razor ページに自動的に適用されます。

検証ロジックの変更が必要な場合は、モデルでのみ変更します。 検証は常にアプリ全体に適用され、検証ロジックは 1 か所に定義されます。 検証が 1 か所であることは、コードが整理された状態を保つことを助け、保守と更新を簡単にします。

DataType 属性を使用する

Movie クラスを調べます。 System.ComponentModel.DataAnnotations 名前空間には、組み込みの検証属性セットに加え、書式設定の属性もあります。 [DataType] 属性は、ReleaseDate および Price プロパティに適用されます。

[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[DataType] 属性では、以下が提供されます。

  • ビュー エンジンでデータを書式設定するためのヒント。
  • URL の <a> や電子メールの <a href="mailto:EmailAddress.com"> などの属性の指定。

データの書式を検証するためには、[RegularExpression] 属性を使用してください。 [DataType] 属性は、データベースの組み込み型よりも具体的なデータ型を指定するために使用されます。 [DataType] 属性は、検証属性ではありません。 サンプル アプリでは、日付のみが表示され、時刻は表示されません。

DataType 列挙型には、DateTimePhoneNumberCurrencyEmailAddress などの多数のデータ型があります。

[DataType] 属性は:

  • アプリで、型固有の機能を自動的に提供できるようにします。 たとえば、DataType.EmailAddress に対して mailto: リンクを作成できます。
  • HTML5 をサポートしているブラウザーに、日付セレクター DataType.Date を提供できます。
  • HTML 5 ブラウザーで使用される HTML 5 data- ("データ ダッシュ" と読みます) 属性を出力します。
  • 検証が行われることはありません

DataType.Date は、表示される日付の書式を指定しません。 既定で、日付フィールドはサーバーの CultureInfo に基づき、既定の書式に従って表示されます。

[Column(TypeName = "decimal(18, 2)")] データ注釈は、Entity Framework Core がデータベースの通貨と Price を正しくマッピングできるようにするために必要です。 詳細については、「Data Types」(データ型) を参照してください。

[DisplayFormat] 属性は、日付の書式を明示的に指定するために使用されます。

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

ApplyFormatInEditMode 設定には、編集対象の値を表示するときに適用される書式設定を指定します。 一部のフィールドでは、この動作は不要です。 たとえば、通貨値の場合、通常、編集 UI では通貨記号は必要ありません。

[DisplayFormat] 属性を単独で使用できますが、一般的に、[DataType] 属性を使用することが推奨されます。 [DataType] 属性は、画面でのレンダリング方法とは異なり、データのセマンティクスを伝達します。 [DataType] 属性には、[DisplayFormat] では得られない以下のような利点があります。

  • ブラウザーで HTML5 機能を有効にすることができます。たとえば、カレンダー コントロール、ロケールに適した通貨記号、電子メール リンクを表示できます。
  • 既定では、ブラウザーでは、ロケールに基づく適切な書式を使用してデータがレンダリングされます。
  • [DataType] 属性を使用すると、ASP.NET Core フレームワークで、適切なフィールド テンプレートを選択し、データをレンダリングすることができます。 DisplayFormat を単独で使用する場合、文字列テンプレートが使用されます。

注: jQuery の検証は、[Range] 属性と DateTime では機能しません。 たとえば、次のコードでは、指定した範囲内の日付であっても、クライアント側の検証エラーが常に表示されます。

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

ベスト プラクティスは、モデル内に日付をハードコーディングしてコンパイルしないようにすることです。したがって、[Range] 属性と DateTime の使用は推奨されません。 頻繁に変更される可能性のある日付範囲やその他の値の場合、コード内にそれらを指定するのではなく、Configuration を使用します。

次のコードは、1 行で複数の属性を組み合わせる例です。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; } = string.Empty;

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; } = string.Empty;
}

Razor Pages と EF Core の概要に関するページでは、Razor Pages を使用した高度な EF Core の操作について説明されています。

移行を適用する

クラスに適用された DataAnnotations によって、スキーマが変更されます。 たとえば、Titleフィールドに適用された DataAnnotations は次のようになります。

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
  • 文字数を 60 に制限します。
  • null 値を許可しません。

Movie テーブルには現在、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

上記のスキーマ変更では、EF によって例外がスローされることはありません。 ただし、スキーマがモデルと一致するように、移行を作成してください。

[ツール] メニューで、[NuGet パッケージ マネージャー] > [パッケージ マネージャー コンソール] の順に選択します。 PMC で、次のコマンドを入力します。

Add-Migration New_DataAnnotations
Update-Database

Update-Database は、New_DataAnnotations クラスの Up メソッドを実行します。

Up メソッドを検証します。

public partial class New_DataAnnotations : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            type: "nvarchar(60)",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            type: "nvarchar(5)",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            type: "nvarchar(30)",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");
    }

更新された Movie テーブルには、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Azure に発行する

Azure へのデプロイの詳細については、「チュートリアル: SQL Database を使用して Azure に ASP.NET Core アプリを作成する」をご覧ください。

このたびは、この Razor Pages の紹介を最後までお読みいただきありがとうございました。 Razor Pages と EF Core の概要に関するページには、このチュートリアルの補足情報が提供されています。

その他のリソース

次のステップ

ここでは、Movie モデルに検証ロジックを追加します。 検証規則は、ユーザーがムービーを作成または編集するときに、いつでも適用できます。

検証

ソフトウェア開発には、DRY ("Don't Repeat Yourself" (繰り返しを避けること)) という重要な理念があります。 Razor ページでは、機能を一度規定したら、それをアプリ全体に反映する開発を推奨しています。 DRY は次の場合に役立ちます。

  • アプリのコード量を減らす。
  • コードのエラーが発生する可能性を低くし、テストと保守を簡単にする。

Razor Pages と Entity Framework によって提供される検証のサポートは、DRY 原則の好例です。

  • 検証規則は、1 つの場所 (モデル クラス内) に宣言的に指定されます。
  • 規則は、アプリ内のあらゆる場所に適用されます。

検証規則をムービー モデルに追加する

System.ComponentModel.DataAnnotations 名前空間では以下が提供されます。

  • クラスまたはプロパティに宣言的に適用される一連の組み込みの検証属性。
  • 書式設定に役立つ、検証を行わない [DataType] のような書式設定属性。

組み込みの [Required][StringLength][RegularExpression]、および [Range] 検証属性を利用するように、Movie クラスを更新します。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    [Required]
    public string Title { get; set; } = string.Empty;

    // [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [Range(1, 100)]
    [DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
    [StringLength(5)]
    [Required]
    public string Rating { get; set; } = string.Empty;
}

検証属性では、適用対象のモデル プロパティに適用する動作が指定されます。

  • [Required][MinimumLength] の属性は、プロパティに値が必要なことを示します。 この検証に対応するためにユーザーが空白を入力することを妨げるものは何もありません。

  • [RegularExpression] 属性は、入力できる文字を制限するために使用されます。 前のコードの Genre では:

    • 文字のみを使用する必要があります。
    • 最初の文字は大文字にする必要があります。 空白は使用できますが、数字と特殊文字は使用できません。
  • RegularExpressionRating:

    • 最初の文字が大文字である必要があります。
    • 後続のスペースでは、特殊文字と数字が使用できます。 "PG-13" は Rating では有効ですが、Genre ではエラーになります。
  • [Range] 属性は、値を指定された範囲内に制限します。

  • [StringLength] 属性では、文字列プロパティの最大長を設定できます。任意で最小長も設定できます。

  • 値の型 (decimalintfloatDateTime など) はもともと必須であり、[Required] 属性を必要としません。

前の検証規則はデモンストレーションのために使用されており、実稼働システムには適していません。 たとえば、前の例では、2 文字のみのムービーを入力することはできず、Genre で特殊文字は許可されません。

ASP.NET Core によって自動的に適用される検証規則を設定すると、以下のために役立ちます。

  • アプリの堅牢性を高めます。
  • 無効なデータがデータベースに保存される可能性を減らします。

Razor ページの検証エラー UI

アプリを実行し、[Pages/Movies]/(ページ/ムービー/) に移動します。

[Create New](新規作成) リンクを選択します。 いくつか無効な値を入力してフォームを設定します。 jQuery クライアント側検証がエラーを検出すると、エラー メッセージが表示されます。

複数 jQuery クライアント側検証エラーが表示されたムービー ビュー フォーム

Note

小数フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマを追加する手順については、こちらの GitHub コメント 4076 を参照してください

無効な値を含む各フィールドに、検証エラー メッセージが自動的に表示されることがわかります。 エラーは、JavaScript と jQuery を使用しているクライアント側で発生し、ユーザーが JavaScript を無効にしている場合はサーバー側でも発生します。

大きな利点は、[Create]/(作成/) ページまたは [Edit]/(編集/) ページの変更が必要ないことです。 データ注釈がモデルに適用された後、検証 UI が有効になりました。 このチュートリアルで作成した Razor Pages では、Movie モデル クラスのプロパティの検証属性を使用して、検証規則が自動的に選択されました。 [Edit]/(編集/) ページを使用して検証をテストすると、同じ検証が適用されます。

クライアント側の検証エラーがなくなるまで、フォーム データはサーバーにポストされません。 次のうち 1 つまたは複数の方法で、フォーム データがポストされていないことを確認します。

  • OnPostAsync メソッドにブレークポイントを設定します。 フォームを送信するには、 [Create]/(作成/) または [Save]/(保存/) を選択します。 ブレークポイントがヒットすることはありません。
  • Fiddler ツールを使用します。
  • ブラウザー開発者向けツールを使用して、ネットワーク トラフィックを監視します。

サーバー側の検証

ブラウザーで JavaScript が無効にされている場合、エラーがあるフォームを送信すると、サーバーにポストされます。

必要に応じて、サーバー側の検証をテストします。

  1. ブラウザーで JavaScript を無効にします。 ブラウザーの開発者ツールを使用して JavaScript を無効にすることができます。 ブラウザーで JavaScript を無効にすることができない場合は、別のブラウザーを試してください。

  2. [Create] または [Edit] ページの OnPostAsync メソッドにブレークポイントを設定します。

  3. 無効なデータを含むフォームを送信します。

  4. モデルの状態が無効であることを確認します。

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

または、サーバーでクライアント側の検証を無効にします

次のコードは、チュートリアルで前にスキャフォールディング処理した Create.cshtml ページの一部を示しています。 これは、[Create]/(作成/) ページと [Edit]/(編集/) ページで以下を行うために使用されます。

  • 最初のフォームを表示する。
  • エラーが発生した場合にフォームを再表示する。
<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Movie.Title" class="control-label"></label>
        <input asp-for="Movie.Title" class="form-control" />
        <span asp-validation-for="Movie.Title" class="text-danger"></span>
    </div>

入力タグ ヘルパーDataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。 検証タグ ヘルパーには検証エラーが表示されます。 詳しくは、検証に関する記事をご覧ください。

[Create] ページと [Edit] ページ内に検証規則はありません。 検証規則とエラー文字列は、Movie クラスでのみ指定されています。 これらの検証規則は、Movie モデルを編集する Razor ページに自動的に適用されます。

検証ロジックの変更が必要な場合は、モデルでのみ変更します。 検証は常にアプリ全体に適用され、検証ロジックは 1 か所に定義されます。 検証が 1 か所であることは、コードが整理された状態を保つことを助け、保守と更新を簡単にします。

DataType 属性を使用する

Movie クラスを調べます。 System.ComponentModel.DataAnnotations 名前空間には、組み込みの検証属性セットに加え、書式設定の属性もあります。 [DataType] 属性は、ReleaseDate および Price プロパティに適用されます。

// [Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[DataType] 属性では、以下が提供されます。

  • ビュー エンジンでデータを書式設定するためのヒント。
  • URL の <a> や電子メールの <a href="mailto:EmailAddress.com"> などの属性の指定。

データの書式を検証するためには、[RegularExpression] 属性を使用してください。 [DataType] 属性は、データベースの組み込み型よりも具体的なデータ型を指定するために使用されます。 [DataType] 属性は、検証属性ではありません。 サンプル アプリでは、日付のみが表示され、時刻は表示されません。

DataType 列挙型には、DateTimePhoneNumberCurrencyEmailAddress などの多数のデータ型があります。

[DataType] 属性は:

  • アプリで、型固有の機能を自動的に提供できるようにします。 たとえば、DataType.EmailAddress に対して mailto: リンクを作成できます。
  • HTML5 をサポートしているブラウザーに、日付セレクター DataType.Date を提供できます。
  • HTML 5 ブラウザーで使用される HTML 5 data- ("データ ダッシュ" と読みます) 属性を出力します。
  • 検証が行われることはありません

DataType.Date は、表示される日付の書式を指定しません。 既定で、日付フィールドはサーバーの CultureInfo に基づき、既定の書式に従って表示されます。

[Column(TypeName = "decimal(18, 2)")] データ注釈は、Entity Framework Core がデータベースの通貨と Price を正しくマッピングできるようにするために必要です。 詳細については、「Data Types」(データ型) を参照してください。

[DisplayFormat] 属性は、日付の書式を明示的に指定するために使用されます。

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

ApplyFormatInEditMode 設定には、編集対象の値を表示するときに適用される書式設定を指定します。 一部のフィールドでは、この動作は不要です。 たとえば、通貨値の場合、通常、編集 UI では通貨記号は必要ありません。

[DisplayFormat] 属性を単独で使用できますが、一般的に、[DataType] 属性を使用することが推奨されます。 [DataType] 属性は、画面でのレンダリング方法とは異なり、データのセマンティクスを伝達します。 [DataType] 属性には、[DisplayFormat] では得られない以下のような利点があります。

  • ブラウザーで HTML5 機能を有効にすることができます。たとえば、カレンダー コントロール、ロケールに適した通貨記号、電子メール リンクを表示できます。
  • 既定では、ブラウザーでは、ロケールに基づく適切な書式を使用してデータがレンダリングされます。
  • [DataType] 属性を使用すると、ASP.NET Core フレームワークで、適切なフィールド テンプレートを選択し、データをレンダリングすることができます。 DisplayFormat を単独で使用する場合、文字列テンプレートが使用されます。

注: jQuery の検証は、[Range] 属性と DateTime では機能しません。 たとえば、次のコードでは、指定した範囲内の日付であっても、クライアント側の検証エラーが常に表示されます。

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

ベスト プラクティスは、モデル内に日付をハードコーディングしてコンパイルしないようにすることです。したがって、[Range] 属性と DateTime の使用は推奨されません。 頻繁に変更される可能性のある日付範囲やその他の値の場合、コード内にそれらを指定するのではなく、Configuration を使用します。

次のコードは、1 行で複数の属性を組み合わせる例です。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models;

public class Movie
{
    public int Id { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; } = string.Empty;

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; } = string.Empty;

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; } = string.Empty;
}

Razor Pages と EF Core の概要に関するページでは、Razor Pages を使用した高度な EF Core の操作について説明されています。

移行を適用する

クラスに適用された DataAnnotations によって、スキーマが変更されます。 たとえば、Titleフィールドに適用された DataAnnotations は次のようになります。

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
  • 文字数を 60 に制限します。
  • null 値を許可しません。

Movie テーブルには現在、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

上記のスキーマ変更では、EF によって例外がスローされることはありません。 ただし、スキーマがモデルと一致するように、移行を作成してください。

[ツール] メニューで、[NuGet パッケージ マネージャー] > [パッケージ マネージャー コンソール] の順に選択します。 PMC で、次のコマンドを入力します。

Add-Migration New_DataAnnotations
Update-Database

Update-Database は、New_DataAnnotations クラスの Up メソッドを実行します。

Up メソッドを検証します。

public partial class NewDataAnnotations : Migration
{
    /// <inheritdoc />
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            type: "nvarchar(60)",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            type: "nvarchar(5)",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            type: "nvarchar(30)",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");
    }

更新された Movie テーブルには、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Azure に発行する

Azure へのデプロイの詳細については、「チュートリアル: SQL Database を使用して Azure に ASP.NET Core アプリを作成する」をご覧ください。

このたびは、この Razor Pages の紹介を最後までお読みいただきありがとうございました。 Razor Pages と EF Core の概要に関するページには、このチュートリアルの補足情報が提供されています。

その他のリソース

次のステップ

ここでは、Movie モデルに検証ロジックを追加します。 検証規則は、ユーザーがムービーを作成または編集するときに、いつでも適用できます。

検証

ソフトウェア開発には、DRY ("Don't Repeat Yourself" (繰り返しを避けること)) という重要な理念があります。 Razor ページでは、機能を一度規定したら、それをアプリ全体に反映する開発を推奨しています。 DRY は次の場合に役立ちます。

  • アプリのコード量を減らす。
  • コードのエラーが発生する可能性を低くし、テストと保守を簡単にする。

Razor Pages と Entity Framework によって提供される検証のサポートは、DRY 原則の好例です。

  • 検証規則は、1 つの場所 (モデル クラス内) に宣言的に指定されます。
  • 規則は、アプリ内のあらゆる場所に適用されます。

検証規則をムービー モデルに追加する

System.ComponentModel.DataAnnotations 名前空間では以下が提供されます。

  • クラスまたはプロパティに宣言的に適用される一連の組み込みの検証属性。
  • 書式設定に役立つ、検証を行わない [DataType] のような書式設定属性。

組み込みの [Required][StringLength][RegularExpression]、および [Range] 検証属性を利用するように、Movie クラスを更新します。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Title { get; set; } = string.Empty;

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
        [Required]
        [StringLength(30)]
        public string Genre { get; set; } = string.Empty;

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
        [StringLength(5)]
        [Required]
        public string Rating { get; set; } = string.Empty;
    }
}

検証属性では、適用対象のモデル プロパティに適用する動作が指定されます。

  • [Required][MinimumLength] の属性は、プロパティに値が必要なことを示します。 この検証に対応するためにユーザーが空白を入力することを妨げるものは何もありません。

  • [RegularExpression] 属性は、入力できる文字を制限するために使用されます。 前のコードの Genre では:

    • 文字のみを使用する必要があります。
    • 最初の文字は大文字にする必要があります。 空白は使用できますが、数字と特殊文字は使用できません。
  • RegularExpressionRating:

    • 最初の文字が大文字である必要があります。
    • 後続のスペースでは、特殊文字と数字が使用できます。 "PG-13" は Rating では有効ですが、Genre ではエラーになります。
  • [Range] 属性は、値を指定された範囲内に制限します。

  • [StringLength] 属性では、文字列プロパティの最大長を設定できます。任意で最小長も設定できます。

  • 値の型 (decimalintfloatDateTime など) はもともと必須であり、[Required] 属性を必要としません。

前の検証規則はデモンストレーションのために使用されており、実稼働システムには適していません。 たとえば、前の例では、2 文字のみのムービーを入力することはできず、Genre で特殊文字は許可されません。

ASP.NET Core によって自動的に適用される検証規則を設定すると、以下のために役立ちます。

  • アプリの堅牢性を高めます。
  • 無効なデータがデータベースに保存される可能性を減らします。

Razor ページの検証エラー UI

アプリを実行し、[Pages/Movies]/(ページ/ムービー/) に移動します。

[Create New](新規作成) リンクを選択します。 いくつか無効な値を入力してフォームを設定します。 jQuery クライアント側検証がエラーを検出すると、エラー メッセージが表示されます。

複数 jQuery クライアント側検証エラーが表示されたムービー ビュー フォーム

Note

小数フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマを追加する手順については、こちらの GitHub コメント 4076 を参照してください

無効な値を含む各フィールドに、検証エラー メッセージが自動的に表示されることがわかります。 エラーは、JavaScript と jQuery を使用しているクライアント側で発生し、ユーザーが JavaScript を無効にしている場合はサーバー側でも発生します。

大きな利点は、[Create]/(作成/) ページまたは [Edit]/(編集/) ページの変更が必要ないことです。 データ注釈がモデルに適用された後、検証 UI が有効になりました。 このチュートリアルで作成した Razor Pages では、Movie モデル クラスのプロパティの検証属性を使用して、検証規則が自動的に選択されました。 [Edit]/(編集/) ページを使用して検証をテストすると、同じ検証が適用されます。

クライアント側の検証エラーがなくなるまで、フォーム データはサーバーにポストされません。 次のうち 1 つまたは複数の方法で、フォーム データがポストされていないことを確認します。

  • OnPostAsync メソッドにブレークポイントを設定します。 フォームを送信するには、 [Create]/(作成/) または [Save]/(保存/) を選択します。 ブレークポイントがヒットすることはありません。
  • Fiddler ツールを使用します。
  • ブラウザー開発者向けツールを使用して、ネットワーク トラフィックを監視します。

サーバー側の検証

ブラウザーで JavaScript が無効にされている場合、エラーがあるフォームを送信すると、サーバーにポストされます。

必要に応じて、サーバー側の検証をテストします。

  1. ブラウザーで JavaScript を無効にします。 ブラウザーの開発者ツールを使用して JavaScript を無効にすることができます。 ブラウザーで JavaScript を無効にすることができない場合は、別のブラウザーを試してください。

  2. [Create] または [Edit] ページの OnPostAsync メソッドにブレークポイントを設定します。

  3. 無効なデータを含むフォームを送信します。

  4. モデルの状態が無効であることを確認します。

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

または、サーバーでクライアント側の検証を無効にします

次のコードは、チュートリアルで前にスキャフォールディング処理した Create.cshtml ページの一部を示しています。 これは、[Create]/(作成/) ページと [Edit]/(編集/) ページで以下を行うために使用されます。

  • 最初のフォームを表示する。
  • エラーが発生した場合にフォームを再表示する。
<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Movie.Title" class="control-label"></label>
        <input asp-for="Movie.Title" class="form-control" />
        <span asp-validation-for="Movie.Title" class="text-danger"></span>
    </div>

入力タグ ヘルパーDataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。 検証タグ ヘルパーには検証エラーが表示されます。 詳しくは、検証に関する記事をご覧ください。

[Create] ページと [Edit] ページ内に検証規則はありません。 検証規則とエラー文字列は、Movie クラスでのみ指定されています。 これらの検証規則は、Movie モデルを編集する Razor ページに自動的に適用されます。

検証ロジックの変更が必要な場合は、モデルでのみ変更します。 検証は常にアプリケーション全体に適用され、検証ロジックは 1 か所に定義されます。 検証が 1 か所であることは、コードが整理された状態を保つことを助け、保守と更新を簡単にします。

DataType 属性を使用する

Movie クラスを調べます。 System.ComponentModel.DataAnnotations 名前空間には、組み込みの検証属性セットに加え、書式設定の属性もあります。 [DataType] 属性は、ReleaseDate および Price プロパティに適用されます。

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
[Column(TypeName = "decimal(18, 2)")]
public decimal Price { get; set; }

[DataType] 属性では、以下が提供されます。

  • ビュー エンジンでデータを書式設定するためのヒント。
  • URL の <a> や電子メールの <a href="mailto:EmailAddress.com"> などの属性の指定。

データの書式を検証するためには、[RegularExpression] 属性を使用してください。 [DataType] 属性は、データベースの組み込み型よりも具体的なデータ型を指定するために使用されます。 [DataType] 属性は、検証属性ではありません。 サンプル アプリケーションでは、日付のみが表示され、時刻は表示されません。

DataType 列挙型には、DateTimePhoneNumberCurrencyEmailAddress などの多数のデータ型があります。

[DataType] 属性は:

  • アプリケーションで、型固有の機能を自動的に提供できるようにします。 たとえば、DataType.EmailAddress に対して mailto: リンクを作成できます。
  • HTML5 をサポートしているブラウザーに、日付セレクター DataType.Date を提供できます。
  • HTML 5 ブラウザーで使用される HTML 5 data- ("データ ダッシュ" と読みます) 属性を出力します。
  • 検証が行われることはありません

DataType.Date は、表示される日付の書式を指定しません。 既定で、日付フィールドはサーバーの CultureInfo に基づき、既定の書式に従って表示されます。

[Column(TypeName = "decimal(18, 2)")] データ注釈は、Entity Framework Core がデータベースの通貨と Price を正しくマッピングできるようにするために必要です。 詳細については、「Data Types」(データ型) を参照してください。

[DisplayFormat] 属性は、日付の書式を明示的に指定するために使用されます。

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

ApplyFormatInEditMode 設定には、編集対象の値を表示するときに適用される書式設定を指定します。 一部のフィールドでは、この動作は不要です。 たとえば、通貨値の場合、通常、編集 UI では通貨記号は必要ありません。

[DisplayFormat] 属性を単独で使用できますが、一般的に、[DataType] 属性を使用することが推奨されます。 [DataType] 属性は、画面でのレンダリング方法とは異なり、データのセマンティクスを伝達します。 [DataType] 属性には、[DisplayFormat] では得られない以下のような利点があります。

  • ブラウザーで HTML5 機能を有効にすることができます。たとえば、カレンダー コントロール、ロケールに適した通貨記号、電子メール リンクを表示できます。
  • 既定では、ブラウザーでは、ロケールに基づく適切な書式を使用してデータがレンダリングされます。
  • [DataType] 属性を使用すると、ASP.NET Core フレームワークで、適切なフィールド テンプレートを選択し、データをレンダリングすることができます。 DisplayFormat を単独で使用する場合、文字列テンプレートが使用されます。

注: jQuery の検証は、[Range] 属性と DateTime では機能しません。 たとえば、次のコードでは、指定した範囲内の日付であっても、クライアント側の検証エラーが常に表示されます。

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

ベスト プラクティスは、モデル内に日付をハードコーディングしてコンパイルしないようにすることです。したがって、[Range] 属性と DateTime の使用は推奨されません。 頻繁に変更される可能性のある日付範囲やその他の値の場合、コード内にそれらを指定するのではなく、Configuration を使用します。

次のコードは、1 行で複数の属性を組み合わせる例です。

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        public string Title { get; set; } = string.Empty;

        [Display(Name = "Release Date"), DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
        public string Genre { get; set; } = string.Empty;

        [Range(1, 100), DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
        public string Rating { get; set; } = string.Empty;
    }
}

Razor Pages と EF Core の概要に関するページでは、Razor Pages を使用した高度な EF Core の操作について説明されています。

移行を適用する

クラスに適用された DataAnnotations によって、スキーマが変更されます。 たとえば、Titleフィールドに適用された DataAnnotations は次のようになります。

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; } = string.Empty;
  • 文字数を 60 に制限します。
  • null 値を許可しません。

Movie テーブルには現在、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

上記のスキーマ変更では、EF によって例外がスローされることはありません。 ただし、スキーマがモデルと一致するように、移行を作成してください。

[ツール] メニューで、[NuGet パッケージ マネージャー] > [パッケージ マネージャー コンソール] の順に選択します。 PMC で、次のコマンドを入力します。

Add-Migration New_DataAnnotations
Update-Database

Update-Database は、New_DataAnnotations クラスの Up メソッドを実行します。

Up メソッドを検証します。

public partial class New_DataAnnotations : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            type: "nvarchar(60)",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            type: "nvarchar(5)",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            type: "nvarchar(30)",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldType: "nvarchar(max)");
    }

更新された Movie テーブルには、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Azure に発行する

Azure へのデプロイの詳細については、「チュートリアル: SQL Database を使用して Azure に ASP.NET Core アプリを作成する」をご覧ください。

このたびは、この Razor Pages の紹介を最後までお読みいただきありがとうございました。 Razor Pages と EF Core の概要に関するページには、このチュートリアルの補足情報が提供されています。

その他のリソース

次のステップ

ここでは、Movie モデルに検証ロジックを追加します。 検証規則は、ユーザーがムービーを作成または編集するときに、いつでも適用できます。

検証

ソフトウェア開発には、DRY ("Don't Repeat Yourself" (繰り返しを避けること)) という重要な理念があります。 Razor ページでは、機能を一度規定したら、それをアプリ全体に反映する開発を推奨しています。 DRY は次の場合に役立ちます。

  • アプリのコード量を減らす。
  • コードのエラーが発生する可能性を低くし、テストと保守を簡単にする。

Razor Pages と Entity Framework によって提供される検証のサポートは、DRY 原則の好例です。

  • 検証規則は、1 つの場所 (モデル クラス内) に宣言的に指定されます。
  • 規則は、アプリ内のあらゆる場所に適用されます。

検証規則をムービー モデルに追加する

DataAnnotations 名前空間では以下が提供されます。

  • クラスまたはプロパティに宣言的に適用される一連の組み込みの検証属性。
  • 書式設定に役立つ、検証を行わない [DataType] のような書式設定属性。

組み込みの [Required][StringLength][RegularExpression]、および [Range] 検証属性を利用するように、Movie クラスを更新します。

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace RazorPagesMovie.Models
{
    public class Movie
    {
        public int ID { get; set; }

        [StringLength(60, MinimumLength = 3)]
        [Required]
        public string Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Range(1, 100)]
        [DataType(DataType.Currency)]
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$")]
        [Required]
        [StringLength(30)]
        public string Genre { get; set; }

        [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$")]
        [StringLength(5)]
        [Required]
        public string Rating { get; set; }
    }
}

検証属性では、適用対象のモデル プロパティに適用する動作が指定されます。

  • [Required][MinimumLength] の属性は、プロパティに値が必要なことを示します。 この検証に対応するためにユーザーが空白を入力することを妨げるものは何もありません。

  • [RegularExpression] 属性は、入力できる文字を制限するために使用されます。 前のコードの Genre では:

    • 文字のみを使用する必要があります。
    • 最初の文字は大文字にする必要があります。 空白は使用できますが、数字と特殊文字は使用できません。
  • RegularExpressionRating:

    • 最初の文字が大文字である必要があります。
    • 後続のスペースでは、特殊文字と数字が使用できます。 "PG-13" は Rating では有効ですが、Genre ではエラーになります。
  • [Range] 属性は、値を指定された範囲内に制限します。

  • [StringLength] 属性では、文字列プロパティの最大長を設定できます。任意で最小長も設定できます。

  • 値の型 (decimalintfloatDateTime など) はもともと必須であり、[Required] 属性を必要としません。

前の検証規則はデモンストレーションのために使用されており、実稼働システムには適していません。 たとえば、前の例では、2 文字のみのムービーを入力することはできず、Genre で特殊文字は許可されません。

ASP.NET Core によって自動的に適用される検証規則を設定すると、以下のために役立ちます。

  • アプリの堅牢性を高めます。
  • 無効なデータがデータベースに保存される可能性を減らします。

Razor ページの検証エラー UI

アプリを実行し、[Pages/Movies]/(ページ/ムービー/) に移動します。

[Create New](新規作成) リンクを選択します。 いくつか無効な値を入力してフォームを設定します。 jQuery クライアント側検証がエラーを検出すると、エラー メッセージが表示されます。

複数 jQuery クライアント側検証エラーが表示されたムービー ビュー フォーム

Note

小数フィールドに小数点のコンマを入力できない場合があります。 小数点にコンマ (",") を使い、英語 (米国) 以外の日付形式を使う英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。 小数点のコンマを追加する手順については、こちらの GitHub コメント 4076 を参照してください

無効な値を含む各フィールドに、検証エラー メッセージが自動的に表示されることがわかります。 エラーは、JavaScript と jQuery を使用しているクライアント側で発生し、ユーザーが JavaScript を無効にしている場合はサーバー側でも発生します。

大きな利点は、[Create]/(作成/) ページまたは [Edit]/(編集/) ページの変更が必要ないことです。 データ注釈がモデルに適用された後、検証 UI が有効になりました。 このチュートリアルで作成した Razor Pages では、Movie モデル クラスのプロパティの検証属性を使用して、検証規則が自動的に選択されました。 [Edit]/(編集/) ページを使用して検証をテストすると、同じ検証が適用されます。

クライアント側の検証エラーがなくなるまで、フォーム データはサーバーにポストされません。 次のうち 1 つまたは複数の方法で、フォーム データがポストされていないことを確認します。

  • OnPostAsync メソッドにブレークポイントを設定します。 フォームを送信するには、 [Create]/(作成/) または [Save]/(保存/) を選択します。 ブレークポイントがヒットすることはありません。
  • Fiddler ツールを使用します。
  • ブラウザー開発者向けツールを使用して、ネットワーク トラフィックを監視します。

サーバー側の検証

ブラウザーで JavaScript が無効にされている場合、エラーがあるフォームを送信すると、サーバーにポストされます。

必要に応じて、サーバー側の検証をテストします。

  1. ブラウザーで JavaScript を無効にします。 ブラウザーの開発者ツールを使用して JavaScript を無効にすることができます。 ブラウザーで JavaScript を無効にすることができない場合は、別のブラウザーを試してください。

  2. [Create] または [Edit] ページの OnPostAsync メソッドにブレークポイントを設定します。

  3. 無効なデータを含むフォームを送信します。

  4. モデルの状態が無効であることを確認します。

     if (!ModelState.IsValid)
     {
        return Page();
     }
    

または、サーバーでクライアント側の検証を無効にします

次のコードは、チュートリアルで前にスキャフォールディング処理した Create.cshtml ページの一部を示しています。 これは、[Create]/(作成/) ページと [Edit]/(編集/) ページで以下を行うために使用されます。

  • 最初のフォームを表示する。
  • エラーが発生した場合にフォームを再表示する。
<form method="post">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="Movie.Title" class="control-label"></label>
        <input asp-for="Movie.Title" class="form-control" />
        <span asp-validation-for="Movie.Title" class="text-danger"></span>
    </div>

入力タグ ヘルパーDataAnnotations 属性を使用し、クライアント側で jQuery 検証に必要な HTML 属性を生成します。 検証タグ ヘルパーには検証エラーが表示されます。 詳しくは、検証に関する記事をご覧ください。

[Create] ページと [Edit] ページ内に検証規則はありません。 検証規則とエラー文字列は、Movie クラスでのみ指定されています。 これらの検証規則は、Movie モデルを編集する Razor ページに自動的に適用されます。

検証ロジックの変更が必要な場合は、モデルでのみ変更します。 検証は常にアプリケーション全体に適用され、検証ロジックは 1 か所に定義されます。 検証が 1 か所であることは、コードが整理された状態を保つことを助け、保守と更新を簡単にします。

DataType 属性を使用する

Movie クラスを調べます。 System.ComponentModel.DataAnnotations 名前空間には、組み込みの検証属性セットに加え、書式設定の属性もあります。 [DataType] 属性は、ReleaseDate および Price プロパティに適用されます。

[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }

[Range(1, 100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }

[DataType] 属性では、以下が提供されます。

  • ビュー エンジンでデータを書式設定するためのヒント。
  • URL の <a> や電子メールの <a href="mailto:EmailAddress.com"> などの属性の指定。

データの書式を検証するためには、[RegularExpression] 属性を使用してください。 [DataType] 属性は、データベースの組み込み型よりも具体的なデータ型を指定するために使用されます。 [DataType] 属性は、検証属性ではありません。 サンプル アプリケーションでは、日付のみが表示され、時刻は表示されません。

DataType 列挙型には、DateTimePhoneNumberCurrencyEmailAddress などの多数のデータ型があります。

[DataType] 属性は:

  • アプリケーションで、型固有の機能を自動的に提供できるようにします。 たとえば、DataType.EmailAddress に対して mailto: リンクを作成できます。
  • HTML5 をサポートしているブラウザーに、日付セレクター DataType.Date を提供できます。
  • HTML 5 ブラウザーで使用される HTML 5 data- ("データ ダッシュ" と読みます) 属性を出力します。
  • 検証が行われることはありません

DataType.Date は、表示される日付の書式を指定しません。 既定で、日付フィールドはサーバーの CultureInfo に基づき、既定の書式に従って表示されます。

[Column(TypeName = "decimal(18, 2)")] データ注釈は、Entity Framework Core がデータベースの通貨と Price を正しくマッピングできるようにするために必要です。 詳細については、「Data Types」(データ型) を参照してください。

[DisplayFormat] 属性は、日付の書式を明示的に指定するために使用されます。

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }

ApplyFormatInEditMode 設定には、編集対象の値を表示するときに適用される書式設定を指定します。 一部のフィールドでは、この動作は不要です。 たとえば、通貨値の場合、通常、編集 UI では通貨記号は必要ありません。

[DisplayFormat] 属性を単独で使用できますが、一般的に、[DataType] 属性を使用することが推奨されます。 [DataType] 属性は、画面でのレンダリング方法とは異なり、データのセマンティクスを伝達します。 [DataType] 属性には、[DisplayFormat] では得られない以下のような利点があります。

  • ブラウザーで HTML5 機能を有効にすることができます。たとえば、カレンダー コントロール、ロケールに適した通貨記号、電子メール リンクを表示できます。
  • 既定では、ブラウザーでは、ロケールに基づく適切な書式を使用してデータがレンダリングされます。
  • [DataType] 属性を使用すると、ASP.NET Core フレームワークで、適切なフィールド テンプレートを選択し、データをレンダリングすることができます。 DisplayFormat を単独で使用する場合、文字列テンプレートが使用されます。

注: jQuery の検証は、[Range] 属性と DateTime では機能しません。 たとえば、次のコードでは、指定した範囲内の日付であっても、クライアント側の検証エラーが常に表示されます。

[Range(typeof(DateTime), "1/1/1966", "1/1/2020")]

ベスト プラクティスは、モデル内に日付をハードコーディングしてコンパイルしないようにすることです。したがって、[Range] 属性と DateTime の使用は推奨されません。 頻繁に変更される可能性のある日付範囲やその他の値の場合、コード内にそれらを指定するのではなく、Configuration を使用します。

次のコードは、1 行で複数の属性を組み合わせる例です。

public class Movie
{
    public int ID { get; set; }

    [StringLength(60, MinimumLength = 3)]
    public string Title { get; set; }

    [Display(Name = "Release Date"), DataType(DataType.Date)]
    public DateTime ReleaseDate { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z\s]*$"), Required, StringLength(30)]
    public string Genre { get; set; }

    [Range(1, 100), DataType(DataType.Currency)]
    [Column(TypeName = "decimal(18, 2)")]
    public decimal Price { get; set; }

    [RegularExpression(@"^[A-Z]+[a-zA-Z0-9""'\s-]*$"), StringLength(5)]
    public string Rating { get; set; }
}

Razor Pages と EF Core の概要に関するページでは、Razor Pages を使用した高度な EF Core の操作について説明されています。

移行を適用する

クラスに適用された DataAnnotations によって、スキーマが変更されます。 たとえば、Titleフィールドに適用された DataAnnotations は次のようになります。

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; }
  • 文字数を 60 に制限します。
  • null 値を許可しません。

Movie テーブルには現在、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (MAX)  NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (MAX)  NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

上記のスキーマ変更では、EF によって例外がスローされることはありません。 ただし、スキーマがモデルと一致するように、移行を作成してください。

[ツール] メニューで、[NuGet パッケージ マネージャー] > [パッケージ マネージャー コンソール] の順に選択します。 PMC で、次のコマンドを入力します。

Add-Migration New_DataAnnotations
Update-Database

Update-Database では、New_DataAnnotations クラスの Up メソッドが実行されます。 Up メソッドを検証します。

public partial class New_DataAnnotations : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AlterColumn<string>(
            name: "Title",
            table: "Movie",
            maxLength: 60,
            nullable: false,
            oldClrType: typeof(string),
            oldNullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Rating",
            table: "Movie",
            maxLength: 5,
            nullable: false,
            oldClrType: typeof(string),
            oldNullable: true);

        migrationBuilder.AlterColumn<string>(
            name: "Genre",
            table: "Movie",
            maxLength: 30,
            nullable: false,
            oldClrType: typeof(string),
            oldNullable: true);
    }

更新された Movie テーブルには、次のスキーマがあります。

CREATE TABLE [dbo].[Movie] (
    [ID]          INT             IDENTITY (1, 1) NOT NULL,
    [Title]       NVARCHAR (60)   NOT NULL,
    [ReleaseDate] DATETIME2 (7)   NOT NULL,
    [Genre]       NVARCHAR (30)   NOT NULL,
    [Price]       DECIMAL (18, 2) NOT NULL,
    [Rating]      NVARCHAR (5)    NOT NULL,
    CONSTRAINT [PK_Movie] PRIMARY KEY CLUSTERED ([ID] ASC)
);

Azure に発行する

Azure へのデプロイの詳細については、「チュートリアル: SQL Database を使用して Azure に ASP.NET Core アプリを作成する」をご覧ください。

このたびは、この Razor Pages の紹介を最後までお読みいただきありがとうございました。 Razor Pages と EF Core の概要に関するページには、このチュートリアルの補足情報が提供されています。

信頼性の高い Web アプリ パターン

.NET 用の信頼性の高い Web アプリ パターンYouTube のビデオ記事を参照して、ゼロからでも既存のアプリをリファクタリングしても、信頼性が高く、パフォーマンスが高く、テスト可能で、コスト効率が高く、スケーラブルな ASP.NET Core アプリを作成する方法に関するガイダンスを参照してください。

その他のリソース

次のステップ