2011-02-09 290 views
7

在閱讀關於這個主題的ScottGU's blog post後,我一直在修補ASP.net MVC中的客戶端驗證功能。這是很容易使用System.Componentmodel.DataAnnotations屬性是這樣的:asp.net mvc客戶端驗證

[Required(ErrorMessage = "You must specify a reason")] 
    public string ReasonText { get; set; } 

...但如果你需要的東西只是一個稍微複雜一些,會發生什麼。如果您的Address類具有PostalCode和CountryCode字段,該怎麼辦?您需要針對每個國家/地區的不同正則表達式驗證郵政編碼。 [0-9] {5}適用於美國,但對於加拿大您需要另外一個。

我通過滾動我自己的ValidationService類來解決該問題,該類使用控制器的ModelState屬性並相應地進行驗證。這在服務器端很好用,但不適用於新的客戶端驗證。

在Webforms中,我會使用JavaScript的發射控制像RequiredFieldValidator或CompareValidator的簡單的東西,然後使用CustomValidator的複雜規則。通過這種方式,我可以將所有驗證邏輯集中在一個地方,並且我可以從簡單的東西(90%的時間)中獲得快速的javascript驗證,而我仍然可以將服務器端驗證的安全性作爲支持。

什麼是MVC中的等效方法?

+0

我不確定這一點,但我認爲你幾乎必須推出自己的客戶端驗證定製類似的東西。也許看看JQuery的驗證-http://docs.jquery.com/Plugins/validation – Vishal 2011-02-09 23:04:44

+0

你的目標是哪個版本的ASP.NET MVC? – 2011-02-09 23:04:58

回答

1

我剛剛在MVC 3中看到了有關IValidatableObject接口的一些信息,我會試試看。

1

ValidationAttribute導出您自己的驗證屬性並相應地應用邏輯。在MVC 2中,爲了根據另一個屬性的值執行屬性驗證,必須在Validator中進行驗證,該驗證程序使用自定義驗證屬性進行註冊(假設您使用的是DataAnnotationsModelValidatorProvider

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(ValidationAttribute), typeof(ValidationValidator)); 

因爲在驗證屬性中,您只能訪問綁定屬性的屬性值,而不是模型。

看看MVC FoolProof Validation看看這個方法是如何完成的。

+0

這是否會自動在開箱即用的客戶端驗證中找到答案? – CRice 2011-02-09 23:10:56

+0

@CRice - 如果從System.ComponentModel.DataAnnotations中的某個屬性派生出來,那麼客戶端將被照顧。如果定義自己的驗證attirbute,則還需要自己編寫客戶端邏輯。假設你使用jQuery驗證,你可以添加一個驗證器函數來調用jQuery驗證,驗證規則與密鑰匹配時使用字符串作爲密鑰。 – 2011-02-09 23:13:42

7

編輯:這假設你使用MVC 3.不幸的是我的代碼是在VB.NET中,因爲這是我在工作中使用。

爲了使一切正常工作與新的不顯眼的驗證有一些事情你必須做。幾周前我通過它們供電。

首先,創建一個繼承自ValidationAttribute的自定義屬性類。一個簡單的RequiredIf屬性類如下:

Imports System.ComponentModel 
Imports System.ComponentModel.DataAnnotations 

<AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> _ 
Public NotInheritable Class RequiredIfAttribute 
    Inherits ValidationAttribute 

    Private Const _defaultErrorMessage As String = "'{0}' is required." 
    Private ReadOnly _dependentProperty As String 
    Private ReadOnly _targetValues  As Object() 

    Public Sub New(dependentProperty As String, targetValues As Object()) 

     MyBase.New(_defaultErrorMessage) 

     _dependentProperty = dependentProperty 
     _targetValues  = targetValues 

    End Sub 

    Public Sub New(dependentProperty As String, targetValues As Object(), errorMessage As String) 

     MyBase.New(errorMessage) 

     _dependentProperty = dependentProperty 
     _targetValues  = targetValues 

    End Sub 

    Public ReadOnly Property DependentProperty() As String 
     Get 
      Return _dependentProperty 
     End Get 
    End Property 

    Public ReadOnly Property TargetValues() As Object() 
     Get 
      Return _targetValues 
     End Get 
    End Property 

    Public Overrides Function FormatErrorMessage(name As String) As String 

     Return String.Format(Globalization.CultureInfo.CurrentUICulture, ErrorMessageString, name) 

    End Function 

    Protected Overrides Function IsValid(value As Object, context As ValidationContext) As ValidationResult 

     ' find the other property we need to compare with using reflection 
     Dim propertyValue = context.ObjectType.GetProperty(DependentProperty).GetValue(context.ObjectInstance, Nothing).ToString() 

     Dim match = TargetValues.SingleOrDefault(Function(t) t.ToString().ToLower() = propertyValue.ToLower()) 

     If match IsNot Nothing AndAlso value Is Nothing Then 
      Return New ValidationResult(FormatErrorMessage(context.DisplayName)) 
     End If 

     Return Nothing 

    End Function 

End Class 

接下來,您需要實現一個驗證器類。這個類負責讓MVC知道不引人注意的驗證庫工作所需的客戶端驗證規則。現在

Public Class RequiredIfValidator 
    Inherits DataAnnotationsModelValidator(Of RequiredIfAttribute) 

    Public Sub New(metaData As ModelMetadata, context As ControllerContext, attribute As RequiredIfAttribute) 

     MyBase.New(metaData, context, attribute) 

    End Sub 

    Public Overrides Function GetClientValidationRules() As IEnumerable(Of ModelClientValidationRule) 

     Dim rule As New ModelClientValidationRule() With {.ErrorMessage = ErrorMessage, 
                  .ValidationType = "requiredif"} 

     rule.ValidationParameters("dependentproperty") = Attribute.DependentProperty.Replace("."c, HtmlHelper.IdAttributeDotReplacement) 

     Dim first  As Boolean = True 
     Dim arrayString As New StringBuilder() 

     For Each param In Attribute.TargetValues 
      If first Then 
       first = False 
      Else 
       arrayString.Append(",") 
      End If 
      arrayString.Append(param.ToString()) 
     Next 

     rule.ValidationParameters("targetvalues") = arrayString.ToString() 

     Return New ModelClientValidationRule() {rule} 

    End Function 

End Class 

你可以註冊的Global.asax應用啓動方法的一切:

DataAnnotationsModelValidatorProvider.RegisterAdapter(GetType(RequiredIfAttribute), GetType(RequiredIfValidator)) 

到此你90%的方式出現。現在,你只需要告訴jQuery驗證和MS的不顯眼的驗證層如何解讀新屬性:

/// <reference path="jquery-1.4.1-vsdoc.js" /> 
/// <reference path="jquery.validate-vsdoc.js" /> 

/* javascript for custom unobtrusive validation 
    ==================================================== */ 

(function ($) { 

    // this adds the custom "requiredif" validator to the jQuery validate plugin 
    $.validator.addMethod('requiredif', 
          function (value, element, params) { 

           // the "value" variable must not be empty if the dependent value matches 
           // one of the target values 
           var dependentVal = $('#' + params['dependentProperty']).val().trim().toLowerCase(); 
           var targetValues = params['targetValues'].split(','); 

           // loop through all target values 
           for (i = 0; i < targetValues.length; i++) { 
            if (dependentVal == targetValues[i].toLowerCase()) { 
             return $.trim(value).length > 0; 
            } 
           } 

           return true; 
          }, 
          'not used'); 

    // this tells the MS unobtrusive validation layer how to read the 
    // HTML 5 attributes that are output for the custom "requiredif" validator 
    $.validator.unobtrusive.adapters.add('requiredif', ['dependentProperty', 'targetValues'], function (options) { 

     options.rules['requiredif'] = options.params; 
     if (options.message) { 
      options.messages['requiredif'] = options.message; 
     } 

    }); 

} (jQuery)); 

希望這會有所幫助,這是一個真正的痛苦得到工作。

3

ScottGu今天早上在Twitter上發佈了一條消息,說明Pluralsight如何在接下來的48小時內免費獲得MVC 3 training。他們有一個視頻顯示如何做這種自定義驗證。相關視頻在「ASP.NET MVC 3.0中的模型」下,具體爲「自定義驗證屬性」和「自我驗證模型」。

0

我認爲解決問題的方法是在MVC

對於複雜的邏輯,你可以實現自己的邏輯System.ComponentModel.DataAnnotations。它非常簡單。 看一看定製此鏈接:http://msdn.microsoft.com/en-us/library/cc668224.aspx

對於基本的東西使您查看綁定與模型類和屬性上添加屬性... 像

public class CustomerSearchDE 
{ 
    [StringLength(2, ErrorMessageResourceType = typeof(Translation), ErrorMessageResourceName = MessageConstants.conCompanyNumberMaxLength)] 
    public string CompanyNumber { get; set; } 
} 

查看本類強類型