Для контроллеров и моделей представления, которые должны содержать большую часть бизнес-логики?
Ни один из них.
Я пробовал несколько способовзаставить мои ViewModels практически содержать всю бизнес-логику.Однако в конструкторе моего ViewModel должен быть аргумент, который принимает единицу работы.Это хорошая идея?
imho Это очень плохая идея.Прежде всего, вы нарушаете несколько принципов SOLID.Объединение всего кода в модель представления затрудняет тестирование.Что если вы хотите использовать некоторую бизнес-логику в другом представлении?Вы дублируете этот код?
Какова лучшая практика здесь?
Давайте сначала вернемся к шаблону MVC.Это довольно широкое определение, но зная, что оно должно дать вам представление о том, куда вы должны поместить.
«Модель» в MVC - это действительно все, что используется для объединения данных.Это могут быть веб-сервисы, бизнес-уровень, репозитории и т. Д.
Представление - это весь код, который генерирует HTML (поскольку речь идет о сети).
Контроллер следует считать связующим звеном между моделью и видом.Следовательно, он должен взять информацию из модели и преобразовать ее в нечто, пригодное для использования представлением.
Проблема с этой структурой заключается в том, что довольно просто «просачивать» информацию, относящуюся к слою, вдругие части рисунка.Поэтому Microsoft ввела ViewModel в свою реализацию MVC.
Таким образом, мы можем удалить всю логику рендеринга из представлений и поместить ее в ViewModel.Вместо того чтобы делать это по вашему мнению:
<span>@(model.Age == 0 ? "n/a" : model.Age)</span>
вы помещаете этот код в ViewModel и просто вызываете @model.Age
.Таким образом, вам не нужно дублировать этот код во всех представлениях, которые используют вашу модель представления.
Ответ на ваш вопрос о ViewModel заключается в том, что он должен содержать только логику, которая используется для правильной визуализации информации из «Модели».
Что касается контроллера, я бы не стал ставитьлюбая бизнес-логика в это тоже.Прежде всего, это очень затрудняет проверку вашей логики.Затем вы добавляете больше обязанностей (и тем самым нарушаете SRP).Единственная логика, которая действительна в контроллере, - это взять информацию из ViewModel и преобразовать ее во что-то, что можно использовать с помощью «Модели», и наоборот.
Надеюсь, что ответ на ваш вопрос.
Обновление
Я бы создал отдельный проект и добавил к нему классы.Затем просто добавьте ссылку из вашего веб-проекта и вызовите эти классы в контроллерах.
Я бы также начал использовать инверсию контейнера управления для автоматического создания этих зависимостей, созданных для меня.
Autofac может обнаружить ваши услуги для вас (нулевая конфигурация)и внедрить себя в MVC.
Чтобы следовать шаблону разделенного интерфейса, создайте следующие проекты:
- YourProject.BusinessLayer <- добавьте свои классы сюда </li>
- YourProject.BusinessLayer.Specification <- Добавьте сюда интерфейсы, которые определяют ваш бизнес-уровень. </li>
- YourProject.Mvc <- Проект MVC. </li>
Проект "Спецификация" можно использовать дляупростить тестирование и переключить реализацию (может быть только несколько классов и не обязательно весь бизнес-уровень).Читайте о "Шаблоне разделенного интерфейса"