I have a restful URL for the action of editing a page. This is implemented on the controller as an Edit method, which accepts GET requests and an Edit method that accepts POST requests.
This means you can visit the Edit URL and it will display a form for a GET or save a form for a POST.
[HttpGet]
public ActionResult Edit(int id) {
...
}
[HttpPost]
public ActionResult Edit(EditModel model) {
...
}
The Post-Redirect-Get (PRG) pattern seems pretty black and white, because it essentially redirects every POST back to a GET action. However, I need to be convinced that this is the correct thing to do.
My plan is that in the POST action, if the model is valid I will use the Post-Redirect-Get pattern to send the user to a reasonable location (probably the Index or Details action).
However, if there is a model validation problem, I still want to just display the view. I don't want to redirect the user, because it means stuffing the model and ModelState into temporary data and redirecting to the GET action - and then adding logic into the GET action to handle the temp data. I could avoid all of this by simply displaying the view.
Yes, if the user presses F5 it will re-submit the form and they will be presented with the "resubmission warning", but then the same page (asking them to fix validation errors). However, it seems unlikely that they will hit F5 and there is also no danger of a double-submission as the form will simply fail the validation once again.
If the validation passes, the user will be redirected and they will be safe from double submissions.
So should I implement additional code and stuff data into temp data in order to strictly follow the PRG pattern, or is it more sensible to use the PRG pattern when the form is valid and data is being stored?
You should only do the redirect if the form information is valid; in the case of submission errors, return the view from the same Edit method.
Doing it this way is compliant with PRG, because if your model is invalid, you are not allowing any changes to be made to the state of objects on the server. PRG is designed primarily to prevent multiple posts that can change the state of server objects (e.g., business objects, database tables, etc.) in unpredictable ways; in your validation example, however, the user can hit resubmit as many times as they want and they will always be sent back to the initial view with validation errors--nothing on the server changes. Therefore, you have it right: only issue the Redirect if your model passes validation in your presentation tier.
Even though Ken's answer does highlight an important fact - PRG doesn't necessarily mean "blindly return a redirect when posting" - you still might want to do redirect and preserve modelstate sometimes.
The easiest way to handle that scenario, is using action filters to export modelstate to the session (before redirecting), and then import modelstate (before executing the new action). Kazi Manzur Rashid has a couple of excellent blog posts (Part 1 Part 2) on best practices in ASP.NET MVC. They're quite old, but many of the tips there are still very much applicable. Tip number 13 in the first article is exactly what you're looking for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With