Как я могу поддерживать ModelState с RedirectToAction?

Как я могу вернуть результат другого действия или переместить пользователя на другое действие, если в моем ModelState есть ошибка, не потеряв мою информацию ModelState?

Сценарий; Действие «Удалить» принимает POST из формы DELETE, отображаемой моим указателем Action / View. Если в Delete есть ошибка, я хочу переместить пользователя обратно в действие / представление индекса и показать ошибки, которые сохраняются действием Delete в ViewData.ModelState . Как это можно сделать в ASP.NET MVC?

 [AcceptVerbs(HttpVerbs.Post | HttpVerbs.Delete)] public ActionResult Delete([ModelBinder(typeof(RdfUriBinder))] RdfUri graphUri) { if (!ModelState.IsValid) return Index(); //this needs to be replaced with something that works :) return RedirectToAction("Index"); } 

Сохраните данные своего вида в TempData и извлеките их оттуда в своем указателе, если оно существует.

  ... if (!ModelState.IsValid) TempData["ViewData"] = ViewData; RedirectToAction( "Index" ); } public ActionResult Index() { if (TempData["ViewData"] != null) { ViewData = (ViewDataDictionary)TempData["ViewData"]; } ... } 

[EDIT] Я проверил он-лайн источник для MVC, и кажется, что ViewData в controllerе настраивается, поэтому, вероятно, проще всего передать все ViewData, включая ModelState, в действие индекса.

Используйте Action Filters (шаблон PRG) (так же просто, как и с использованием атрибутов)

Упоминается здесь и здесь .

Обратите внимание, что решение tvanfosson не всегда будет работать, хотя в большинстве случаев это должно быть хорошо.

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

Другая ситуация, когда она может работать не так, как ожидалось, – если у вас есть фильтр действий, который инициализировал некоторые ошибки ViewData или ModelState. Опять же, они будут перезаписаны этим кодом.

Мы рассматриваем некоторые решения для ASP.NET MVC, которые позволят вам более легко слить состояние из двух запросов, поэтому следите за обновлениями.

Спасибо, Эйлон

В случае, если это полезно для всех, кто использовал рекомендованное @bob решение с использованием PRG:

см. ссылку 13 ->.

У меня была дополнительная проблема с сообщениями, передаваемыми в VeiwBag, на представление, которое записывается и проверяется / загружается вручную из TempData в действиях controllerа при выполнении RedirectToAction("Action") . В попытке упростить (а также сделать его поддерживаемым) я немного расширил этот подход, чтобы проверить и сохранить / загрузить другие данные. Мои методы действий выглядели примерно так:

  [AcceptVerbs(HttpVerbs.Post)] [ExportModelStateToTempData] public ActionResult ChangePassword(ProfileViewModel pVM) { bool result = MyChangePasswordCode(pVM.ChangePasswordViewModel); if (result) { ViewBag.Message = "Password change success"; else { ModelState.AddModelError("ChangePassword", "Some password error"); } return RedirectToAction("Index"); } 

И мое действие по индексу:

 [ImportModelStateFromTempData] public ActionResult Index() { ProfileViewModel pVM = new ProfileViewModel { //setup } return View(pVM); } 

Код в Action Filters:

 // Following best practices as listed here for storing / restoring model data: // http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#prg public abstract class ModelStateTempDataTransfer : ActionFilterAttribute { protected static readonly string Key = typeof(ModelStateTempDataTransfer).FullName; } 

:

 public class ExportModelStateToTempData : ModelStateTempDataTransfer { public override void OnActionExecuted(ActionExecutedContext filterContext) { //Only export when ModelState is not valid if (!filterContext.Controller.ViewData.ModelState.IsValid) { //Export if we are redirecting if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult)) { filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState; } } // Added to pull message from ViewBag if (!string.IsNullOrEmpty(filterContext.Controller.ViewBag.Message)) { filterContext.Controller.TempData["Message"] = filterContext.Controller.ViewBag.Message; } base.OnActionExecuted(filterContext); } } 

:

 public class ImportModelStateFromTempData : ModelStateTempDataTransfer { public override void OnActionExecuted(ActionExecutedContext filterContext) { ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary; if (modelState != null) { //Only Import if we are viewing if (filterContext.Result is ViewResult) { filterContext.Controller.ViewData.ModelState.Merge(modelState); } else { //Otherwise remove it. filterContext.Controller.TempData.Remove(Key); } } // Restore Viewbag message if (!string.IsNullOrEmpty((string)filterContext.Controller.TempData["Message"])) { filterContext.Controller.ViewBag.Message = filterContext.Controller.TempData["Message"]; } base.OnActionExecuted(filterContext); } } 

Я понимаю, что мои изменения здесь являются довольно очевидным расширением того, что уже было сделано с ModelState по коду @ ссылка, предоставленная @bob, – но мне пришлось наткнуться на эту тему, прежде чем я даже подумал о ее обработке таким образом.

Возможно, попробуйте

 return View("Index"); 

вместо

 return Index(); 
  • Как создать собственный атрибут проверки для MVC
  • Вытягивание представления из базы данных, а не файла
  • Как избежать уязвимостей XSS в ASP.Net (MVC)?
  • Модель, поддерживающая контекст «ApplicationDbContext», изменилась с момента создания базы данных
  • Jquery ajax form submit, содержащий файлы
  • DropDownList устанавливает выбранный элемент в asp.net MVC
  • Как использовать Simple Ajax Beginform в Asp.net MVC 4?
  • Поддержка ASP.net MVC для URL с дефисами
  • Как включить модель с RedirectToAction?
  • Как вы перенаправляетесь на страницу с помощью глагола POST?
  • ASP.NET связывает, как отключить минимизацию
  • Давайте будем гением компьютера.