Перемещение проверки модели в класс обслуживания - ASP.NET MVC - PullRequest
2 голосов
/ 04 января 2012

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

public ActionResult Edit(Post post)
{
    if(!ModelState.IsValid)
       return View();

    _postDataService.SavePost(post);

    return View("Index");
}

Мне не нравится тот факт, что мой _postDataService.SavePost () может сохранить недопустимые данные, и я хочу переместить проверку модели в мой _postDataService.Метод SavePost ().Мой вопрос: какой самый элегантный способ сделать это?И если я перенесу валидацию модели в метод Service, как я могу вернуть ошибки модели обратно в контроллер?И, наконец, куда пойдет проверка модели, например, уникальность адреса электронной почты, поскольку для этого требуется доступ к некоторым данным?Из всех подобных вопросов, на которые я смотрел, ни один из них не дает прямого способа сделать это.

Я также рассмотрел это решение, но эта статья устарела, и у меня есть чувствоэто не актуально.

1 Ответ

3 голосов
/ 04 января 2012

Я предполагаю, что вы делаете проверку, помещая атрибуты в свойства в вашей модели Post / классе сущности.Если это так, вы можете выполнить проверку на уровне службы, выполнив следующее:

var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(post, 
    new ValidationContext(post, null, null), results, true);

По сути, это то, что делает связыватель моделей по умолчанию, когда он проверяет и настраивает объект ModelState для контроллера / действия.

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

Обновление после комментария

Да, мой ответ рекомендует выполнить проверку дважды.

Как я к этому отношусь?Я не противМы используем Entity Framework 4.1 с MVC и не используем объекты в MVC.Вместо этого мы используем automapper для DTO-сущностей в отдельный слой viewmodel.Наши сущности EF также украшены ValidationAttributes, которые EF оценивает автоматически во время любой операции DbContext.SaveChanges ().Мы применяем очень похожие атрибуты проверки к свойствам наших классов viewmodel.Это может показаться не СУХИМЫМ, и определенно имеет место частичное совпадение, но в некоторых случаях атрибуты проверки на стороне пользовательского интерфейса могут отличаться от атрибутов проверки в модели домена.,Наш уровень обслуживания является просто координатором потока приложений и не несет ответственности за бизнес-правила.Тем не менее, проверка подлинности по-прежнему происходит дважды в нашем приложении.Во-первых, по умолчанию связыватель модели против правил проверки модели представления.Затем, если транзакция доходит до EF, проверка выполняется в отношении сущностей.Таким образом, мы фактически проверяем 2 отдельных слоя.

Если вы подумаете об этом, вы действительно решаете 2 разных вопроса.В пользовательском интерфейсе вы хотите, чтобы MVC отображал сообщения проверки пользователям.ModelState отлично подходит для этого, поскольку он прекрасно подходит для проверки MVC (привязка модели / jquery / ненавязчивая проверка / проверка клиента / и т. Д.).

И наоборот, в домене вы защищаете целостность своих данных и применяете бизнес-правила.Домен не заботится о отображении сообщений для пользователя.Насколько он знает, клиент может быть машиной, службой WCF или чем-то еще.Роль домена состоит в том, чтобы предотвратить возникновение транзакции, и (в нашем случае) выдает исключение, а не пытается «работать с» клиентом.

...