Search code examples
c#asp.net-mvcpost-redirect-get

Cleaning up post action in MVC


I'm using PRG for cleaning up my posts in MVC

On the POST action I store the controller modelstate in tempdata using an action filter and then redirect to the GET method which reloads the modelstate.

GET and POST action headers:

[ImportModelStateFromTempData]
public ActionResult Details(int id) { 
    var object = load(id);
    return View(object);
}

[HttpPost]
[ExportModelStateToTempData]
public ActionResult Details(MyViewModel model) { 
    update(model); return RedirectToAction("Details", new { id = model.id }) 
}

if an error occurs I in the post action I add an error to the modelstate which invalidates the modelstate and then redirect to the get action.

My question is how best can I determine, in the GET "Details" action that the model was in an error state after the post? If the modelstate was invalid I want to skip the logic...

var object = load(id);

in the GET action. I've tried ModelState.IsValid but this does not work.


Solution

  • You could try something like this:

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;
    
        if( !modelState.IsValid )
        {
            filterContext.Controller.TempData.Add("IsValid", false);
        }
    }
    

    In your controller you can check the TempData["IsValid"] field instead of ModelState.IsValid:

    if( TempData["IsValid"] != null ) // do whatever here, or skip code etc.
    

    Notice how the action filter code is in the OnActionExecuting method. YOu will keep the existing code in the OnActionExecuted:

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {         ModelStateDictionary modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;
    
        if (modelState != null)
        {
            if (filterContext.Result is ViewResult)
            {
                filterContext.Controller.ViewData.ModelState.Merge(modelState);
            }
            else
            {
                filterContext.Controller.TempData.Remove(Key);
            }
        }
    }