Using MVC2 TempData with the PRG Design Pattern

Post/Redirect/Get (PRG) is a common design pattern recommended for use with HTML forms. Redirecting after a successful form post can help avoid accidental duplicate submissions and allows a browser to behave more intuitively with bookmarks and the refresh button. Most MVC examples follow this pattern:

[HttpPost]
public ActionResult Edit(int id, Contact contact) {
    if (ModelState.IsValid) {
        // Submit values to the database
        return RedirectToAction("Index");
    }
    return View();
}

As you can see, if the POST action is completed successfully, then a REDIRECT occurs to GET a new page. If there is a validation error, then the posted data is returned back to the client through a view (usually through the same view). ViewData keeps track of posted data throughout the request lifecycle. You can add and modify values in this collection during action processing. However, when a RedirectToAction is executed, the ViewData is lost. This is a good thing since the redirect causes a new GET request to be issued which, according to RESTful principles, should not track any state from a preceding request.

However, sometimes we want to internally pass information to the next request. This could be implemented as a URL parameter, but then the information would be present whenever that specific URL was requested rather than just one time in the next request after the post that issued the redirect. A common need, for example, is to display a confirmation message after an update from the previous page has completed successfully.

The TempData collection provides a solution to this problem. It exists to store information that can be consumed in a subsequent request (or in the case of multiple RedirectToActions, it can be consumed in more than one subsequent request). By default, the temporary data is stored internally in SessionState to provide the required persistence.

This example demonstrates use of TempData to pass a message to the next request:

[HttpPost]
public ActionResult Edit(int id, Contact contact) {
    if (ModelState.IsValid) {
        // Submit values to the database
        TempData["Message"] = "Your changes have been saved.";
        return RedirectToAction("Index");
    }
    return View();
}

Within the Index view:

<% if (TempData["Message"] != null) { %>
    <p class="message"%gt;<%: TempData["Message"] %></p>
<% } %>

To learn more about the internal behavior of TempData, read Jacques Eloff’s article on TempData improvements in MVC2.

Leave a Reply

Your email address will not be published. Required fields are marked *