【问题标题】:How do I maintain ModelState errors when using RedirectToAction?使用 RedirectToAction 时如何维护 ModelState 错误?
【发布时间】:2009-03-18 15:24:03
【问题描述】:

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

谢谢。

【问题讨论】:

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


    【解决方案1】:

    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 并重定向回引荐来源网址。既然动作被抓到了,OnActionExecuted还是会被执行,但是第一次绕ModelStateTempData["ModelState"]是一样的,所以不想和自己合并。执行重定向操作时,OnActionExecuted 再次触发。这一次,如果TempData["ModelState"] 中有任何内容,它将与此操作的 ModelState 合并。

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

    【讨论】:

    • 我喜欢这个...似乎是一种方便的方法来完成这项工作。谢谢!
    • @Bill。我喜欢它。我已经扩展了您的代码以供我使用。而不是你的 RulesException.AddModelStateErrors(),我用另一种方式做,我扩展了 ModelState 有两个扩展方法;更新模型和恢复模型。为你 +1。
    【解决方案2】:

    我知道这个帖子很旧,但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");
    }
    

    【讨论】:

    • 问题或答案的年龄真的无关紧要 - 即使在 2014 年,他们也可以提供帮助 :-) 感谢您提供的链接,非常好的东西!
    • [ImportModelStateFromTempData][ExportModelStateToTempData] 属性也在这里解释:How to save the ModelState into session following the good practice
    • 您的链接(在我看到的 MVC 中关于 PRG 的每一次讨论中都无处不在)奇怪地死了。看起来 Rashid 的整个博客已从 ASP.NET 团队博客中删除。
    • 找到(大概)相同的链接asp.net MVC Best Practices (Part 1) - 见#13。使用 PRG 模式进行数据修改
    【解决方案3】:

    这篇博文描述了如何在 MVC 中实现 PRG 模式 http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx

    【讨论】:

    • 此链接已损坏
    【解决方案4】:

    使用 TempData[] 集合

    临时数据从一个请求存储到下一个请求,然后就消失了。

    【讨论】:

      【解决方案5】:

      无论我在哪里进行重定向,我为维护我的 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);
        }
        

      【讨论】:

        猜你喜欢
        • 2010-09-21
        • 2014-05-01
        • 1970-01-01
        • 2011-06-06
        • 1970-01-01
        • 2016-06-29
        • 2014-04-05
        • 2011-05-30
        • 2014-03-23
        相关资源
        最近更新 更多