开发者

How to pass ModelErrors along with redirect?

开发者 https://www.devze.com 2023-01-04 14:32 出处:网络
ASP.NET MVC 2.0 I\'m doing Post-Redirect-Get, if I get errors on post, I need to include ModelErrors along for the ride to along -Redirect-Get route.

ASP.NET MVC 2.0

I'm doing Post-Redirect-Get, if I get errors on post, I need to include ModelErrors along for the ride to along -Redirect-Get route. I send it through 'TempData':

TempData["modelErors"] = 
    ModelState.
        Where(item => item.Value.Errors.Count > 0).
开发者_如何学运维        ToDictionary(
            item => item.Key, 
            item => item.Value.Errors.Select(error=>error.ErrorMessage).ToList()
        );

And then reinsert it into a 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);
        }
    }
}

Is there a better way?


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.

In ASP.NET MVC2 by default I think TempData uses Session state to store the information for the next request.


I think that the most cleaner solution was to use ActionFilterAttribute like this :

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)
{

And that works like a charm with clean manageable code.

Hope this Help!

Julien

0

精彩评论

暂无评论...
验证码 换一张
取 消