PRG (Post Redirect Get) - sdcruzinsight/Kentico13CoreBaseline GitHub Wiki

Post Redirect Get is a method of preventing Post-back when someone submits a form. The form Posts to your controller, the controller performs whatever logic, then redirects to the next step or back to the original page (if there are errors).

In MVC, this is somewhat complicated by the ModelState that gets populated with various validation errors and user inputs, as well as the ViewModel does not naturally persist. A solution is when a POST action is performed, to store the ModelState/ViewModel before the redirect in a buffer that persists between requests, then restore that model state after the redirect has occurred. This is done through the [ExportModelState] Attribute that is provided in the baseline, as well as the IModelStateService.StoreViewModel(TempData, viewModel).

To restore this ModelState afterwards, you can either call the <vc:import-model-state /> view component or call IModelStateService.MergeModelState(ModelState, TempData) in your ViewComponent/Controller. This handles merging and restoring the Model with the ModelState.

To restore the ViewModel afterwards, you should call IModelStateService.GetViewModel<TheViewModel>(TempData). This returns null if there is no existing view model stored in the temp data, so i recommend coding it like this:

var model = _modelStateService.GetViewModel<ResetPasswordViewModel>(TempData) ?? new ResetPasswordViewModel()
{
     // Default properties here
};

Doing these two things allows you to to have a Page builder page that POSTs to a controller action, that controller action validate (adding validation errors), and redirect back to your page to show the errors.

You can see an example on the Login View Component and the Login Post Action

Clearing ModelState/ViewModel

TempData persists until the same request is made. Normally this is fine if you Post-Redirect-Get back to your original page, however if you redirect to a different page, then that TempData will be there until you hit original page again. In cases such as Logging in (where you may redirect to a different page), you should ModelState.Clear() and IModelStateService.ClearViewModel<MyViewModel>(TempData) before redirecting to prevent the user from seeing old TempData when they return to the page later. See Login Post Action for an example.