У меня есть многоэтапный процесс регистрации , поддерживаемый одним объектом на уровне домена , в свойствах которого определены правила проверки.
Как мне проверить объект домена, когда домен разделен на несколько представлений, и мне нужно частично сохранить объект в первом представлении при публикации?
Я думал об использовании сеансов, но это невозможно, потому что процесс длительный, а объем данных велик, поэтому я не хочу использовать сеанс.
Я подумал о том, чтобы сохранить все данные в реляционной базе данных в памяти (с той же схемой, что и основная база данных), а затем сбросить эти данные в основную базу данных, но возникли проблемы, потому что я должен маршрутизировать между службами (запрошенными в представлениях), которые работают с основная база данных и база данных в памяти.
Я ищу элегантное и чистое решение (точнее, лучшую практику).
ОБНОВЛЕНИЕ И Уточнение:
@Darin Спасибо за ваш вдумчивый ответ, это именно то, что я делал до сих пор. Но, кстати, у меня есть запрос, в котором много вложений, я разрабатываю, Step2View
например, какой пользователь может загружать в него документы асинхронно, но эти вложения должны быть сохранены в таблице со ссылочной ссылкой на другую таблицу, которая должна была быть сохранена ранее в Step1View
,
Таким образом, я должен сохранить объект домена в Step1
(частично), но я не могу, потому что поддерживаемый объект Core Domain, который частично сопоставлен с ViewModel Step1, не может быть сохранен без реквизитов, которые поступают из преобразованных Step2ViewModel
.
источник
Ответы:
Во-первых, вы не должны использовать в своих представлениях какие-либо объекты домена. Вы должны использовать модели просмотра. Каждая модель представления будет содержать только те свойства, которые требуются для данного представления, а также атрибуты проверки, специфичные для данного представления. Таким образом, если у вас есть мастер из 3 шагов, это означает, что у вас будет 3 модели просмотра, по одной для каждого шага:
и так далее. Все эти модели представления могут поддерживаться основной моделью представления мастера:
тогда у вас могут быть действия контроллера, отображающие каждый шаг процесса мастера и передающие основную часть
WizardViewModel
в представление. Когда вы находитесь на первом шаге внутри действия контроллера, вы можете инициализироватьStep1
свойство. Затем внутри представления вы должны сгенерировать форму, позволяющую пользователю заполнить свойства шага 1. Когда форма будет отправлена, действие контроллера применит правила проверки только для шага 1:Теперь внутри представления шага 2 вы можете использовать помощник Html.Serialize из фьючерсов MVC, чтобы сериализовать шаг 1 в скрытое поле внутри формы (вроде ViewState, если хотите):
и внутри действия POST шага 2:
И так далее, пока вы не дойдете до последнего шага, на котором вы
WizardViewModel
заполните все данные. Затем вы сопоставите модель представления с моделью предметной области и передадите ее на уровень сервиса для обработки. Уровень сервиса может сам выполнять любые правила проверки и так далее ...Есть и другая альтернатива: использовать javascript и разместить все на одной странице. Есть много плагинов jquery , которые предоставляют функции мастера ( Stepy - хороший вариант ). В основном это вопрос отображения и скрытия div на клиенте, и в этом случае вам больше не нужно беспокоиться о сохранении состояния между этапами.
Но независимо от того, какое решение вы выберете, всегда используйте модели представления и выполняйте проверку этих моделей представления. Пока вы прикрепляете атрибуты проверки аннотации данных к своим моделям предметной области, вам будет очень трудно, поскольку модели предметной области не адаптированы к представлениям.
ОБНОВИТЬ:
Хорошо, по многочисленным комментариям делаю вывод, что мой ответ был непонятен. И я должен согласиться. Итак, позвольте мне попытаться продолжить мой пример.
Мы могли бы определить интерфейс, который должны реализовывать все модели пошаговых представлений (это просто интерфейс маркера):
Затем мы определим 3 шага для мастера, каждый из которых, конечно, будет содержать только те свойства, которые ему необходимы, а также соответствующие атрибуты проверки:
Затем мы определяем основную модель представления мастера, которая состоит из списка шагов и индекса текущего шага:
Затем переходим к контроллеру:
Пара замечаний об этом контроллере:
[Deserialize]
атрибуты из библиотеки Microsoft Futures, поэтому убедитесь, что вы установилиMvcContrib
NuGet. По этой причине модели представлений следует украшать[Serializable]
атрибутомIStepViewModel
интерфейс, поэтому для того, чтобы это имело смысл, нам нужен пользовательский связыватель модели.Вот связанная связка модели:
Этот связыватель использует специальное скрытое поле StepType, которое будет содержать конкретный тип каждого шага и которое мы будем отправлять по каждому запросу.
Эта папка модели будет зарегистрирована в
Application_Start
:Последний недостающий фрагмент головоломки - это виды. Вот основной
~/Views/Wizard/Index.cshtml
вид:И это все, что вам нужно, чтобы это работало. Конечно, при желании вы можете персонализировать внешний вид некоторых или всех шагов мастера, определив собственный шаблон редактора. Например, сделаем это для шага 2. Итак, мы определяем
~/Views/Wizard/EditorTemplates/Step2ViewModel.cshtml
партиал:Вот как выглядит конструкция:
Конечно, есть возможности для улучшения. Действие Index POST выглядит как s..t. В нем слишком много кода. Дальнейшее упрощение включало бы перемещение всего инфраструктурного материала, такого как индекс, управление текущим индексом, копирование текущего шага в мастер, ... в другой связыватель модели. Итак, в итоге мы получаем:
что больше похоже на то, как должны выглядеть действия POST. Оставляю это улучшение в следующий раз :-)
источник
В дополнение к ответу Амита Багги вы найдете ниже то, что я сделал. Даже если это менее элегантно, я считаю, что этот способ проще, чем ответ Дарина.
Контроллер:
Модели:
источник
Я бы посоветовал вам поддерживать состояние Complete Process на клиенте с помощью JQuery.
Таким образом, вы можете легко создать объект домена непосредственно из данных публикации формы, и в случае, если в данных есть ошибки, верните действительный JSON, содержащий все сообщения об ошибках, и отобразите их в div.
Пожалуйста, разделите шаги
источник
Мастера - это всего лишь простые шаги в обработке простой модели. Нет причин создавать несколько моделей для мастера. Все, что вам нужно сделать, это создать единую модель и передавать ее между действиями в одном контроллере.
Вышеупомянутая команда глупо проста, поэтому замените там свои поля. Далее мы начинаем с простого действия, которое запускает наш мастер.
Это вызывает представление "WizardStep1.cshtml (если используется бритва). Вы можете использовать мастер создания шаблона, если хотите. Мы просто перенаправим сообщение на другое действие.
Следует отметить, что мы разместим это в другом действии; действие WizardStep2
В этом действии мы проверяем, действительна ли наша модель, и если это так, мы отправляем ее в наше представление WizardStep2.cshtml, иначе мы отправляем ее обратно на первый шаг с ошибками проверки. На каждом шаге мы отправляем его на следующий шаг, подтверждаем этот шаг и идем дальше. Теперь некоторые сообразительные разработчики могут сказать, что мы не можем перемещаться между шагами, такими как этот, если мы используем атрибуты [Required] или другие аннотации данных между шагами. И вы будете правы, поэтому удалите ошибки по пунктам, которые еще предстоит проверить. как показано ниже.
Наконец, мы сохраняем модель один раз в хранилище данных. Это также предотвращает запуск мастера, который запускает мастер, но не завершает его, чтобы не сохранить неполные данные в базе данных.
Я надеюсь, что вы найдете этот метод создания мастера намного проще в использовании и обслуживании, чем любой из ранее упомянутых методов.
Спасибо за прочтение.
источник
Я хотел поделиться своим собственным способом выполнения этих требований. Я вообще не хотел использовать SessionState и не хотел, чтобы он обрабатывался на стороне клиента, а для метода сериализации требуется MVC Futures, который я не хотел включать в свой проект.
Вместо этого я создал помощник HTML, который будет перебирать все свойства модели и генерировать настраиваемый скрытый элемент для каждого из них. Если это сложное свойство, оно будет работать с ним рекурсивно.
В вашей форме они будут отправляться контроллеру вместе с данными новой модели на каждом шаге «мастера».
Я написал это для MVC 5.
Теперь для всех шагов вашего «мастера» вы можете использовать одну и ту же базовую модель и передать свойства модели «Step 1,2,3» в помощник @ Html.HiddenClassFor, используя лямбда-выражение.
Вы даже можете использовать кнопку возврата на каждом этапе, если хотите. Просто добавьте в форму кнопку «Назад», которая отправит ее в действие StepNBack на контроллере с использованием атрибута formaction. Не включено в приведенный ниже пример, это просто идея для вас.
В любом случае, вот базовый пример:
Вот ваша МОДЕЛЬ
Вот ваш КОНТРОЛЛЕР
Вот ваши Мнения
Шаг 1
Шаг 2
Шаг 3
источник
Добавление дополнительной информации из ответа @Darin.
Что, если у вас есть отдельный стиль дизайна для каждого шага и вы хотите сохранить каждый в отдельном частичном представлении, или что, если у вас есть несколько свойств для каждого шага?
При использовании
Html.EditorFor
у нас есть ограничение на использование частичного просмотра.Создайте 3 частичных представления в
Shared
папке с именем:Step1ViewModel.cshtml , Step3ViewModel.cshtml , Step3ViewModel.cshtml
Для краткости я просто публикую 1-е представление, другие шаги такие же, как и ответ Дарина.
Step1ViewModel.cs
Step1ViewModel.cshtml
Index.cshtml
Если есть лучшее решение, прокомментируйте, чтобы другие знали.
источник
Один из вариантов - создать набор идентичных таблиц, в которых будут храниться данные, собранные на каждом этапе. Затем на последнем этапе, если все пойдет хорошо, вы можете создать реальный объект, скопировав временные данные и сохранив их.
Другой - создать
Value Objects
для каждого шага и сохранить его вCache
илиSession
. Затем, если все пойдет хорошо, вы можете создать из них свой объект домена и сохранить его.источник