TryValidate контроллера ASP.Net MVC 2 не проверяет элементы List <> в модели - PullRequest
3 голосов
/ 17 декабря 2010

Как вы получаете проверку модели, чтобы также проверять дочерние объекты в свойстве общего списка.

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

 ...
public class A {
   [Required]
   public string Property1 { get; set; }
}
...
public class B {
   public List<A> Values { get; set; }
}
...
    if (!TryValidateModel(instanceofB))
    {
        //this should fire, as one of A inside B isn't valid.
        return View(instanceofB);
    }

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

Ответы [ 2 ]

5 голосов
/ 20 декабря 2010

Метод TryValidateModel опускается только на один уровень, поэтому он проверяет только атрибуты Validation для объекта типа B, а не для его вложенных объектов.Один из способов преодолеть это - определить собственную реализацию ValidationAttribute:

public class ListValidationAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        IEnumerable enumerable = value as IEnumerable;
        // If the input object is not enumerable it's considered valid.
        if (enumerable == null)
        {
            return true;
        }
        foreach (object item in enumerable)
        {
            // Get all properties on the current item with at least one
            // ValidationAttribute defined.
            IEnumerable<PropertyInfo> properties = item.GetType().
                GetProperties().Where(p => p.GetCustomAttributes(
                typeof(ValidationAttribute), true).Count() > 0);
            foreach (PropertyInfo property in properties)
            {
                // Validate each property.
                IEnumerable<ValidationAttribute> validationAttributes =
                    property.GetCustomAttributes(typeof(ValidationAttribute),
                    true).Cast<ValidationAttribute>();
                foreach (ValidationAttribute validationAttribute in
                    validationAttributes)
                {
                    object propertyValue = property.GetValue(item, null);
                    if (!validationAttribute.IsValid(propertyValue))
                    {
                        // Return false if one value is found to be invalid.
                        return false;
                    }
                }
            }
        }
        // If everything is valid, return true.
        return true;
    }
}

Теперь List<A> можно проверить с помощью атрибута:

public class B
{
    [ListValidation]
    public List<A> Values { get; set; }
}

У меня нетТщательно протестировал производительность для вышеуказанного подхода, но если в вашем случае это оказывается проблемой, альтернативный подход заключается в использовании вспомогательной функции:

    if (!ValidateB(instanceofB))
    {
        //this should fire, as one of A inside B isn't valid.
        return View(instanceofB);
    }

...

public bool ValidateB(B b)
{
    foreach (A item in b.Values)
    {
        if (!TryValidateModel(item))
        {
            return false;
        }
    }
    return true; 
}
1 голос
/ 22 ноября 2012

У меня была похожая проблема, которую я исправил, вообще избегая вызова TryValidate.Причина, по которой я позвонил в TryValidate, заключалась в том, что мне нужно было внести некоторые изменения в мою модель, а затем выполнить проверку.В итоге я создал интерфейс для модели и заменил механизм связывания модели по умолчанию на тот, который распознает интерфейс и вызывает мой метод.Все это происходит до того, как вызовы платформы проверяют первый раз (что является рекурсивным).

...