Search code examples
asp.net-mvc-4sessionpersistencetempdata

MVC PRG pattern - passing a model around


I'm using the PRG pattern (Post-Redirect-Get) in my MVC project. The idea is that you don't return a View from your action, rather on a successful POST you Redirect to another view entirely which does a Get (perhaps on a database) to get back the saved values and redisplay them (think of a "Save Successful" page).

In my case I do not have a database to persist the saved details, and I'd like to know a reliable way to store and then get the saved details on the next page.

I was doing

RedirectToAction("Success", myViewModel)

which I understand is wrong, not least because it has all the values in the URL bar. What I need to do is

RedirectToAction("Success")

and then somehow get the values back out, build a viewmodel and give it to the view.

I'm aware that there is the ViewBag, TempData, ViewData and Session but without a lot of testing in various scenarios I do not know which one is the one to use for my situation. Statics are obviously no good for a public-facing website.

If you are doing PRG without a database, what is the way to persist the data? Or can I simply throw some sort of an error & redirect if the user does go back & forwards?

Many thanks in advance.

EDIT: Example scenario - car insurance. A user visits a site, fills in personal details and hits Submit. On the next page the options are presented (third-party, theft, voluntary excess etc) and upon selecting them a call via AJAX is made to get a quote.

All the personal details get sent along with the options. But there is no user account and nothing has been written to the database (Data Protection Act - we don't store data unless given permission and asking will put people off if they are just browsing).

UPDATE: The solution we settled on was as follows: Details POST action builds an OptionsViewModel. It is put into TempData. RedirectToAction("Options") is called. In the Options action we get the viewmodel

OptionsViewModel viewModel = (OptionsViewModel)TempData.Peek("MyViewModel"); // .Peek preserves the value

If the viewmodel is null, we RedirectToAction() back to Details. Otherwise we return the Options view.


Solution

  • Apart from the ugly query string it creates, RedirectToAction("Success", myViewModel) can fail because (1) you could exceed the query string limit (which would throw an exception) or (2) if your model contains properties which are complex objects or collections, those properties will be null in the GET method.

    ViewBag and ViewData are not appropriate for passing values between methods - they are for passing data from the controller to the view (refer this article)

    Its not clear why you do not have some kind to permanent storage, but without it, you would need either TempData or Session to temporarily store the data between requests.

    TempData uses Session but it only lasts one request, so if you use it to pass the model to the Success() method, and the user refreshes the browser, the model will be null, although you can use .Peek or .Keep to override that behavior (refer this question/answer).

    Personally, I never use Session (and only use TempData for passing non critical data such as a one time message indicating success) and would consider persisting the data somewhere, for example to a xml file before redirecting so that it can be read again in the GET method.