Я довольно новичок в MVC, и по мере того, как я все больше и больше углубляюсь во всю инфраструктуру, я обнаруживаю, что моделирование становится все труднее поддерживать.
Позвольте мне объяснить ...
Я пишу базовое приложение CRUD-over-database.Мои доменные модели будут очень богатыми.В попытке сохранить свои контроллеры настолько тонкими, насколько это возможно, я настроил их так, чтобы в командах «Создать / Редактировать» параметр для действия представлял собой богато заполненный экземпляр модели моего домена.Чтобы сделать это, я реализовал пользовательский механизм связывания модели.
В результате, однако, этот пользовательский механизм связывания очень специфичен для вида и модели.Я решил просто переопределить DefaultModelBinder, который поставляется с MVC 2. В случае, когда поле, привязанное к моей модели, является просто текстовым полем (или чем-то более простым), я просто делегирую базовому методу.Однако, когда я работаю с раскрывающимся списком или чем-то более сложным (пользовательский интерфейс требует, чтобы дата и время были отдельными полями ввода данных, но для модели это одно свойство), я должен выполнить некоторые проверки и некоторое ручное копирование данных.
Конечный результат - у меня довольно тесные связи между View и Binder.Я архитектурно в порядке с этим, но с точки зрения обслуживания кода, это кошмар.
Например, моя модель, которую я здесь связываю, имеет тип Log (это объект, который я получу в качестве параметра в моем Action).«ServiceStateTime» является свойством в журнале.Значения формы "log.ServiceStartDate" и "log.ServiceStartTime" являются абсолютно произвольными и берутся из двух текстовых полей в форме (Html.TextBox ("log.ServiceStartTime", ...))
protected override object GetPropertyValue(ControllerContext controllerContext,
ModelBindingContext bindingContext,
PropertyDescriptor propertyDescriptor,
IModelBinder propertyBinder)
{
if (propertyDescriptor.Name == "ServiceStartTime")
{
string date = bindingContext.ValueProvider.GetValue("log.ServiceStartDate").ConvertTo(typeof (string)) as string;
string time =
bindingContext.ValueProvider.GetValue("log.ServiceStartTime").ConvertTo(typeof (string)) as string;
DateTime dateTime = DateTime.Parse(date + " " + time);
return dateTime;
}
if (propertyDescriptor.Name == "ServiceEndTime")
{
string date = bindingContext.ValueProvider.GetValue("log.ServiceEndDate").ConvertTo(typeof(string)) as string;
string time =
bindingContext.ValueProvider.GetValue("log.ServiceEndTime").ConvertTo(typeof(string)) as string;
DateTime dateTime = DateTime.Parse(date + " " + time);
return dateTime;
}
Log.ServiceEndTime - похожее поле.
Мне это не кажется СУХИМЫМ.Во-первых, если я проведу рефакторинг ServiceStartTime или ServiceEndTime в разные имена полей, текстовые строки могут быть пропущены (хотя мой инструмент рефакторинга R # довольно хорош в подобных вещах, он не вызовет сбой во время сборкии будет пойман только при ручном тестировании).Во-вторых, если бы я решил произвольно изменить дескрипторы «log.ServiceStartDate» и «log.ServiceStartTime», я столкнулся бы с той же проблемой.Для меня ошибки молчания во время выполнения - наихудший вид ошибок там.
Итак, я вижу здесь несколько вариантов помощи, и хотел бы получить некоторую информацию от людей, которые сталкивались с некоторыми из этих проблем:
- Измените любые текстовые строки, общие для связывателей вида и модели, на константные строки, присоединенные к объекту ViewModel, который я передаю из контроллера в представление aspx / ascx.Однако это загрязняет объект ViewModel.
- Обеспечивает модульные тесты для всех взаимодействий.Я большой сторонник юнит-тестов и не начал реализовывать эту опцию, но у меня есть ощущение, что это не спасет меня от стрельбы по ногам.
Если это имеет значение, журнал и другие объекты в системе сохраняются в базе данных с помощью Fluent NHibernate.Я действительно хочу сохранить свои контроллеры настолько тонкими, насколько это возможно.
Итак, любые предложения здесь приветствуются!
Спасибо