2011-02-09 2 views
7

Я изучал возможности проверки на стороне клиента в ASP.net MVC после прочтения ScottGU's blog post по этому вопросу. Это довольно легко использовать 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 контроллера и соответствующим образом проверяет его. Это отлично работает на стороне сервера, но не работает с новой проверкой на стороне клиента.

В веб-формах я бы использовал элементы управления с использованием javascript, такие как RequiredFieldValidator или CompareValidator, для простого использования, а затем использовать CustomValidator для сложных правил. Таким образом, у меня есть вся моя логика проверки в одном месте, и я получаю преимущество быстрой проверки javascript для простых вещей (в 90% случаев), в то время как я по-прежнему получаю безопасность проверки на стороне сервера в качестве блокиратора обратного хода.

Каким будет эквивалентный подход в MVC?

+0

Я не уверен в этом, но я думаю, вам в значительной степени придется выкатывать собственную проверку клиента для таких вещей. Возможно, посмотрите на Jquery Validation-http: //docs.jquery.com/Plugins/validation – Vishal

+0

Какую версию ASP.NET MVC вы используете? –

ответ

1

Я только что увидел что-то о интерфейсе IValidatableObject в MVC 3, и я дам попробовать.

1

Получите свой собственный атрибут проверки от ValidationAttribute и примените соответствующую логику. В MVC 2, чтобы выполнить проверку свойства на основе значения другого свойства, это должно быть сделано внутри Validator, который вы регистрируете для использования с атрибутом пользовательской проверки, используя (при условии, что вы используете DataAnnotationsModelValidatorProvider)

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

, потому что в атрибуте проверки вы имеете доступ только к значению свойства, к которому привязан атрибут, а не к модели.

Посмотрите на MVC FoolProof Validation, чтобы узнать, как это делается.

+0

Это автоматически получает подтверждение на стороне клиента после проверки? – CRice

+0

@CRice - если из одного из атрибутов в System.ComponentModel.DataAnnotations, то клиентская сторона будет заботиться о вас. Если вы определяете свою собственную валидацию, вам также нужно будет самостоятельно позаботиться о написании логики на стороне клиента. Предполагая, что вы используете проверку jQuery, вы должны добавить функцию валидатора для вызова проверки jQuery с помощью строки, используемой, когда правило проверки соответствует ключу. –

+0

Как система знает, какой javascript для вывода использовать для проверки любого наследуемого класса, наследуемого от System.ComponentModel.DataAnnotations.ValidationAttribute? – CRice

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 проверки и ненавязчивые проверки уровень мобильной станции, как читать ваши новые атрибуты:

/// <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)); 

Надеется, что это помогает, это был реальная боль, чтобы получить работу.

+0

Хорошее объяснение, имеет смысл видеть его от начала до конца – CRice

+0

Спасибо, @CRice. Надеюсь, это поможет кому-то другому. Я бы убил что-то вроде этого, в то время как MVC 3 был в бета-версии, но все было в кусках. –

+0

@SheaDaniels «К сожалению, мой код находится в VB.NET, так как это то, что я должен использовать на работе». Это достаточно для новой работы! – Elisabeth

3

ScottGu твиттер сегодня утром, как Pluralsight имеет бесплатное MVC 3 training в течение следующих 48 часов. У них есть видео, показывающее, как выполнить такую ​​специальную проверку. Соответствующие видео находятся в разделе «Модели в ASP.NET MVC 3.0», в частности «Пользовательские атрибуты проверки» и «Самонастраивающиеся модели».

+0

Отличные видео. И блестящий маркетинг, чтобы отдать их на два дня. –

+0

+1 Отличное видео. Я только что зарегистрировался для бесплатной пробной версии и наблюдал за «Индивидуальной проверкой клиента». Это было довольно тщательно и помогло. Я сейчас на 10-дневной пробной версии и могу посмотреть еще несколько, прежде чем она закончится. Они обеспечивают хорошее обслуживание. – Aaron

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; } 
} 

Просмотр Сильно типа с этим классом

Смежные вопросы