Можно ли поразить базу данных из пользовательского механизма связывания? - PullRequest
3 голосов
/ 17 апреля 2010

Скажем, у меня есть объект, который получает некоторые данные из HttpPost, а некоторые из базы данных. Я думаю, что я хочу позволить ModelBinder перейти в базу данных / хранилище для этих данных, отсутствующих в посте. На практике это хорошая или плохая идея?

Ответы [ 6 ]

6 голосов
/ 24 мая 2010

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

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

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

4 голосов
/ 17 апреля 2010

Я бы сказал, плохая идея. Идея связующего элемента модели заключается в том, что он берет параметры из запроса и создает из них вашу модель. Если ваша модель переплета за кадром заполняет некоторые детали из базы данных, это нарушает парадигму. Я бы предпочел показать вызов базы данных в моем контроллере, явно выбрав необходимые дополнительные данные из базы данных напрямую. Обратите внимание, что это может быть преобразовано в метод, если используется часто.

2 голосов
/ 18 апреля 2010

Это нарушает способ работы MVC. ModelBinder предназначен для связывания моделей с данными, полученными из представления. Заполнение недостающей информации из базы данных - это то, что должен обрабатывать контроллер. В идеале он должен иметь тот же класс слоя данных / репозитория, который он использует для этого.

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

Сделайте еще один шаг, скажем, вы хотите войти в БД, какую информацию не публикует пользователь, или поймать исключение при получении недостающих данных и уведомлении об этом администраторов электронной почты. Вы должны поместить их в свою модель связующего таким образом, и это становится все более и более уродливым с ModelBinder становится все более и более искаженным от его первоначального назначения.

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

2 голосов
/ 17 апреля 2010

Я думаю, что это прекрасно, и постоянно использую эту технику.

Единственные аргументы против очень педантичны и равносильны спорам по поводу философии. ИМХО, вы можете поместить код «заполнить пропущенные опубликованные данные» в свое MVC-приложение как метод в вашем базовом контроллере по сравнению с методом в вашем ActionFilter против метода в ModelBinder. Все зависит от того, кто за что отвечает. Для меня механизм связывания может сделать гораздо больше, чем просто связать некоторые свойства из опубликованных значений.

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

    //logic not in modelbinder
    public ActionResult Edit( KittyCat cat )
    {
        DoSomeOrthagonalDatabaseCall( cat );

        return View( new MODEL() );
    }

против

    //logic in model binder
    public ActionResult Add( KittyCat cat )
    {
        return View( new MODEL() );
    }
1 голос
/ 25 октября 2013

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

1- Доступ к базе данных должен быть ограничен через интерфейсы репозитория. Интерфейсы репозитория являются частью модели предметной области, а их реализация является частью уровня инфраструктуры / доступа к данным. Таким образом, нет никакой зависимости от базы данных.

2 - Связующие и контроллеры моделей являются частью уровня представления, реализованного с использованием ASP.NET MVC Framework. Если Контроллерам разрешен доступ к базе данных с использованием интерфейсов репозитория, почему модели Binder не разрешены?

Кроме того, существуют ситуации, когда вам «лучше» заполнить недостающие данные в вашей модели из связывателей моделей. Рассмотрим сценарий, в котором у вас есть раскрывающийся список. При первой загрузке представления заполняется раскрывающийся список. Пользователь отправляет форму, но проверка не проходит. Так что вам нужно будет вернуть форму снова. На этом этапе вам нужно будет заново заполнить список в модели для раскрывающегося списка. Делать это в контроллере выглядит некрасиво:

public ActionResult Save(DocumentViewModel viewModel)
{
     if (!ModelState.IsValid)
     {
         viewModel.Categories = _repository.GetAll();
         return View(viewModel);
     }
}

Я считаю, что инициализация категорий здесь ужасна и похожа на запах кода. Что если у вас есть несколько свойств, которые необходимо заполнить из базы данных? Что если у вас было более одного действия, в котором в качестве аргумента использовалась DocumentViewModel? Вам придется повторять этот уродливый шаг снова и снова. Лучший подход - заполнить все свойства модели, используя связыватель модели, и передать ее в контроллер. Таким образом, объект, который передается контроллеру, находится в «согласованном» состоянии.

1 голос
/ 17 апреля 2010

Я бы сказал, нет.

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

...