asp.net mvc 客户端验证

标签 asp.net asp.net-mvc

在阅读 ScottGU's blog post 后,我一直在修改 ASP.net MVC 中的客户端验证功能。就此主题而言。使用 System.Componentmodel.DataAnnotations 属性非常简单,如下所示:

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

...但是如果您需要更复杂一点的东西会发生什么。如果您有一个包含 PostalCode 和 CountryCode 字段的 Address 类,该怎么办?您可能希望针对每个国家/地区使用不同的正则表达式来验证邮政编码。 [0-9]{5} 适用于美国,但您需要为加拿大使用不同的。

我通过滚动我自己的 ValidationService 类来解决这个问题,该类采用 Controller 的 ModelState 属性并相应地对其进行验证。这在服务器端工作得很好,但不适用于新奇的客户端验证。

在 Webforms 中,我会使用 JavaScript 发射控件(例如,RequiredFieldValidator 或 CompareValidator)来处理简单的事情,然后使用 CustomValidator 来处理复杂的规则。这样我就可以将所有验证逻辑集中在一个地方,并且可以从简单内容的快速 javascript 验证中受益(90% 的时间),同时我仍然可以获得服务器端验证的安全性作为后盾。

MVC 中的等效方法是什么?

最佳答案

编辑:假设您使用的是 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));

希望这会有所帮助,这对工作来说真的很痛苦。

关于asp.net mvc 客户端验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4951531/

相关文章:

c# - 如何使用 Property List<IOBJ> 对对象进行 json 序列化或 json 反序列化?

javascript - 在 Kendo Grid 中,当用户在 "items per page"下拉列表中选择特定值时如何添加警报?

asp.net-mvc - 如何最好地在服务器上安装MVC 3?

c# - 当用户点击网站链接时自动填写用户名+密码

asp.net - 如何在服务器发布操作结果后打开新选项卡

c# - ISomeInterface referenceVariable = ClassThatImplementsIt

c# - 消息正文中定义的错误代码的 AdalServiceException 列表

c# - 无法在 Electron 应用程序中使用 Discord OAuth2

asp.net-mvc - Unity 不解析依赖

asp.net - 找不到 'aspnetcorev2_inprocess.dll' 。异常消息