使用RedirectToAction时如何维护ModelState错误?
我有一些代码可以在我们的系统中保存票证。 如果有错误,它会执行RedirectToAction。 问题是我似乎没有在新动作中出现错误。 我怎样才能解决这个问题?
ModelState.AddModelError("_FORM", "Unable to save ticket"); ModelState.AddModelError("_FORM", "Phone number was invalid."); ModelState.AddModelError("_FORM", "Lane number is required."); return RedirectToAction("CreateStep", "Ticket");
我知道有人建议使用TempData,但是如何从ModelState中获取每个错误?
谢谢。
PRG模式还可以,但我这样做了:
基础控制器:
protected override void OnActionExecuted(ActionExecutedContext filterContext) { if (TempData["ModelState"] != null && !ModelState.Equals(TempData["ModelState"])) ModelState.Merge((ModelStateDictionary)TempData["ModelState"]); base.OnActionExecuted(filterContext); }
动作(我正在使用xVal ):
try { user.Login(); AuthenticationManager.SignIn(user); } catch (RulesException rex) { // on bad login rex.AddModelStateErrors(ModelState, "user"); TempData["ModelState"] = ModelState; return Redirect(Request.UrlReferrer.ToString()); }
该操作抛出exception,将ModelState添加到TempData并重定向回引用者。 由于操作被捕获,OnActionExecuted仍然执行,但第一次围绕ModelState与TempData [“ModelState”]相同,因此您不希望与自己合并。 执行重定向操作时,OnActionExecuted再次触发。 这一次,如果TempData [“ModelState”]中有任何内容,它会与此动作的ModelState合并。
您可以使用TempData [“ModelState.user”] = ModelState将其扩展为多个模型,然后合并以ModelState开头的每个TempData对象。
我知道这个post已经过时了,但是关于ASP.NET最佳实践的博客有一些很好的建议。
页面上的#13处理使用2个Actionfilter在重定向之间保存和恢复ModelState
。
这是我的作品使用的模式,我喜欢它。
这是简化的例子:
[ImportModelStateFromTempData] public ActionResult Dashboard() { return View(); } [AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData] public ActionResult Dashboard(string data) { if (ValidateData(data)) { try { _service.Submit(data); } catch (Exception e) { ModelState.AddModelError(ModelStateException, e); } } return RedirectToAction("Dashboard"); }
这篇博文描述了如何在MVC中实现PRG模式http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx
心连心
使用TempData []集合
tempdata从一个请求存储到下一个请求,然后它就消失了。
无论我在哪里使用重定向,我所做的是维护我的ModelState,如下所示:
-
在您的模型中,添加:
public ModelStateDictionary modelstate { get; set; }
-
在模型的构造函数中,添加:
this.modelstate = new System.Web.Mvc.ModelStateDictionary();
-
我的模型示例post名为Models.ContactInformation:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult contact(Models.ContactInformation con) { if (string.IsNullOrEmpty(con.SelectedAgencySelectorType)) { ModelState.AddModelError("", "You did not select an agency type."); } con.modelstate = ModelState; TempData["contact"] = con; if (!ModelState.IsValid) return RedirectToAction("contactinformation", "reports"); //do stuff return RedirectToAction("contactinformation", "reports"); }
-
所以现在你的tempdata有你的模型和模型状态。
-
以下是我对任何事物的状态都是不可知的观点,除非它有某些东西。 这是代码:
[HttpGet] public ActionResult contactinformation() { //try cast to model var m = new Models.ContactInformation(); if (TempData["contact"] is Models.ContactInformation) m = (Models.ContactInformation)TempData["contact"]; //restore modelstate if needed if (!m.modelstate.IsValid) { foreach (ModelState item in m.modelstate.Values) { foreach (ModelError err in item.Errors) { ModelState.AddModelError("", err.ErrorMessage.ToString()); } } } return View(m); }
我相信当你进行重定向时你会失去模型状态。 也许你可以将你的逻辑重写为:
public ActionResult Save() { // your code... if(saveSucceeded) { return View("Saved"); } else { return View("Create"); } }
以及获取错误消息的常用方法:
<%= Html.ValidationMessage("property_name") %>