【ASP.NET MVC】【Razor】【VB】 Razor ~ Validation / 応用編 [2] ~

独自のデータ検証を行う

 * 以下の2パターンを考える

 [1] 1つのプロパティに対して、独自の検証を行う
 [2] 複数プロパティをまたがった検証を行う

※今回は、[1]を扱う

■ポイント

 => ValidationAttributeを継承することにより、カスタム属性の作成する

※ただ、正規表現による検証「RegularExpressionValidator」を使用できないかを検討してみた方がいい
http://blog.shibayan.jp/entry/20110708/1310132392
http://blog.shibayan.jp/entry/20130619/1371576352
http://www.atmarkit.co.jp/fdotnet/scottgublog/20100208mvc2mvalidation/mvc2mvalidation.html
http://www.remember-the-time.xyz/2012/05/aspnet-mvc-url.html
http://d.hatena.ne.jp/fyts/20071017/validator

クライアント側でのチェックをするための環境設定

環境

 * Visual Studio : Microsoft Visual Studio Express 2015 for Web 

手順

[1] Visual Studio で [ツール]-[NuGetパッケージ マネージャー]-[パッケージ マネージャー コンソール]を選択
[2] 以下のコマンド(2つ)を入力する

Install-Package jQuery.Validation
Install-Package jQuery.Validation.Unobtrusive
https://www.nuget.org/packages/jQuery.Validation/
https://www.nuget.org/packages/jQuery.Validation.Unobtrusive/

出力画面:パッケージ マネージャー コンソール

パッケージ マネージャー コンソール ホストのバージョン 3.0.0.0

利用可能なすべての NuGet コマンドを参照するには、'get-help NuGet' を入力します。

PM> Install-Package jQuery.Validation
'.NETFramework,Version=v4.6' を対象とするプロジェクト 'WebAppli' に関して、パッケージ 'jQuery.Validation.1.14.0' の依存関係情報の収集を試行しています
DependencyBehavior 'Lowest' でパッケージ 'jQuery.Validation.1.14.0' の依存関係の解決を試行しています
パッケージ 'jQuery.Validation.1.14.0' をインストールするアクションを解決しています
パッケージ 'jQuery.Validation.1.14.0' をインストールするアクションが解決されました
パッケージ 'jQuery.Validation.1.14.0' をフォルダー 'C:\Xxxx\visual studio 2015\Projects\WebAppli\packages' に追加しています
パッケージ 'jQuery.Validation.1.14.0' をフォルダー 'C:\Xxxx\visual studio 2015\Projects\WebAppli\packages' に追加しました
パッケージ 'jQuery.Validation.1.14.0' を 'packages.config' に追加しました
'jQuery.Validation 1.14.0' が WebAppli に正常にインストールされました
PM> Install-Package jQuery.Validation.Unobtrusive
'.NETFramework,Version=v4.6' を対象とするプロジェクト 'WebAppli' に関して、パッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' の依存関係情報の収集を試行しています
DependencyBehavior 'Lowest' でパッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' の依存関係の解決を試行しています
パッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' をインストールするアクションを解決しています
パッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' をインストールするアクションが解決されました
パッケージ 'Microsoft.jQuery.Unobtrusive.Validation.2.0.20710' をフォルダー 'C:\Xxxx\visual studio 2015\Projects\WebAppli\packages' に追加しています
パッケージ 'Microsoft.jQuery.Unobtrusive.Validation.2.0.20710' をフォルダー 'C:\Xxxx\visual studio 2015\Projects\WebAppli\packages' に追加しました
パッケージ 'Microsoft.jQuery.Unobtrusive.Validation.2.0.20710' を 'packages.config' に追加しました
'Microsoft.jQuery.Unobtrusive.Validation 2.0.20710' が WebAppli に正常にインストールされました
依存関係のみが含まれるパッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' をプロジェクト 'WebAppli' に追加しています。
パッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' をフォルダー 'C:\Xxxx\visual studio 2015\Projects\WebAppli\packages' に追加しています
パッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' をフォルダー 'C:\Xxxx\visual studio 2015\Projects\WebAppli\packages' に追加しました
パッケージ 'jQuery.Validation.Unobtrusive.2.0.20710' を 'packages.config' に追加しました
'jQuery.Validation.Unobtrusive 2.0.20710' が WebAppli に正常にインストールされました
PM> 

サンプル

http://blogs.yahoo.co.jp/dk521123/35593993.html
のサンプルに、独自検証(サーバ側、クライアント側)を行う
# コントローラ「PersonController.vb」およびビュー「Result.vbhtml」に変更はないので省略。

■ カスタム属性

* NoneValidationAttribute.vb
Imports System.ComponentModel.DataAnnotations
Imports System.Globalization
Imports System.Web.Mvc

<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False)>
Public Class NoneValidationAttribute : Inherits ValidationAttribute
    Implements IClientValidatable

    ' 値リストを表すプライベート変数
    Private _opts As String

    Public Sub New(ByVal opts As String)
        Me._opts = opts
        Me.ErrorMessage = "{0}は、{1}を設定しないで下さい。"
    End Sub


    '  プロパティの表示名と値リストでエラー・メッセージを整形
    Public Overrides Function FormatErrorMessage(ByVal name As String) As String
        Return String.Format(CultureInfo.CurrentCulture,
                             ErrorMessageString, name, Me._opts)
    End Function

    Public Function GetClientValidationRules(
        metadata As ModelMetadata, context As ControllerContext) As IEnumerable(Of ModelClientValidationRule) Implements IClientValidatable.GetClientValidationRules
        ' 検証ルールを準備
        Dim rule = New ModelClientValidationRule() With
        {
            .ValidationType = "enumnonevalue", ' 検証名
            .ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()) ' エラー
        }
        rule.ValidationParameters("opts") = Me._opts ' 検証パラメータ
        Dim list = New List(Of ModelClientValidationRule)()
        list.Add(rule)
        Return list
    End Function

    ' サーバ側の検証
    Public Overrides Function IsValid(ByVal value As Object) As Boolean

        ' 入力値が空の場合は検証をスキップ  
        If value Is Nothing Then
            Return True
        End If

        ' Noneだったら不正
        If value.ToString().Equals("None") Then
            Return False
        End If

        Return True
    End Function
End Class

■ モデル

* PersonModel.vb
Imports System.Web.Mvc

Namespace Models
    Public Class PersonModel
        Private Property _Id As Long
        Private Property _Name As String
        Private Property _Gender As Gender

        <ComponentModel.DisplayName("ID")>
        <ComponentModel.DataAnnotations.Required(ErrorMessage:="{0}は必須です。")>
        <ComponentModel.DataAnnotations.Range(100, 10000, ErrorMessage:="{0}は{1}~{2}の間で入力してください。")>
        Public Property Id As Long
            Get
                Return Me._Id
            End Get
            Set(ByVal value As Long)
                Me._Id = value
            End Set
        End Property

        <ComponentModel.DisplayName("名前")>
        <ComponentModel.DataAnnotations.Required(ErrorMessage:="{0}は必須です。")>
        <ComponentModel.DataAnnotations.StringLength(100, ErrorMessage:="{0}は{1}文字以内で入力してください。")>
        Public Property Name As String
            Get
                Return Me._Name
            End Get
            Set(ByVal value As String)
                Me._Name = value
            End Set
        End Property

        ' ★ここに適用★
        <NoneValidation("None")>
        Public Property Gender As Gender
            Get
                Return Me._Gender
            End Get
            Set(ByVal value As Gender)
                Me._Gender = value
            End Set
        End Property
    End Class

    Public Enum Gender
        None
        Man
        Woman
    End Enum

End Namespace

■ ビュー

* Index.vbhtml
@ModelType WebAppli.Models.PersonModel
@Code
    ViewData("Title") = "View"
End Code

<script src="@Url.Content("~/Scripts/jquery-1.10.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/enumNoneValue.js")" type="text/javascript"></script>

<h2>View</h2>
@Using (Html.BeginForm(
             "Result", ' アクション名
             "Person", ' コントローラ名
             FormMethod.Post))

    @Html.AntiForgeryToken()
    @Html.ValidationSummary(False, "", New With {.class = "text-danger"})

    @Html.LabelFor(Function(model) model.Id, htmlAttributes:=New With {.class = "control-label col-md-2"})
    @Html.EditorFor(Function(model) model.Id, New With {.htmlAttributes = New With {.class = "form-control"}})
    @Html.ValidationMessageFor(Function(model) model.Id, "*")
    @<br />

    @Html.LabelFor(Function(model) model.Name, htmlAttributes:=New With {.class = "control-label col-md-2"})
    @Html.EditorFor(Function(model) model.Name, New With {.htmlAttributes = New With {.class = "form-control"}})
    @Html.ValidationMessageFor(Function(model) model.Name, "*")
    @<br />

    @Html.EnumDropDownListFor(Function(model) model.Gender, "Please select", Nothing)
    @Html.ValidationMessageFor(Function(model) model.Gender, "*")
    @<br />

    @<input type = "submit" value="Send" Class="btn btn-default" />
End Using

JavaScript:クライアント側の検証

* /Scripts/enumNoneValue.js
//  インテリセンス機能を有効化
/// <reference path="jquery-1.10.2.js" />

//  enumNoneValue検証をjQuery Validationに登録
$.validator.addMethod("enumnonevalue", function (value, element, param) {

    // 入力値が空の場合は検証をスキップ
    value = $.trim(value);
    if (value === '') {
        return true;
    }

    // Noneだったら不正
    if (value === "0") {
        return false;
    }
    return true;
});

$.validator.unobtrusive.adapters.addSingleVal('enumnonevalue', 'opts');


関連記事

Razor ~入門編~

http://blogs.yahoo.co.jp/dk521123/35586581.html

Razor ~ Validation / 基本編 [1] ~

http://blogs.yahoo.co.jp/dk521123/35593993.html

Razor ~ Validation / 応用編 [2] ~

http://blogs.yahoo.co.jp/dk521123/35596847.html

Razor ~ Validation / 応用編 [3] ~

http://blogs.yahoo.co.jp/dk521123/35599883.html