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?
I have a method that adds model state to temp data. I then have a method in my base controller that checks temp data for any errors. If it has them, it adds them back to ModelState.
You need to have the same instance of
Review
on yourHttpGet
action. To do that you should save an objectReview review
in temp variable on yourHttpPost
action and then restore it onHttpGet
action.Also i would advice, if you want to make it work also when browser refresh button pressed after
HttpGet
action executed first time, you may go like thatOtherwise on refresh button object
review
will be empty because there wouldn't be any data inTempData["Review"]
.Why not create a private function with the logic in the "Create" method and calling this method from both the Get and the Post method and just do return View().
My scenario is a little bit more complicated as I am using the PRG pattern so my ViewModel ("SummaryVM") is in TempData, and my Summary screen displays it. There is a small form on this page to POST some info to another Action. The complication has come from a requirement for the user to edit some fields in SummaryVM on this page.
Summary.cshtml has the validation summary which will catch ModelState errors that we'll create.
My form now needs to POST to a HttpPost action for Summary(). I have another very small ViewModel to represent edited fields, and modelbinding will get these to me.
The new form:
and the action...
In here I do some validation and I detect some bad input, so I need to return to the Summary page with the errors. For this I use TempData, which will survive a redirection. If there is no issue with the data, I replace the SummaryVM object with a copy (but with the edited fields changed of course) then do a RedirectToAction("NextAction");
The Summary controller action, where all this begins, looks for any errors in the tempdata and adds them to the modelstate.
I had to solve this problem today myself, and came across this question.
Some of the answers are useful (using TempData), but don't really answer the question at hand.
The best advice I found was on this blog post:
http://www.jefclaes.be/2012/06/persisting-model-state-when-using-prg.html
Basically, use TempData to save and restore the ModelState object. However, it's a lot cleaner if you abstract this away into attributes.
E.g.
Then as per your example, you could save / restore the ModelState like so:
If you also want to pass the model along in TempData (as bigb suggested) then you can still do that too.
I could use
TempData["Errors"]
TempData are passed accross actions preserving data 1 time.