Как заставить ValidationAttribute пометить указанные элементы объекта как недействительные? - PullRequest
1 голос
/ 22 июля 2011

У меня есть моя модель, которая содержит несколько членов:

public class Address
{
   public Street { get; set;}
   public City { get; set; }
   public PostalCode { get; set; }
}

Теперь у меня есть ValidationAttribute с IsValid методом, переопределенным так:

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    var input = value as Address;

    if (string.IsNullOrEmpty(input.City))
        return new ValidationResult("City is required);

    if (!string.IsNullOrEmpty(input.PostalCode))
        if (string.IsNullOrEmpty(input.Street))
            return new ValidationResult("Stret is required");

    return ValidationResult.Success;
}

Проблема:

После проверки мое состояние модели добавляет ошибку модели только ко всему члену Adress, но мне нужно, чтобы ее добавили к указанным членам, таким как город или улица.

Любая помощь с этим будет оценена ... спасибо!

Ответы [ 2 ]

3 голосов
/ 22 июля 2011

Вы можете добавить memberNames!

return new ValidationResult("City is required", new string[] { "City", "Street" });

РЕДАКТИРОВАТЬ: Я проверил и нашел решение: System.ComponentModel.IDataErrorInfo !! это не работает на клиенте javascript, но при отправке результата мы пытались это сделать :) так что продолжайте использовать ValidationResult с memberNames и:

public class myModel : System.ComponentModel.IDataErrorInfo
    {

        private Dictionary<string, List<ValidationResult>> errors;
        private bool IsValidated = false;

        private void Validate()
        {
            errors = new Dictionary<string, List<ValidationResult>>();
            List<ValidationResult> lst = new List<ValidationResult>();
            Validator.TryValidateObject(this, new ValidationContext(this, null, null), lst, true);
            lst.ForEach(vr =>
                {
                    foreach (var memberName in vr.MemberNames)
                        AddError(memberName, vr);
                });
            IsValidated = true;
        }
        private void AddError(string memberName, ValidationResult error)
        {
            if (!errors.ContainsKey(memberName))
                errors[memberName] = new List<ValidationResult>();
            errors[memberName].Add(error);
        }

        public string Error
        {
            get
            {
                if (!IsValidated)
                    Validate();

                return string.Join("\n", errors
                    .Where(kvp => kvp.Value.Any())
                    .Select(kvp => kvp.Key + " : " + string.Join(", ", kvp.Value.Select(err => err.ErrorMessage)))
                    );
            }
        }

        public string this[string columnName]
        {
            get
            {
                if (!IsValidated)
                    Validate();

                if (errors.ContainsKey(columnName))
                {
                    var value = errors[columnName];
                    return string.Join(", ", value.Select(err => err.ErrorMessage));
                }
                else
                    return null;
            }
        }

и теперь текущее свойство помечено по ошибке, а также memberNames!

: D

Редактировать 2

На самом деле вы можете хранить простые аннотации данных для информирования клиента, и на стороне сервера, вы можете добавить более сложную проверку бизнеса:

public class myModel : IValidatableObject
{
      public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
      {

            if (string.IsNullOrEmpty(input.City))
                  yield return new ValidationResult("City is required",new string[]{"prop1","prop2"});
            if (!string.IsNullOrEmpty(input.PostalCode))
                  if (string.IsNullOrEmpty(input.Street))
                        yield return new ValidationResult("Stret is required");
      }

обратите внимание, что метод Validate вызывается только , когда все аннотации Data действительны!

1 голос
/ 22 июля 2011

Вам необходимо использовать этот конструктор класса ValidationResult. Например,

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    var input = value as Address;

    if (string.IsNullOrEmpty(input.City))
        return new ValidationResult("City is required", new List<string>(){"City"});

    if (!string.IsNullOrEmpty(input.PostalCode))
        if (string.IsNullOrEmpty(input.Street))
            return new ValidationResult("Stret is required", new List<string>(){"Street"});

    return ValidationResult.Success;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...