使用RedirectToAction时如何维护ModelState错误?

时间:2009-03-18 15:24:03

标签: c# asp.net asp.net-mvc

我有一些代码可以在我们的系统中保存票证。如果有错误,它会执行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中获取每个错误?

感谢。

5 个答案:

答案 0 :(得分:41)

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());
}

该操作抛出异常,将ModelState添加到TempData并重定向回referrer。由于捕获了动作,OnActionExecuted仍然执行,但ModelState第一次与TempData [“ModelState”]相同,因此您不想与自己合并。执行重定向操作时,OnActionExecuted再次触发。这一次,如果TempData [“ModelState”]中有任何内容,它会与此动作的ModelState合并。

您可以使用TempData [“ModelState.user”] = ModelState将其扩展为多个模型,然后合并以ModelState开头的每个TempData对象。

答案 1 :(得分:29)

我知道这个帖子已经过时了,但this blog about ASP.NET Best Practices有一些很好的建议 页面上的#13处理使用2个动作过滤器在重定向之间保存和恢复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");
}

答案 2 :(得分:4)

此博客文章介绍了如何在MVC中实现PRG-Pattern http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx

HTH

答案 3 :(得分:3)

使用TempData [] Collection

tempdata从一个请求存储到下一个请求,然后就消失了。

答案 4 :(得分:0)

无论我在哪里使用重定向,我所做的是维护我的ModelState,如下所示:

  1. 在您的模型中,添加:

    public ModelStateDictionary modelstate { get; set; }
    
  2. 在模型的构造函数中,添加:

    this.modelstate = new System.Web.Mvc.ModelStateDictionary();
    
  3. 我的模型示例帖子名为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");
    }
    
  4. 所以现在你的tempdata按原样有你的模型和模型状态。

  5. 以下是我对任何事物的状态都不了解的观点,除非它有某些东西。这是代码:

    [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);
    }