Проверка вложенных ViewModels - PullRequest
8 голосов
/ 30 ноября 2011

У меня есть две модели представления (упрощенно):

public class ParentViewModel
{
    public ParentViewModel
    {
        Content = new ChildViewModel();
    }

    public ChildViewModel Content { get; set, }
}

public class ChildViewModel
{
    [Required]
    public string Name1 { get; set, }
    [Required]
    public string Name2 { get; set, }
}

И следующее действие контроллера для публикации:

[HttpPost]
public ActionResult Create(ParentViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        // process viewModel -> write something into database
        return RedirectToAction("Index");
    }
    return View(viewModel);
}

Теперь я отправляю следующие значения формы в теле запроса на отправкуURL, соответствующий этому действию (вручную в Fiddler Request Builder):

  • Content.Name1 = X

    Это прекрасно работает, Name1 свойство заполнено viewModel.Content, Name2 равно null, а состояние модели недопустимо, так как требуется Name2.Таким образом, проверка завершается неудачно, как и ожидалось.

  • Xontent.Name1 = X или Name1 = X или что угодно, чтобы ничто не связывалось с viewModel

    Теперь viewModel.Content - это не null (потому что я создаю его экземпляр в конструкторе), но все свойства Name1 и Name2 равны null.Это ожидается.Я не ожидал, что состояние модели будет допустимо , поэтому оно проходит проверку (что приводит к исключениям из БД позже, поскольку имеются столбцы, не допускающие значения NULL).

Как улучшить этот код, чтобы проверка работала и во втором случае?

Я провел три эксперимента:

  • Я удалилсоздание экземпляра Content в конструкторе ParentViewModel, тогда Content равно null во втором примере выше, но проверка все еще проходит.

  • Я добавил [Required]Атрибут к свойству Content (но не удалить экземпляр Content в конструкторе ParentViewModel).Это никак не влияет, описанное поведение двух тестов выше.

  • Я добавил атрибут [Required] к свойству Content и удалено создание экземпляра Content в конструкторе ParentViewModel.Кажется, это работает так, как я хочу: во втором тесте Content равен null, и проверка не проходит из-за атрибута [Required].Это выглядело бы так:

    public class ParentViewModel
    {
        [Required]
        public ChildViewModel Content { get; set, }
    }
    
    public class ChildViewModel
    {
        [Required]
        public string Name1 { get; set, }
        [Required]
        public string Name2 { get; set, }
    }
    

Теперь я пришел бы к выводу, что создание экземпляра дочернего свойства Content в конструкторе ParentViewModel является источником проблемы и связывателем моделиСам должен создавать экземпляры дочерних свойств (или нет, если в запросе нет соответствующих полей формы), чтобы иметь правильно работающую проверку на стороне сервера.

У меня есть создание экземпляров дочерних свойств в нескольких других конструкторах модели представления ине замечал этой проблемы до сих пор.Так это вообще плохая практика?Есть ли другие способы решения проблемы?

Ответы [ 2 ]

0 голосов
/ 18 января 2013

Третий вариант в порядке:

public class ParentViewModel
{
    [Required]
    public ChildViewModel Content { get; set, }
}

public class ChildViewModel
{
    [Required]
    public string Name1 { get; set, }
    [Required]
    public string Name2 { get; set, }
}

Я использую его сейчас в нескольких местах и ​​не заметил никаких проблем.

0 голосов
/ 30 ноября 2011

ModelState.IsValid сообщает, были ли добавлены какие-либо ошибки модели в ModelState.

Связыватель модели по умолчанию добавит некоторые ошибки для базовых проблем преобразования типов, таких как передача не-числа для чего-то, что является "INT».Вы можете заполнить ModelState более полно в зависимости от используемой вами системы валидации.Я бы посоветовал изучить аннотации данных для проверки ViewModels, поскольку он хорошо работает.

Этот синтаксис может быть неправильным или старым.ModelState.AddModelError ("ключ", исключение)

перефразировано из Что такое ModelState.IsValid, допустимое для ASP.NET MVC в NerdDinner?

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