ASP.NET Аннотация данных MVC 3: добавление проверки динамически

#asp.net #validation #asp.net-mvc-3 #dynamic #data-annotations

#asp.net #проверка #asp.net-mvc-3 #динамический #данные-аннотации

Вопрос:

Я новичок в аннотации данных. Я хотел бы знать, возможно ли (и как) добавить некоторую проверку динамически. Это очень подробно объясняет, почему, но у меня есть ViewModel, которая получает и объект при создании. В этом объекте я должен проверить наличие некоторого свойства, и в зависимости от его значения у меня должны быть или не быть некоторые проверки.

Пример:

 public class ProfileViewModel
{
    [Required(ErrorMessage = "The field {0} is required")]
    [Display(Name = "Client Code")]
    public int ClientCode { get; set; }

    [Required(ErrorMessage = "The field {0} is required")]
    [StringLength(100, ErrorMessage = "The field {0} must have up to 100 characters.")]
    [Display(Name = "Company")]
    public string Company { get; set; }

    [StringLength(50, ErrorMessage = "The field {0} must have up to 50 characters.")]
    [Display(Name = "Name")]
    public string Name { get; set; }

    [StringLength(50, ErrorMessage = "The field {0} must have up to 50 characters.")]
    [Display(Name = "LastName")]
    public string LastName { get; set; }

    public ProfileViewModel(User usr)
    {
        if (usuario.ClientCode != null)
        {
            ClientCode = Convert.ToInt32(usr.ClientCode);
        }
        else
        {
             //ClientCode and Company are not yet required.
             //Name and LastName are now required.
        }
        Company = usr.Company;
        Name = usr.Name;
        LastName = usr.LastName;
    }
}
  

Ответ №1:

Я думаю, что самый простой способ сделать то, что я хотел, — это реализовать IValidatableObject :

 public class Product : IValidatableObject
{
    public int Prop1 { get; set; }
    public int Prop2 { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Prop1 < Prop2)
            yield return new ValidationResult("Property 1 can't be less than Property 2");
    }
}
  

Смотрите также: Проверка модели на уровне класса с помощью … ASP.NET MVC 3

Комментарии:

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

2. Вы правы. Это не добавляет проверку на стороне клиента. Если вам это нужно, я считаю, что лучшим способом было бы написать свой собственный скрипт для добавления этой проверки.

Ответ №2:

Пользовательский атрибут:

 [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class CustomRequiredIfAttribute : CustomAttribute
{
    private RequiredAttribute innerAttribute = new RequiredAttribute();
    public string DependentProperty { get; set; }
    public object TargetValue { get; set; }

    public CustomRequiredIfAttribute()
    {
    }

    public CustomRequiredIfAttribute(string dependentProperty, object targetValue)
        : base()
    {
        this.DependentProperty = dependentProperty;
        this.TargetValue = targetValue;
    }

    public override bool IsValid(object value)
    {
        return innerAttribute.IsValid(value);
    }
}
  

Пользовательский RequiredIfValidator

 using System;
using System.Collections.Generic;
using System.Web.Mvc;

namespace Custom.Web.Validation
{
    public class RequiredIfValidator : DataAnnotationsModelValidator<CustomRequiredIfAttribute>
    {
        public RequiredIfValidator(ModelMetadata metadata, ControllerContext context, CustomRequiredIfAttribute attribute)
            : base(metadata, context, attribute)
        {
        }

        public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
        {
            return base.GetClientValidationRules();
        }

        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            // get a reference to the property this validation depends upon
            var field = Metadata.ContainerType.GetProperty(Attribute.DependentProperty);

            if (field != null)
            {
                // get the value of the dependent property
                object value = field.GetValue(container, null);

                // compare the value against the target value
                if (this.IsEqual(value) || (value == null amp;amp; Attribute.TargetValue == null))
                {
                    // match => means we should try validating this field
                    if (!Attribute.IsValid(Metadata.Model))
                    {
                        // validation failed - return an error
                        yield return new ModelValidationResult { Message = ErrorMessage };
                    }
                }
            }
        }

        private bool IsEqual(object dependentPropertyValue)
        {
            bool isEqual = false;

            if (Attribute.TargetValue != null amp;amp; Attribute.TargetValue.GetType().IsArray)
            {
                foreach (object o in (Array)Attribute.TargetValue)
                {
                    isEqual = o.Equals(dependentPropertyValue);
                    if (isEqual)
                    {
                        break;
                    }
                }
            }
            else
            {
                isEqual = Attribute.TargetValue.Equals(dependentPropertyValue);
            }

            return isEqual;
        }
    }
}
  

Зарегистрируйте пользовательский DataAnnotationsModelValidatorProvider

 DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(CustomRequiredIfAttribute), typeof(RequiredIfValidator));
  

Используйте этот CustomRequiredIf в ViewModel

 [CustomRequiredIf("CategoryId", 3, ErrorMessageResourceName = GlobalResourceLiterals.AccountGroup_Required)]
public string AccountGroup { get; set; }
  

Ответ №3:

Вот обновленная версия MVC 3 этого сообщения в блогеhttp://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx