カテゴリー別アーカイブ: DataAnnotations

【F# + ASP.NET MVC】 リモート検証(指定されたアクションで正否を判定)を行うには

◆Controller(リモート検証用)
  ※ 検証のタイミングを遅らせる場合は、こちらを参照。

namespace Sample.Controllers

open System
open System.Web.Mvc

type LoginController() =
    inherit Controller()

    [<HttpPost>]
    member this.Index() =
        this.View() :> ActionResult

    // リモート検証アクション
    member this.IsLogin(userName : string) : JsonResult =
        if userName = "admin" then
            // 検証OK
            base.Json(true, JsonRequestBehavior.AllowGet)
        else
            // 検証NG
            base.Json(false, JsonRequestBehavior.AllowGet)

◆Entity

namespace Sample.Entities

open System.Web.Mvc

type Employee() =
    let mutable userName = ""
    
    // リモート検証
    [<Remote("IsLogin","Login")>]
    member x.UserName
        with get() = userName
        and set v = userName <- v
    

◆Controller

namespace Sample.Controllers

open System.Web
open System.Web.Mvc

open Sample.Models
open Sample.Entities

type HomeController() =
    inherit Controller()

    member this.Index() =
        this.View() :> ActionResult

    [<HttpPost>]
    member this.Index(entity:Employee) =
        // 検証結果を判定
        if this.ModelState.IsValid then
            this.ViewData.["Message"] <- "検証OK"
        else
            this.ViewData.["Message"] <- "検証NG"

        this.View(entity) :> ActionResult

◆View

@model Sample.Entities.Employee

@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <title>F# + ASP.NET</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet"
        type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
        type="text/javascript"></script>
    <!-- クライアントサイド検証を有効に設定-->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
        type="text/javascript"></script>
</head>
<body>
    <div>
        @using (Html.BeginForm()) {
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.UserName)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.UserName)
                    @Html.ValidationMessageFor(model => model.UserName)
                </div>
                <p>
                    <input type="submit" value="Validate" />
                </p>
            </fieldset>
        }
    </div>
</body>
</html>

【F# + ASP.NET MVC】 アノテーション検証用Attributeを自作するには

◆Attribute(半角数値検証用)

namespace MsdnWeb.Attributes

open System
open System.ComponentModel.DataAnnotations
open System.Text.RegularExpressions

// 半角数値検証用Attribute
[<AttributeUsageAttribute(AttributeTargets.Property, AllowMultiple = false)>]
type NumberStringAttribute() =
    inherit ValidationAttribute()
        // コンストラクタ
        do
            base.ErrorMessage <- "{0}は半角数字を入力してください。"
        // 検証メソッド
        override x.IsValid(value, validationContext) =
            let regex = new Regex("^([0-9])*$")
            match value with
                // 値がブランクの場合は、検証OKとする
                | _ when value.ToString().Length = 0
                    -> ValidationResult.Success
                // 半角数値チェック
                | _ when regex.IsMatch(value.ToString())
                    -> ValidationResult.Success
                // 検証NG
                | _ -> ValidationResult(String.Empty)

◆Entity(使用例)

namespace MsdnWeb.Entities

open System.ComponentModel
open System.ComponentModel.DataAnnotations
open MsdnWeb.ValidationAttributes

type Employee() =
    let mutable age = ""
    
    // 半角数値検証
    [<NumberString>]
    member x.ID
        with get() = age
        and set v = age <- v

◆View

@model MsdnWeb.Entities.Employee

@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <title>F# + ASP.NET</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet"
        type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
        type="text/javascript"></script>
    <!-- クライアントサイド検証を有効に設定-->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
        type="text/javascript"></script>
</head>
<body>
    <div>
        @using (Html.BeginForm()) {
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.ID)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.ID)
                    @Html.ValidationMessageFor(model => model.ID)
                </div>
                <p>
                    <input type="submit" value="Validate" />
                </p>
            </fieldset>
        }
    </div>
</body>
</html>

【F# + ASP.NET MVC】 複数のプロパティを参照して検証するには

◆Entity

namespace MsdnWeb.Entities

open System.ComponentModel
open System.ComponentModel.DataAnnotations

type Employee() =
    let mutable id = ""
    let mutable password = ""
    
    [<DisplayName("ID")>]
    member x.ID
        with get() = id
        and set v = id <- v

    [<DisplayName("パスワード")>]
    [<DataType(DataType.Password)>]
    member x.Password
        with get() = password
        and set v = password <- v

    // 複数のプロパティを参照しての検証
    interface IValidatableObject with
        member x.Validate(validationContext : ValidationContext)
            = seq { 
                if (x.ID = "admin") && (x.Password = "ok") then
                    ()
                else
                    yield ValidationResult(
                        "IDまたはパスワードが間違っています。"
                        , seq["ID"; "Password"] ) 
                }

◆View

@model MsdnWeb.Entities.Employee

@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <title>F# + ASP.NET MVC</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet"
        type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
        type="text/javascript"></script>
    <!-- クライアントサイド検証を有効に設定-->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
        type="text/javascript"></script>
</head>
<body>
    <div>
        @using (Html.BeginForm()) {
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.ID)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.ID)
                    @Html.ValidationMessageFor(model => model.ID)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Password)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Password)
                    @Html.ValidationMessageFor(model => model.Password)
                </div>
                <p>
                    <input type="submit" value="Validate" />
                </p>
            </fieldset>
        }
    </div>
</body>
</html>

【F# + ASP.NET MVC】 アノテーション検証を行うには その2

◆Entity

namespace MsdnWeb.Entities

open System.Collections.Generic
open System.ComponentModel
open System.ComponentModel.DataAnnotations
open System.Web.Mvc

type Employee() =
    let mutable date = System.DateTime.Today
    let mutable email = ""
    let mutable comfirmEmai = ""
    
    [<DisplayName("日付")>]
    //日付型か検証
    [<DataType(DataType.Date)>]
    member x.Date
        with get() = date
        and set v = date <- v

    [<DisplayName("Eメール")>]
    // Eメール型か検証
    // ※ 入力制限は行われないが、
    //    HTMLヘルパーのDisplayForメソッドで
    //    Eメールソフトへのリンク表示される
    [<DataType(DataType.EmailAddress)>]
    member x.Email
        with get() = email
        and set v = email <- v

    [<DisplayName("確認用Eメール")>]
    // 他のプロパティと同等か検証
    [<Compare("Email",
        ErrorMessage = "{0}は入力されたEメールと異なります。")>]
    member x.ComfirmEmai
        with get() = comfirmEmai
        and set v = comfirmEmai <- v

◆View

@model MsdnWeb.Entities.Employee

@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <title>F# + ASP.NET MVC</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet"
        type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")"
        type="text/javascript"></script>
    <!-- クライアントサイド検証を有効に設定-->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
        type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
        type="text/javascript"></script>
</head>
<body>
    <div>
        @using (Html.BeginForm()) {
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Date)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Date)
                    @Html.ValidationMessageFor(model => model.Date)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Email)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Email)
                    @Html.DisplayFor(model => model.Email)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.ComfirmEmai)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.ComfirmEmai)
                    @Html.ValidationMessageFor(model => model.ComfirmEmai)
                </div>
                <p>
                    <input type="submit" value="Validate" />
                </p>
            </fieldset>
        }
    </div>
</body>
</html>

【F# + ASP.NET MVC】 アノテーション検証を行うには

◆Entity

namespace MsdnWeb.Entities

open System.Collections.Generic
open System.ComponentModel
open System.ComponentModel.DataAnnotations

type Employee() =
    let mutable id = 0
    let mutable name = ""
    let mutable age = 0

    [<DisplayName("ユーザーID")>]
    // 必須検証
    [<Required(ErrorMessage = "{0}は必須です。")>]
    // 正規表現検証
    [<RegularExpression("[0-9]{3}",
        ErrorMessage = "{0}は数字3桁で入力してください。")>]
    member x.ID
        with get() = id
        and set v = id <- v

    [<DisplayName("名前")>]
    // 文字列長検証
    [<StringLength(10,
        ErrorMessage ="{0}は{1}文字以内で入力してください。")>]
    member x.Name
        with get() = name
        and set v = name <- v

    [<DisplayName("年齢")>]
    // 値範囲検証
    [<Range(20, 60,
        ErrorMessage="{0}は{1}~{2}の間で入力してください。")>]
    member x.Age
        with get() = age
        and set v = age <- v

◆Controller

namespace MsdnWeb.Controllers

open System.Web
open System.Web.Mvc

open MsdnWeb.Models
open MsdnWeb.Entities

type HomeController() =
    inherit Controller()

    member this.Index() =
        this.View() :> ActionResult

    [<HttpPost>]
    member this.Index(entity:Employee) =
        // 検証結果を判定
        if this.ModelState.IsValid then
            this.ViewData.["Message"] <- "検証OK"
        else
            this.ViewData.["Message"] <- "検証NG"

        this.View(entity) :> ActionResult

◆View(項目ごとに個別検証)

@model MsdnWeb.Entities.Employee
           
@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <title>F# + ASP.NET MVC</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" 
        type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" 
        type="text/javascript"></script>
    <!-- クライアントサイド検証を有効に設定-->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 
        type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" 
        type="text/javascript"></script>
</head>
<body>
    <div>
        @using (Html.BeginForm()) { 
            @Html.ValidationSummary(true)
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.ID)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.ID)
                    @Html.ValidationMessageFor(model => model.ID)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Name)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Name)
                    @Html.ValidationMessageFor(model => model.Name)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Age)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Age)
                    @Html.ValidationMessageFor(model => model.Age)
                </div>
                <p>
                    <input type="submit" value="Create" />
                </p>
            </fieldset>
        }
    </div>
</body>
</html>

◆View(項目をまとめて検証)

@model MsdnWeb.Entities.Employee
           
@{ Layout = null; }

<!DOCTYPE html>

<html>
<head>
    <title>F# + Entity Framework</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" 
        type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" 
        type="text/javascript"></script>
    <!-- クライアントサイド検証を有効に設定-->
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" 
        type="text/javascript"></script> 
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" 
        type="text/javascript"></script>
</head>
<body>
    <div>
        @using (Html.BeginForm()) { 
            @Html.ValidationSummary(false)
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.ID)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.ID)
                    @Html.ValidationMessageFor(model => model.ID, "*")
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Name)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Name)
                    @Html.ValidationMessageFor(model => model.Name, "*")
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Age)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Age)
                    @Html.ValidationMessageFor(model => model.Age, "*")
                </div>
                <p>
                    <input type="submit" value="Validate" />
                </p>
            </fieldset>
        }
    </div>
</body>
</html>

【Silverlight】 カスタム検証属性を作成するには

◆検証属性(数値チェック)

using System;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace Validations.ValidationAttributes
{
  [AttributeUsage(AttributeTargets.Property
    , AllowMultiple = true, Inherited = true)]
  public class NumberStringAttribute : ValidationAttribute
  {
    public NumberStringAttribute()
    {
        // エラーメッセージ
      this.ErrorMessage = "{0}は数値文字を入力してください。";
    }

    protected override ValidationResult IsValid
      (object value, ValidationContext validationContext)
    {
      if (value.ToString().Length == 0)
        return ValidationResult.Success;

      // 数値チェック
      if (new Regex("^([0-9])*$").IsMatch(value.ToString() ))
        return ValidationResult.Success;
      else
        return new ValidationResult(string.Empty);
    }    
  }
}

◆使用例(プロパティに NumberStringAttribute を適用)

[NumberString()]
public string Age
{
  get { return Model.Age; }
  set
  {
    Model.Age = value;
    this.RaisePropertyChanged(() => Age);
  }
}