asp.net-mvcerror-handlingmodelstateredirecttoactionhttp-redirect

ASP.NET MVC - How to Preserve ModelState Errors Across RedirectToAction?


I have the following two action methods (simplified for question):

[HttpGet]
public ActionResult Create(string uniqueUri)
{
   // get some stuff based on uniqueuri, set in ViewData.  
   return View();
}

[HttpPost]
public ActionResult Create(Review review)
{
   // validate review
   if (validatedOk)
   {
      return RedirectToAction("Details", new { postId = review.PostId});
   }  
   else
   {
      ModelState.AddModelError("ReviewErrors", "some error occured");
      return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
   }   
}

So, if the validation passes, i redirect to another page (confirmation).

If an error occurs, i need to display the same page with the error.

If i do return View(), the error is displayed, but if i do return RedirectToAction (as above), it loses the Model errors.

I'm not surprised by the issue, just wondering how you guys handle this?

I could of course just return the same View instead of the redirect, but i have logic in the "Create" method which populates the view data, which i'd have to duplicate.

Any suggestions?


Solution

  • You need to have the same instance of Review on your HttpGet action. To do that you should save an object Review review in temp variable on your HttpPost action and then restore it on HttpGet action.

    [HttpGet]
    public ActionResult Create(string uniqueUri)
    {
       //Restore
       Review review = TempData["Review"] as Review;            
    
       // get some stuff based on uniqueuri, set in ViewData.  
       return View(review);
    }
    [HttpPost]
    public ActionResult Create(Review review)
    {
       //Save your object
       TempData["Review"] = review;
    
       // validate review
       if (validatedOk)
       {
          return RedirectToAction("Details", new { postId = review.PostId});
       }  
       else
       {
          ModelState.AddModelError("ReviewErrors", "some error occured");
          return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
       }   
    }
    

    If you want this to work even if the browser is refreshed after the first execution of the HttpGet action, you could do this:

      Review review = TempData["Review"] as Review;  
      TempData["Review"] = review;
    

    Otherwise on refresh button object review will be empty because there wouldn't be any data in TempData["Review"].