Как сохранить текст во время обратной передачи с ASP.NET MVC 3

#asp.net-mvc #asp.net-mvc-3

#asp.net-mvc #asp.net-mvc-3

Вопрос:

У меня есть экран редактирования продукта. Пользователь может выбрать поставщика для продукта. Для этого я показываю диалоговое окно jQueryUI, которое позволяет им просматривать и выбирать поставщика. Когда пользователь выбирает поставщика, я обновляю скрытый ввод VendorID на странице, который является частью модели моей страницы. Я также обновляю несколько разделов с подробной информацией о выбранном ими поставщике. Они предназначены только для отображения — для сохранения выбранного поставщика требуется только идентификатор.

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

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

Три варианта, о которых я могу подумать::

  1. При обратной передаче, если есть ошибка, перейдите в базу данных, выберите поставщика, используя предоставленный идентификатор поставщика, и повторно заполните модель текстом, который я хочу отобразить.
  2. Используйте RenderAction и выполните действие, которое отображает сведения о выбранном поставщике.
  3. Используйте текстовые поля только для чтения вместо divs для отображения сведений о поставщике.

Ни один из них не кажется мне очень удовлетворительным. Я чувствую, что, возможно, мне не хватает очевидного решения. Есть ли какие-либо лучшие решения?

Ответ №1:

Я бы посоветовал вам не размещать дополнительную информацию о поставщике как часть главной страницы. Создайте функцию javascript showVendorInfo(). При вызове, если скрытый ввод VendorID имеет значение, он получает соответствующую информацию о поставщике через AJAX и отображает ее, используя метод действия AjaxGetVendorInfo. Вызовите эту функцию из двух мест:

  • В document.ready()
  • после выбора поставщика с помощью отображения jQueryUI.

Теперь это будет в методе действия. Вы могли бы, если ожидаете, что у ваших пользователей возникнут проблемы с задержкой, сделать следующее, чтобы избежать некоторых вызовов ajax: В представлении проверьте, знаете ли вы VendorID ; если да, вызовите Html.RenderAction вызовите тот же метод действия AjaxGetVendorInfo из представления.

Бонус к этому заключается в том, что он позволяет избежать того, что я считаю большим запретом: включать в вашу ViewModel как значения только для отображения, так и значения, привязанные к модели. Это создает очень запутанную ViewModel, особенно при наличии ошибок проверки. [Переход к мыльному ящику] Лучше всего, чтобы в вашей ViewModel были только свойства, предназначенные для привязки к модели, для вашего состояния. Поместите значения списка, дополнительную отображаемую информацию и т. Д. В ViewData или отобразите их через AJAX.

Комментарии:

1. Это звучит как чистое решение, в котором используется ajax для извлечения отображаемых данных. Немного связано с этим решением, если эти данные поступают из БД, вы можете использовать TempData на стороне сервера для кэширования результатов БД. Это также позволяет избежать дополнительного обращения к БД.

2. @Patrick Мне нравится ваш подход. Я попытался использовать RenderAction, как вы предложили при загрузке страницы, чтобы избежать вызова AJAX, но одна из проблем заключается в том, что при обратной передаче при добавлении нового продукта возникает ошибка, VendorID отсутствует в модели. Поэтому я не могу просто вызвать RenderAction, используя VendorID в моей модели, не обращаясь к ModelState, чтобы получить его, что кажется мне взломом. Есть мысли о том, как наилучшим образом справиться с этим случаем?

3. Я неправильно понимаю часть того, что вы делаете, просто не уверен, где. У вас есть свойство VendorID в ViewModel, верно? Итак, пользователь отправляет форму, и VendorID должен быть там в привязанной к модели ViewModel. В методе post action, прежде чем возвращать представление из-за ошибок modelstate, вы можете запросить у объекта ViewModel идентификатор поставщика, верно? Когда вы возвращаете представление при наличии ошибок проверки, передаете ли вы тот же объект ViewModel, который вы получили через modelbinding?

4. (продолжение) Ключ в том, чтобы не думать о ViewModel как о методе Get action и обо всем, что должно изначально отображаться в представлении. ViewModel существует для поддержания состояния в течение всего жизненного цикла. Там должен быть включен идентификатор поставщика, хотя он всегда остается пустым, когда кто-то переходит на страницу заново.

5. Если при добавлении возникает ошибка, я создаю новый экземпляр ViewModel. Я делаю это главным образом потому, что ViewModel необходимо повторно заполнить списки выбора. Но это также объясняет, почему у меня нет идентификатора поставщика. Продукт не был сохранен, поэтому, когда я воссоздаю ViewModel, идентификатор поставщика возвращается к значению по умолчанию. Я предполагаю, что это говорит о вашем предположении, что ViewModel имеет свойства только для привязки модели. Мне было бы интересно узнать больше о ваших рассуждениях по этому поводу. Я был в лагере, что все, что нужно для представления, должно быть в строго типизированной ViewModel, но меня можно убедить в обратном.