Как я могу синхронизировать проверку ViewModel с проверкой модели?

#c# #asp.net-mvc #validation #ef-code-first #asp.net-mvc-5

#c# #asp.net-mvc #проверка #ef-code-first #asp.net-mvc-5

Вопрос:

Я использую подход Entity Framework Code First, что означает, что моей модели нужны атрибуты аннотации данных для создания базы данных. И я действительно хочу, чтобы проверка была на моей модели.

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

Например, у меня могла бы быть модель со следующими обязательными свойствами: Title , Text , X … Но тогда у меня могло бы быть представление, в котором было бы опубликовано только значение для Text . Для этого я создаю ViewModel (в котором также есть другие элементы, не привязанные к модели). Но как я буду проверять Text в этом случае? Мне нужно, чтобы она имела ту же проверку, что и свойство модели Text .

Есть ли способ иметь одинаковые проверки для Model и ViewModel без дублирования кода?


Это попытка, которая просто не сработает…

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

 /* This wouldn't work */
public class PropertyValidationAttribute : ValidationAttribute
{
    public Type Type { get; set; }

    public string PropertyName { get; set; }

    public PropertyValidationAttribute(Type type, string propertyName)
    {
        Type = type;
        PropertyName = propertyName;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var attrs = Type.GetProperty(PropertyName).GetCustomAttributes(typeof(ValidationAttribute), true) as IEnumerable<ValidationAttribute>;

        if (attrs != null)
        {
            foreach (var attr in attrs)
            {
                return attr.GetValidationResult(value, validationContext);
            }
        }

        return base.IsValid(value, validationContext);
    }
}
  

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

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

1. Должно быть, я что-то упускаю. Вы говорите: » Но как я буду проверять текст в этом случае? Мне нужно, чтобы она имела ту же проверку, что и текст свойства модели «. Какая проверка есть в модели, которую вам нужно реплицировать в модели представления?

2. Мне это нужно в ViewModel, чтобы иметь возможность использовать проверку на стороне клиента…

3. Можете ли вы просто применить атрибуты как к модели, так и к ViewModel? Или это дублирование, которого вы пытаетесь избежать?

Ответ №1:

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

Есть вещи, которые следует учитывать. Во-первых, некоторые проверки не совпадают между EF и MVC. Например, EF использует MaxLength и minLength, в то время как MVC использует StringLength .

Во-вторых, как вы собираетесь определять, какие атрибуты вы действительно хотите, а какие нет?

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

Я бы просто взял крошечный удар и продублировал отображение в обоих местах…

Ответ №2:

Вы можете использовать отражение при сопоставлении вашей модели с вашей viewmodel, чтобы проверить наличие любых атрибутов проверки, а затем применить те же атрибуты к вашей viewmodel. Предполагая, что имена ваших свойств одинаковы как в вашей модели, так и в viewmodel, вы сможете создать один метод, который делает это.