パート 8、ASP.NET Core Razor ページへの検証の追加Part 8, add validation to an ASP.NET Core Razor Page

作成者: Rick AndersonBy Rick Anderson

ここでは、Movie モデルに検証ロジックを追加します。In this section, validation logic is added to the Movie model. 検証規則は、ユーザーがムービーを作成または編集するときに、いつでも適用できます。The validation rules are enforced any time a user creates or edits a movie.

検証Validation

ソフトウェア開発には、DRY ("Don't Repeat Yourself" (繰り返しを避けること)) という重要な理念があります。A key tenet of software development is called DRY ("Don't Repeat Yourself"). Razor ページでは、機能を一度規定したら、それをアプリ全体に反映する開発を推奨しています。 Pages encourages development where functionality is specified once, and it's reflected throughout the app. DRY は次の場合に役立ちます。DRY can help:

  • アプリのコード量を減らす。Reduce the amount of code in an app.
  • コードのエラーが発生する可能性を低くし、テストと保守を簡単にする。Make the code less error prone, and easier to test and maintain.

Razor ページと Entity Framework が提供している検証のサポートは、DRY 原則の好例です。The validation support provided by Razor Pages and Entity Framework is a good example of the DRY principle. 検証規則は、1 つの場所 (モデル クラス内) で宣言的に規定され、アプリの任意の場所で適用されます。Validation rules are declaratively specified in one place (in the model class), and the rules are enforced everywhere in the app.

検証規則をムービー モデルに追加するAdd validation rules to the movie model

DataAnnotations 名前空間には、クラスまたはプロパティに宣言的に適用される一連の組み込みの検証属性があります。The DataAnnotations namespace provides a set of built-in validation attributes that are applied declaratively to a class or property. また、DataAnnotations には、書式設定を支援し、どの検証を行わない DataType のような書式設定属性もあります。DataAnnotations also contains formatting attributes like DataType that help with formatting and don't provide any validation.

組み込みの RequiredStringLengthRegularExpression、および Range 検証属性を利用するように、Movie クラスを更新します。Update the Movie class to take advantage of the built-in Required, StringLength, RegularExpression, and Range validation attributes.

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]*$")]
    [Required]
    [StringLength(30)]
    public string Genre { get; set; }

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

検証属性では、適用対象のモデル プロパティに適用する動作が指定されます。The validation attributes specify behavior that you want to enforce on the model properties they're applied to:

  • Required および MinimumLength 属性は、プロパティに値が必要であることを示します。ただし、この検証を満たすためにユーザーが空白を入力することは禁止されていません。The Required and MinimumLength attributes indicate that a property must have a value; but nothing prevents a user from entering white space to satisfy this validation.

  • RegularExpression 属性は、入力できる文字を制限するために使用されます。The RegularExpression attribute is used to limit what characters can be input. 上のコード "Genre" では:In the preceding code, "Genre":

    • 文字のみを使用する必要があります。Must only use letters.
    • 最初の文字は大文字にする必要があります。The first letter is required to be uppercase. 空白、数字、特殊文字は使用できません。White space, numbers, and special characters are not allowed.
  • RegularExpression "評価":The RegularExpression "Rating":

    • 最初の文字が大文字である必要があります。Requires that the first character be an uppercase letter.
    • 後続のスペースでは、特殊文字と数字が使用できます。Allows special characters and numbers in subsequent spaces. "PG-13" は評価に対して有効ですが、"Genre" に対しては失敗します。"PG-13" is valid for a rating, but fails for a "Genre".
  • Range 属性は、指定した範囲内に値を制限します。The Range attribute constrains a value to within a specified range.

  • StringLength 属性では、文字列プロパティの最大長を設定でき、オプションとして最小長も設定できます。The StringLength attribute lets you set the maximum length of a string property, and optionally its minimum length.

  • 値の型 (decimalintfloatDateTime など) は本質的に必須ではなく、[Required] 属性を必要としません。Value types (such as decimal, int, float, DateTime) are inherently required and don't need the [Required] attribute.

ASP.NET Core によって検証規則が自動的に適用されるようにすると、アプリをより堅牢にできます。Having validation rules automatically enforced by ASP.NET Core helps make your app more robust. また、ユーザーが何かを検証することを忘れてしまい、データベースに不適切なデータが誤って格納されることもなくなります。It also ensures that you can't forget to validate something and inadvertently let bad data into the database.

Razor ページの検証エラー UIValidation Error UI in Razor Pages

アプリを実行し、[Pages/Movies]/(ページ/ムービー/) に移動します。Run the app and navigate to Pages/Movies.

[Create New](新規作成) リンクを選択します。Select the Create New link. いくつか無効な値を入力してフォームを設定します。Complete the form with some invalid values. jQuery クライアント側検証がエラーを検出すると、エラー メッセージが表示されます。When jQuery client-side validation detects the error, it displays an error message.

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

注意

小数フィールドに小数点のコンマを入力できない場合があります。You may not be able to enter decimal commas in decimal fields. 小数点にコンマ (",") を使用し、英語 (米国) 以外の日付形式を使用する英語以外のロケールの jQuery 検証をサポートするには、アプリをグローバル化する手順を行う必要があります。To support jQuery validation for non-English locales that use a comma (",") for a decimal point, and non US-English date formats, you must take steps to globalize your app. 小数点のコンマを追加する手順については、こちらの GitHub イシュー 4076 を参照してくださいSee this GitHub issue 4076 for instructions on adding decimal comma.

無効な値を含む各フィールドに、検証エラー メッセージが自動的に表示されることがわかります。Notice how the form has automatically rendered a validation error message in each field containing an invalid value. エラーは、(JavaScript と jQuery を使用している) クライアント側とサーバー側 (ユーザーが JavaScript を無効にしている場合) の両方に適用されます。The errors are enforced both client-side (using JavaScript and jQuery) and server-side (when a user has JavaScript disabled).

大きな利点は、[Create]/(作成/) ページまたは [Edit]/(編集/) ページの変更が必要ないことです。A significant benefit is that no code changes were necessary in the Create or Edit pages. 一度 DataAnnotations がモデルに適用されると、検証 UI は有効化されます。Once DataAnnotations were applied to the model, the validation UI was enabled. このチュートリアルで作成した Razor ページは、(Movie モデル クラスのプロパティの検証属性を使用して) 検証規則を自動的に抽出しました。The Razor Pages created in this tutorial automatically picked up the validation rules (using validation attributes on the properties of the Movie model class). [Edit]/(編集/) ページを使用して検証をテストすると、同じ検証が適用されます。Test validation using the Edit page, the same validation is applied.

クライアント側の検証エラーがなくなるまで、フォーム データはサーバーにポストされません。The form data isn't posted to the server until there are no client-side validation errors. 次のうち 1 つまたは複数の方法で、フォーム データがポストされていないことを確認します。Verify form data isn't posted by one or more of the following approaches:

  • OnPostAsync メソッドにブレークポイントを設定します。Put a break point in the OnPostAsync method. フォームを送信します ( [Create]/(作成/) または [Save]/(保存/) を選択します)。Submit the form (select Create or Save). ブレークポイントがヒットすることはありません。The break point is never hit.
  • Fiddler ツールを使用します。Use the Fiddler tool.
  • ブラウザー開発者向けツールを使用して、ネットワーク トラフィックを監視します。Use the browser developer tools to monitor network traffic.

サーバー側の検証Server-side validation

ブラウザーで JavaScript が無効にされている場合、エラーがあるフォームを送信すると、サーバーにポストされます。When JavaScript is disabled in the browser, submitting the form with errors will post to the server.

必要に応じて、サーバー側の検証をテストします。Optional, test server-side validation:

  • ブラウザーで JavaScript を無効にします。Disable JavaScript in the browser. ブラウザーの開発者ツールを使用して JavaScript を無効にすることができます。You can disable JavaScript using browser's developer tools. ブラウザーで JavaScript を無効にすることができない場合は、別のブラウザーを試してください。If you can't disable JavaScript in the browser, try another browser.

  • [Create] または [Edit] ページの OnPostAsync メソッドにブレークポイントを設定します。Set a break point in the OnPostAsync method of the Create or Edit page.

  • 無効なデータを含むフォームを送信します。Submit a form with invalid data.

  • モデルの状態が無効であることを確認します。Verify the model state is invalid:

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

または、サーバーでクライアント側検証を無効にすることもできます。Alternatively, you can Disable client-side validation on the server.

次のコードは、チュートリアルで前にスキャフォールディング処理した Create.cshtml ページの一部を示しています。The following code shows a portion of the Create.cshtml page scaffolded earlier in the tutorial. [Create] または [Edit] ページにおいて、最初のフォームの表示と、エラーイベント時におけるフォームの再表示のために使用されます。It's used by the Create and Edit pages to display the initial form and to redisplay the form in the event of an error.

<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 属性を生成します。The Input Tag Helper uses the DataAnnotations attributes and produces HTML attributes needed for jQuery Validation on the client-side. 検証タグ ヘルパーには検証エラーが表示されます。The Validation Tag Helper displays validation errors. 詳しくは、検証に関する記事をご覧ください。See Validation for more information.

[Create] ページと [Edit] ページ内に検証規則はありません。The Create and Edit pages have no validation rules in them. 検証規則とエラー文字列は、Movie クラスでのみ指定されています。The validation rules and the error strings are specified only in the Movie class. これらの検証規則は、Movie モデルを編集する Razor ページに自動的に適用されます。These validation rules are automatically applied to Razor Pages that edit the Movie model.

検証ロジックの変更が必要な場合は、モデルでのみ変更します。When validation logic needs to change, it's done only in the model. 検証は常にアプリケーション全体に適用されます (検証ロジックは 1 か所で定義されます)。Validation is applied consistently throughout the application (validation logic is defined in one place). 検証が 1 か所であることは、コードが整理された状態を保つことを助け、保守と更新を簡単にします。Validation in one place helps keep the code clean, and makes it easier to maintain and update.

DataType 属性の使用Using DataType Attributes

Movie クラスを調べます。Examine the Movie class. System.ComponentModel.DataAnnotations 名前空間には、組み込みの検証属性セットに加え、書式設定の属性もあります。The System.ComponentModel.DataAnnotations namespace provides formatting attributes in addition to the built-in set of validation attributes. DataType 属性は、ReleaseDate および Price プロパティに適用されます。The DataType attribute is applied to the ReleaseDate and Price properties.

[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"> などの属性を提供します)。The DataType attributes only provide hints for the view engine to format the data (and supplies attributes such as <a> for URL's and <a href="mailto:EmailAddress.com"> for email). データの書式を検証するためには、RegularExpression 属性を使用してください。Use the RegularExpression attribute to validate the format of the data. DataType 属性は、データベースの組み込み型よりも具体的なデータ型を指定するために使用されます。The DataType attribute is used to specify a data type that's more specific than the database intrinsic type. DataType 属性は、検証属性ではありません。DataType attributes are not validation attributes. サンプル アプリケーションでは、日付のみが表示され、時刻は表示されません。In the sample application, only the date is displayed, without time.

DataType 列挙型は、Date、Time、PhoneNumber、Currency、EmailAddress など、多くの型のために用意されています。The DataType Enumeration provides for many data types, such as Date, Time, PhoneNumber, Currency, EmailAddress, and more. また、DataType 属性を使用して、アプリケーションで型固有の機能を自動的に提供することもできます。The DataType attribute can also enable the application to automatically provide type-specific features. たとえば、DataType.EmailAddress に対して mailto: リンクを作成できます。For example, a mailto: link can be created for DataType.EmailAddress. HTML 5 をサポートしているブラウザーでは、DataType.Date に日付セレクターを提供できます。A date selector can be provided for DataType.Date in browsers that support HTML5. DataType 属性は、HTML 5 ブラウザーが使用する HTML 5 data- ("データ ダッシュ" と読みます) 属性を出力します。The DataType attributes emit HTML 5 data- (pronounced data dash) attributes that HTML 5 browsers consume. DataType 属性は、検証を提供していませんThe DataType attributes do not provide any validation.

DataType.Date は、表示される日付の書式を指定しません。DataType.Date doesn't specify the format of the date that's displayed. 既定で、日付フィールドはサーバーの CultureInfo に基づき、既定の書式に従って表示されます。By default, the data field is displayed according to the default formats based on the server's CultureInfo.

[Column(TypeName = "decimal(18, 2)")] データ注釈は、Entity Framework Core がデータベースの通貨と Price を正しくマッピングできるようにするために必要です。The [Column(TypeName = "decimal(18, 2)")] data annotation is required so Entity Framework Core can correctly map Price to currency in the database. 詳細については、「Data Types」(データ型) を参照してください。For more information, see Data Types.

DisplayFormat 属性は、日付の書式を明示的に指定するために使用されます。The DisplayFormat attribute is used to explicitly specify the date format:

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

ApplyFormatInEditMode 設定では、編集対象の値を表示するときに適用する必要がある書式設定を指定します。The ApplyFormatInEditMode setting specifies that the formatting should be applied when the value is displayed for editing. 一部のフィールドでは、この動作が不要なことがあります。You might not want that behavior for some fields. たとえば、通貨値の場合、編集 UI で通貨記号が不要なことがあります。For example, in currency values, you probably don't want the currency symbol in the edit UI.

DisplayFormat 属性を単独で使用できますが、一般的に、DataType 属性を使用することが推奨されます。The DisplayFormat attribute can be used by itself, but it's generally a good idea to use the DataType attribute. DataType 属性は、画面でのレンダリング方法とは異なり、データのセマンティクスを伝達します。また、DisplayFormat にはない、次の利点があります。The DataType attribute conveys the semantics of the data as opposed to how to render it on a screen, and provides the following benefits that you don't get with DisplayFormat:

  • ブラウザーは HTML5 機能を有効にすることができます (たとえば、カレンダー コントロール、ロケールに適した通貨記号、電子メール リンクを表示するときなど)。The browser can enable HTML5 features (for example to show a calendar control, the locale-appropriate currency symbol, email links, etc.)
  • ブラウザーの既定では、ロケールに基づいて正しい書式を使ってデータがレンダリングされます。By default, the browser will render data using the correct format based on your locale.
  • DataType 属性を使用すると、ASP.NET Core フレームワークで、適切なフィールド テンプレートを選択し、データをレンダリングすることができます。The DataType attribute can enable the ASP.NET Core framework to choose the right field template to render the data. DisplayFormat を単独で使用する場合、文字列テンプレートが使用されます。The DisplayFormat, if used by itself, uses the string template.

注: jQuery の検証は、Range 属性と DateTime では機能しません。Note: jQuery validation doesn't work with the Range attribute and DateTime. たとえば、次のコードでは、指定した範囲内の日付であっても、クライアント側の検証エラーが常に表示されます。For example, the following code will always display a client-side validation error, even when the date is in the specified range:

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

一般的に、モデルに日付をハードコーディングしてコンパイルすることは推奨されません。そのため、Range 属性と DateTime の使用は推奨されません。It's generally not a good practice to compile hard dates in your models, so using the Range attribute and DateTime is discouraged.

次のコードは、1 行で複数の属性を組み合わせる例です。The following code shows combining attributes on one line:

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]*$"), 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 ページと EF Core の概要に関するページでは、Razor ページでの EF Core 操作についてより詳しく説明されています。Get started with Razor Pages and EF Core shows advanced EF Core operations with Razor Pages.

移行を適用するApply migrations

クラスに適用された DataAnnotations によって、スキーマが変更されます。The DataAnnotations applied to the class changes the schema. たとえば、Titleフィールドに適用された DataAnnotations は次のようになります。For example, the DataAnnotations applied to the Title field:

[StringLength(60, MinimumLength = 3)]
[Required]
public string Title { get; set; }
  • 文字数を 60 に制限します。Limits the characters to 60.
  • null 値を許可しません。Doesn't allow a null value.

Movie テーブルには現在、次のスキーマがあります。The Movie table currently has the following schema:

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 によって例外がスローされることはありません。The preceding schema changes don't cause EF to throw an exception. ただし、スキーマがモデルと一致するように、移行を作成してください。However, create a migration so the schema is consistent with the model.

[ツール] メニューで、 [NuGet パッケージ マネージャー]、[パッケージ マネージャー コンソール] の順に選択します。From the Tools menu, select NuGet Package Manager > Package Manager Console. PMC で、次のコマンドを入力します。In the PMC, enter the following commands:

Add-Migration New_DataAnnotations
Update-Database

Update-Database では、New_DataAnnotations クラスの Up メソッドが実行されます。Update-Database runs the Up methods of the New_DataAnnotations class. Up メソッドを検証します。Examine the Up method:

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 テーブルには、次のスキーマがあります。The updated Movie table has the following schema:

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 に発行するPublish to Azure

Azure へのデプロイの詳細については、「チュートリアル: SQL Database を使用して Azure に ASP.NET Core アプリを作成する」をご覧ください。For information on deploying to Azure, see Tutorial: Build an ASP.NET Core app in Azure with SQL Database.

このたびは、この Razor Pages の紹介を最後までお読みいただきありがとうございました。Thanks for completing this introduction to Razor Pages. このチュートリアルの後は、Razor Pages と EF Core の概要に関するページにお進みいただくことをお勧めします。Get started with Razor Pages and EF Core is an excellent follow up to this tutorial.

その他の技術情報Additional resources