如何传递ModelErrors以及重定向?

时间:2010-06-25 14:10:09

标签: asp.net-mvc tempdata

ASP.NET MVC 2.0

我正在进行Post-Redirect-Get,如果我在帖子上收到错误,我需要包含ModelErrors以便沿着-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()
        );

然后将其重新插入ModelState:

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 个答案:

答案 0 :(得分:2)

成功发帖后你应该只做PRG。否则,如果出现错误,可以从帖子返回。

否则,您需要使用cookie,会话或请求变量来存储下一个请求的信息。

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

答案 1 :(得分:0)

我认为最清洁的解决方案是使用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
}

在您必须将属性放在引发错误的操作的顶部以及收到错误的操作之后:

[RedirectError]
public ActionResult Delete(Guid id)
{

[RedirectError]
public ActionResult Get(Guid id)
{

这就像一个带有干净可管理代码的魅力。

希望这个帮助!

于连