ASP.NET MVC - пользовательский ввод и сервис / репозиторий - где проводить валидацию? - PullRequest
4 голосов
/ 17 ноября 2008

Это может быть слишком самоуверенным вопросом, но вам нужна помощь!

Я пытался уточнить структуру моей программы ASP.NET MVC. Я только начал использовать его в предпросмотре 5, и это мой первый опыт разработки бизнес-приложений - так что все новое!

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

Итак, теперь я хочу добавить подтверждение пользователя. Проблема в том, что я не уверен, куда это поставить. Для меня имеет смысл сделать это на уровне сервиса. Сервисный уровень отвечает за всю бизнес-логику, а валидация - это бизнес-логика. С другой стороны, большинство платформ проверки, которые я вижу, предназначены для проверки объекта, что заставляет меня думать, что объект представления должен быть осведомлен о проверке. Наконец, существуют некоторые методы проверки, которые требуют подключения к базе данных (например, проверка, имеет ли поле ввода пользователя соответствующую запись базы данных), а объект представления не имеет понятия базы данных, только служба.

Итак, я вижу следующие варианты:

  • Выполните проверку в Service.Method для параметров, переданных методу.
  • Выполните проверку в объекте представления перед вызовом Service.Method.
  • Выполните проверку в объекте представления, но для Service.Method требуется ссылка на объект представления, поэтому он инициирует проверку объекта.

Я уверен, что есть и другие. Мне любопытно, как другие люди обрабатывают проверку пользовательского ввода в смысле MVC. Ранее я использовал блок Enterprise Validation Block, и мне нравилось иметь возможность использовать стандартные валидаторы для всего, но я не уверен, как сделать так, чтобы он вписывался в отдельный вид объекта и уровень обслуживания. Было бы легко, если бы они (просмотр объекта / службы) были одним и тем же объектом, что, возможно, делают люди? Как я уже сказал, это все новое для меня, и я ищу лучшие практики / шаблоны.

Ответы [ 6 ]

6 голосов
/ 17 ноября 2008

Обычно я выполняю базовую проверку (обязательные поля, формат электронной почты и т. Д.) В действии контроллера при отправке формы. Затем я позволяю бизнес-уровню обрабатывать проверки, которые требуют знания бизнеса. Я обычно дважды проверяю базовые вещи на бизнес-уровне, поэтому, если я раскрою эту логику через веб-сервисы или позже использую ее в другом приложении, у меня останется проверка того, где она наиболее важна (IMO).

4 голосов
/ 17 ноября 2008

На это есть несколько интересных ссылок

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

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

Наконец, текущие dll MVC имеют возможность передавать сообщения об ошибках обратно в пользовательский интерфейс ... так что представление может отображать их красиво. Проверить: -

  • ViewData.ModelState.AddModelError (ключ, сообщение)

НТН!

2 голосов
/ 17 ноября 2008
1 голос
/ 17 ноября 2008

Я боялся, что не получу ответов на свой пост, рад ошибаться!

Я читал эти ссылки раньше, но, вероятно, месяц или более назад, и перечитывание их с тем, что я понимаю сейчас, было очень полезным. Мне действительно нравится сообщение Стива Сандерсона со скользящей шкалой, но хотелось бы, чтобы он показал пример проверки чего-либо в правом конце спектра.

В качестве примера в своем блоге он приводит: «« имена пользователей должны быть уникальными », вероятно, будут применяться в вашей базе данных». Так что это будет что-то вроде:

public static void SavePerson(Person person)
{
    // make sure it meets some format requirement
    // in this case the object is responsible for validation and the service layer is the caller
    person.EnsureValid();

    // todo: action to verify username is unique by checking database
    // in this case the service layer is responsible for calling and implementing validation

    // todo: action to save to database
}

Это имеет смысл и показало бы мою проблему с пониманием того, куда поместить проверку, так как она находится как внутри сервисного уровня (очень уникальное имя), так и в виде объекта просмотра (проверка форматов).

Еще одна проблема, с которой я сталкиваюсь, - это то, что сервисный уровень начинает развиваться с логикой валидации. Может быть, разделить его на другой класс или что-то? В моем случае некоторая логика проверки может быть разделена между службами, поэтому я хотел бы подумать о СУХОМ способе реализации этого. Забавные вещи, чтобы подумать!

Ссылка Эмада Ибрагима хороша тем, что, как только я начну понимать этот процесс немного больше, я собираюсь искать способ генерировать валидацию на стороне клиента с использованием того же набора правил, без необходимости повторять код. У него уже есть это:)

Я слышал о S # arp, но не сел и не увидел, как он работает (я не уверен, что на нем много демоверсий или загрузка кода - это демо!). Я не уверен, что проверки на модели базы данных будет достаточно. Мне кажется, что в отношении базы данных было бы много действительных состояний модели, которые бизнес-логика считала бы недействительными (например, диапазоны дат / должны быть до / после / и т. Д.). Это случаи, которые поражают мой мозг:)

Кроме того, мне понравилась ссылка (прогуглила ее после того, как я увидела, как Эмад ответил на сообщение Стивса с BLL, и понятия не имела, что это значит ... дух):

http://en.wikipedia.org/wiki/Business_logic_layer

Так что я не знал этого, но я думаю, что пишу для этой модели: объект бизнес-процесса, который обрабатывает взаимодействия данных, и бизнес-объекты, которые являются логическими моделями, а не моделями баз данных. Я думаю, что мне нужно начать читать некоторые более фундаментальные шаблоны и практики с этим материалом, чтобы лучше понять концепции (кажется, что многое из этого - то, что пишут люди на Java против людей .NET). Возможно, пришло время сделать шаг назад:)

1 голос
/ 17 ноября 2008

Взгляните на проект S # arp Architecture. В модели выполняется проверка, чтобы гарантировать, что ни один объект не будет сохранен в базе данных в недопустимом состоянии. Это делается с помощью NHibernate.Validator и присоединения его к событиям сохранения и обновления NHibernate.

Лично для меня этот подход наиболее важен, поскольку вам не нужно дублировать логику проверки на нескольких контроллерах.

0 голосов
/ 14 октября 2009

Я сталкивался с такой же проблемой в недавнем проекте. Во-первых, чтобы сформулировать проблему, я пытаюсь следовать доменно-ориентированному подходу DDD. У меня есть объекты, объединенные в агрегаты, которые могут проверять самих себя, а хранилища проверяют достоверность при сохранении. Пользовательский интерфейс также может получать информацию о достоверности из агрегата, чтобы отображать обратную связь об ошибках для клиента. Общий подход заключается в максимально возможном использовании привязки модели ASP.NET MVC и помощников валидации / формы пользовательского интерфейса. Это создает простой поток пользовательского интерфейса: 1) bind, 2) validate, 3) если верный, save, иначе повторно заполнить представление.

Однако не совсем очевидно, как эффективно использовать ASP.NET MVC и этот простой процесс, когда задействованы службы DDD. Первоначально я разработал свои услуги как таковые:

public class SomeProcessService 
{
  public Result Execute(int anAggregateID, int anotherAggregateID, string someData) 
  {
    // validate input

    // if invalid, return failures

    // else 
    //   modify aggregates
    //   using (transaction)
    //   {
    //     save aggregates
    //     commit
    //   }

    // return success
  }
}

Проблема в том, что проверка и сохранение неразрывно связаны в методе. Чтобы использовать привязку модели MVC, нам нужно нечто, что служит моделью для привязки. Я рефакторинг на это:

public class SomeProcessService 
{
  public class Request : IValidateable
  {
    public int AggregateID {get;set;}
    public int AnotherAggregateID {get;set;}
    public string SomeData {get;set;}

    public Result Validate() 
    {
      // validation
    }
  }

  public void Execute(Request request) 
  {
    // validate input by calling request.Validate()

    // if invalid, throw new ValidationException(request)

    // else 
    //   modify aggregates
    //   using (transaction)
    //   {
    //     save aggregates
    //     commit
    //   }

    // return success
  }
}

Повторно использует шаблон объекта Parameter для разделения проверки входных данных метода. Я могу привязать к объекту SomeProcessService.Request в моем контроллере, а также получить информацию проверки там. Если все хорошо, с моего контроллера я инициирую сервисный вызов, используя объект Request в качестве параметра. Этот подход, похоже, удачно сочетает службы DDD с требованиями валидации ASP.NET MVC.

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