データ検証注釈コントロールの検証 (C#)

提供元: Microsoft

データ注釈モデル バインダーを利用して、ASP.NET MVC アプリケーション内で検証を実行します。 さまざまな種類の検証コントロール属性を使用して、Microsoft Entity Framework で操作する方法について説明します。

このチュートリアルでは、データ注釈検証コントロールを使用して、ASP.NET MVC アプリケーションで検証を実行する方法について説明します。 データ注釈検証コントロールを使用する利点は、Required や StringLength 属性などの 1 つ以上の属性をクラス プロパティに追加するだけで検証を実行できる点です。

データ注釈モデル バインダーは、Microsoft ASP.NET MVC フレームワークで公式に提供されているわけではないことを理解しておくことが重要です。 データ注釈モデル バインダーは Microsoft ASP.NET MVC チームが作成したものですが、Microsoft は、このチュートリアルで説明および使用されるデータ注釈モデル バインダーに対して公式製品サポートを提供していません。

データ注釈モデル バインダーの使用

ASP.NET MVC アプリケーションでデータ注釈モデル バインダーを使用するには、まず、Microsoft.Web.Mvc.DataAnnotations.dll アセンブリと System.ComponentModel.DataAnnotations.dll アセンブリへの参照を追加する必要があります。 メニュー オプション [プロジェクト]、[参照の追加] の順に選択します。 次に、[参照] タブをクリックし、データ注釈モデル バインダーのサンプルをダウンロード (および解凍) した場所を参照します (図 1 を参照)。

Image of browse tab

図 1: データ注釈モデル バインダーへの参照の追加 (クリックするとフルサイズの画像が表示されます)

Microsoft.Web.Mvc.DataAnnotations.dll アセンブリと System.ComponentModel.DataAnnotations.dll アセンブリの両方を選択し、[OK] ボタンをクリックします。

.NET Framework Service Pack 1 に含まれる System.ComponentModel.DataAnnotations.dll アセンブリは、データ注釈モデル バインダーで使用することはできません。 データ注釈モデル バインダー サンプルのダウンロードに含まれている System.ComponentModel.DataAnnotations.dll アセンブリのバージョンを使用する必要があります。

最後に、DataAnnotations モデル バインダーを Global.asax ファイルに登録する必要があります。 Application_Start() メソッドが次のようになるように、Application_Start() イベント ハンドラーに次のコード行を追加します。

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    ModelBinders.Binders.DefaultBinder = new Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder();
}

このコード行により、ASP.NET MVC アプリケーション全体の既定のモデル バインダーとして ataAnnotationsModelBinder が登録されます。

データ注釈検証コントロール属性の使用

データ注釈モデル バインダーを使用する場合は、検証コントロール属性を使用して検証を実行します。 System.ComponentModel.DataAnnotations 名前空間には、次の検証コントロール属性が含まれています。

  • Range – プロパティの値が指定した値の範囲の間にあるかどうかを検証できます。
  • RegularExpression – プロパティの値が指定した正規表現パターンと一致するかどうかを検証できます。
  • Required – プロパティを必須としてマークできます。
  • StringLength – 文字列プロパティの最大長を指定できます。
  • Validation – すべての検証コントロール属性の基底クラス。

Note

検証のニーズが標準検証コントロールのいずれにも満たない場合に、基底の Validation 属性から新しい検証属性を継承してカスタム検証コントロール属性を作成するオプションが常に用意されています。

リスト 1 の Product クラスは、これらの検証コントロール属性の使用方法を示しています。 Name、Description、UnitPrice プロパティは必須としてマークされます。 Name プロパティの文字列の長さは 10 文字未満である必要があります。 そして、UnitPrice プロパティは、通貨金額を表す正規表現パターンと一致している必要があります。

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

namespace MvcApplication1.Models
{
    
    public class Product
    {
        public int Id { get; set; }

        [Required]
        [StringLength(10)]
        public string Name { get; set; }

        [Required]
        public string Description { get; set; }

        [DisplayName("Price")]
        [RegularExpression(@"^\$?\d+(\.(\d{2}))?$")]
        public decimal UnitPrice { get; set; }
    }
}

リスト 1: Models\Product.cs

この Product クラスは、DisplayName 属性という 1 つの追加属性を使用する方法を示しています。 DisplayName 属性を使用すると、エラー メッセージに表示されるプロパティの名前を変更できます。 [The UnitPrice field is required] (UnitPrice フィールドは必須です) というエラー メッセージを表示する代わりに、[The Price field is required] (Price フィールドは必須です) というエラー メッセージを表示できます。

Note

検証コントロールによって表示されるエラー メッセージを全体的にカスタマイズする場合は、<Required(ErrorMessage:="This field needs a value!")> のように、検証コントロールの ErrorMessage プロパティにカスタム エラー メッセージを割り当てることができます。

リスト 1 の Product クラスは、リスト 2 の Create() コントローラー アクションで使用できます。 このコントローラー アクションは、モデルの状態にエラーが含まれている場合に作成ビューを再表示します。

using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    public class ProductController : Controller
    {
         //
        // GET: /Product/Create

        public ActionResult Create()
        {
            return View();
        } 

        //
        // POST: /Product/Create

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create([Bind(Exclude="Id")]Product productToCreate)
        {
            if (!ModelState.IsValid)
                return View();

            // TODO: Add insert logic here
            return RedirectToAction("Index");
        }

    }
}

リスト 2: Controllers\ProductController.vb

最後に、リスト 3 でビューを作成するには、Create() アクションを右クリックし、メニュー オプション [ビューの追加] を選択します。 Product クラスをモデル クラスとして使用して、厳密に型指定されたビューを作成します。 [ビュー コンテンツ] ドロップダウン リストから、[作成] を選択します (図 2 を参照)。

Image of add view dialog box

図 2: 作成ビューの追加

<%@ Page Title="" Language="C#" MasterPageFile="Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Product>" %>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>

    <%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

    <% using (Html.BeginForm()) {%>

        <fieldset>
            <legend>Fields</legend>
            <p>
                <label for="Name">Name:</label>
                <%= Html.TextBox("Name") %>
                <%= Html.ValidationMessage("Name", "*") %>
            </p>
            <p>
                <label for="Description">Description:</label>
                <%= Html.TextBox("Description") %>
                <%= Html.ValidationMessage("Description", "*") %>
            </p>
            <p>
                <label for="UnitPrice">Price:</label>
                <%= Html.TextBox("UnitPrice") %>
                <%= Html.ValidationMessage("UnitPrice", "*") %>
            </p>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>

    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

リスト 3: Views\Product\Create.aspx

Note

[ビューの追加] メニュー オプションによって生成された [作成] フォームから "Id" フィールドを削除します。 "Id" フィールドは ID 列に対応しているため、ユーザーがこのフィールドの値を入力できないようにします。

製品を作成するためのフォームを送信し、必須フィールドの値を入力していないと、図 3 の検証エラー メッセージが表示されます。

Image of all validation errors

図 3: 必須フィールドが未記入

無効な通貨金額を入力すると、図 4 のエラー メッセージが表示されます。

Image of invalid currency validation error

図 4: 無効な通貨金額

Entity Framework でのデータ注釈検証コントロールの使用

Microsoft Entity Framework を使用してデータ モデル クラスを生成する場合、検証コントロール属性をクラスに直接適用することはできません。 Entity Framework デザイナーによってモデル クラスが生成されるため、次にデザイナーで変更を加えたときに、モデル クラスに対して行った変更はすべて上書きされます。

Entity Framework によって生成されたクラスで検証コントロールを使用する場合は、メタ データ クラスを作成する必要があります。 検証コントロールは、実際のクラスに適用するのではなく、メタ データ クラスに適用します。

たとえば、Entity Framework を使用して Movie クラスを作成したとします (図 5 を参照)。 さらに、 Movie Title と Director のプロパティを必須プロパティにするとします。 その場合は、リスト 4 で部分クラスとメタ データ クラスを作成します。

Image of movie class

図 5: Entity Framework によって生成された Movie クラス

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

namespace MvcApplication1.Models
{
    [MetadataType(typeof(MovieMetaData))]
    public partial class Movie
    {
    }

    public class MovieMetaData
    {
        [Required]
        public object Title { get; set; }

        [Required]
        [StringLength(5)]
        public object Director { get; set; }

        [DisplayName("Date Released")]
        [Required]
        public object DateReleased { get; set; }
    }

}

リスト 4: Models\Movie.cs

リスト 4 のファイルには、Movie と MovieMetaData という名前の 2 つのクラスが含まれています。 Movie クラスは部分クラスです。 これは、 Entity Framework によって生成された、DataModel.Designer.vb ファイルに含まれる部分クラスに対応します。

現在、.NET フレームワークでは部分プロパティはサポートされていません。 したがって、リスト 4 のファイルで定義されている Movie クラスのプロパティに検証コントロール属性を適用することによって、DataModel.Designer.vb ファイルで定義されている Movie クラスのプロパティに検証コントロール属性を適用する方法はありません。

Movie 部分クラスは、MovieMetaData クラスを指す MetadataType 属性で修飾されていることに注意してください。 MovieMetaData クラスには、Movie クラスのプロパティのプロキシ プロパティが含まれています。

検証コントロール属性は、MovieMetaData クラスのプロパティに適用されます。 Title、Director、DateReleased プロパティはすべて、必須プロパティとしてマークされます。 Director プロパティには、5 文字未満の文字列を割り当てる必要があります。 最後に、DateReleased プロパティに DisplayName 属性が適用され、[The DateReleased field is required] (DateReleased フィールドは必須です) というエラーの代わりに、[The Date Released field is required] ("公開日" フィールドは必須です) のようなエラー メッセージが表示されます。

Note

MovieMetaData クラスのプロキシ プロパティは、Movie クラスの対応するプロパティと同じ型を表す必要はありません。 たとえば、Director プロパティは Movie クラスでは文字列プロパティで、MovieMetaData クラスではオブジェクト プロパティです。

図 6 のページには、Movie プロパティに無効な値を入力したときに返されるエラー メッセージを示しています。

Image of error message for invalid movie values

図 6: Entity Framework での検証コントロールの使用 (クリックするとフルサイズの画像が表示されます)

まとめ

このチュートリアルでは、データ注釈モデル バインダーを利用して、ASP.NET MVC アプリケーション内で検証を実行する方法を学習しました。 Required や StringLength 属性など、さまざまな種類の検証コントロール属性を使用する方法について学習しました。 また、Microsoft Entity Framework を使用するときにこれらの属性を使用する方法についても学習しました。