The PRG pattern is ok, but I did this:
Base controller:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (TempData["ModelState"] != null && !ModelState.Equals(TempData["ModelState"]))
ModelState.Merge((ModelStateDictionary)TempData["ModelState"]);
base.OnActionExecuted(filterContext);
}
Action (I'm using 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());
}
The action throws an exception, adds the ModelState
to TempData
and redirects back to the referrer. Since the action is caught, OnActionExecuted
is still executed, but the first time around the ModelState
is the same as TempData["ModelState"]
, so you don't want to merge with yourself. When the redirect action is executed, OnActionExecuted
fires again. This time, if there's anything in TempData["ModelState"]
, it merges with this action's ModelState.
You could expand it to multiple models by using TempData["ModelState.user"] = ModelState
and then merging every TempData
object that starts with ModelState.
.