2011-02-09 295 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; } 
} 

查看本类强类型