代码之家  ›  专栏  ›  技术社区  ›  THX-1138

如何将模型错误与重定向一起传递?

  •  1
  • THX-1138  · 技术社区  · 14 年前

    ASP.NET MVC 2

    我正在做post-redirect-get,如果我在post上得到错误,我需要包括modelerrors-along,以便骑车到along-redirect-get路线。 我通过“tempdata”发送:

    TempData["modelErors"] = 
        ModelState.
            Where(item => item.Value.Errors.Count > 0).
            ToDictionary(
                item => item.Key, 
                item => item.Value.Errors.Select(error=>error.ErrorMessage).ToList()
            );
    

    然后将其重新插入模型状态:

    if (TempData.ContainsKey("modelErors")) {
        foreach (var errors in (IDictionary<string,IList<string>>) TempData["modelErors"]) {
            foreach (var error in errors.Value) {
                ModelState.AddModelError(errors.Key, error);
            }
        }
    }
    

    有更好的方法吗?

    2 回复  |  直到 14 年前
        1
  •  2
  •   Chad Moran    14 年前

    You should really only PRG after a successful post. Otherwise it's fine to return from the post if there's an error.

    Otherwise you need to use cookies, session or request variables to store that information for the next request.

    在ASP.NET MVC2中,默认情况下,我认为tempdata使用会话状态来存储下一个请求的信息。

        2
  •  0
  •   Julien    14 年前

    我认为最干净的解决方案是使用这样的actionfilterattribute:

    public class RedirectErrorAttribute : ActionFilterAttribute
    {
        #region Methods & Function
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
        }
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.Controller.TempData.ContainsKey("modelErrors"))
            {
                foreach (var errors in (Dictionary<string, List<string>>)filterContext.Controller.TempData["modelErrors"])
                    foreach (var error in errors.Value)
                        filterContext.Controller.ViewData.ModelState.AddModelError(errors.Key, error);
            }
    
            base.OnActionExecuting(filterContext);
        }
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (filterContext.Controller.ViewData.ModelState.Values.Any(x => x.Errors.Count > 0))
            {
                if (filterContext.Controller.TempData.ContainsKey("modelErrors"))
                    filterContext.Controller.TempData.Remove("modelErrors");
                else
                {
                    filterContext.Controller.TempData["modelErrors"] =
                        filterContext.Controller.ViewData.ModelState.
                        Where(item => item.Value.Errors.Count > 0).
                            ToDictionary(
                                item => item.Key,
                                item => item.Value.Errors.Select(error => error.ErrorMessage).ToList()
                            );
    
                    filterContext.Controller.TempData.Keep("modelErrors");
                }
            }
    
            base.OnResultExecuted(filterContext);
        }
    
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            base.OnResultExecuting(filterContext);
        }
    
        #endregion
    }
    

    After you just have to put your attribute on the top of the action that throw the error and the action that received the error like this :

    [RedirectError]
    public ActionResult Delete(Guid id)
    {
    
    [RedirectError]
    public ActionResult Get(Guid id)
    {
    

    这就像一个具有清晰可管理代码的魅力。

    希望这有帮助!

    朱利安