36

I have a controller that handles three actions that are specific to my problem.

The first is the edit action which returns a view with an HTML form that the user can edit properties on the given item.

The second is the update action which accepts the post back form the browser and updates the database. When the update is successful we do a redirect to action.

The third is the show action which shows the details of the given item. This action is where we get redirected to after a successful update.

The flow is:

Show -> Edit -> Update (Sucess: y -> redirect to Show, n -> return Edit)

What I want to achieve is to have a flag tripped when the update was successful so that on the next Show view I can display a confirmation message for the user. The problem is that I'm not 100% sure on the best way to carry that data over the RedirectToAction() call. One thought I had was using a query string? We are already carrying variables around with the query string for another purpose but part of my is skeptical to abuse that. The call to the redirect is below.

RouteValueDictionary dict = Foo.GetRouteValues(bar);

RedirectToAction("Show", dict);

I've read this question as well but am leary about using the TempData property if I don't have to.

Question

Thanks for some suggestions!

Community
  • 1
  • 1

2 Answers2

49

EDIT: Sorry, didn't originally see your note about not wanting to use TempData.

In a nutshell - do you want your message to reappear if the client refreshes/reloads the page they've been redirected to?

If you do, then use the querystring, something like:

return(RedirectToAction("Index", new { message = "hi there!" }));

and then either define

public ActionResult Index(string message) { }

or explicitly pull out Request.QueryString["message"] and pass it to the View via ViewData in the usual way. This will also work on browsers that aren't accepting cookies from your site.

If you DON'T want the message to display again, then ASP.NET MVC 1.0 provides the TempData collection for this exact purpose.

TempData property values are stored in session state until the next request from the same browser, after which they are cleared - so if you put something in TempData immediately before returning RedirectToAction, it'll be available on the result of the redirect but will be cleared immediately afterwards.

Here's a simple change to the HomeController in the ASP.NET MVC startup project:

public ActionResult Index() {
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string submitButton) {
    TempData["message"] = "You clicked " + submitButton;
return(RedirectToAction("Index"));
}

public ActionResult About() {
    return View();
}

and the corresponding view /Views/Home/Index.aspx should contain something like this:

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
  <% if (TempData["message"] != null) { %>
    <p><%= Html.Encode(TempData["message"]) %></p>
  <% } %>
  <% using (Html.BeginForm()) { %>
    <input type="submit" name="submitButton" value="Button One" />
    <input type="submit" name="submitButton" value="Button Two" />
  <% } %>
</asp:Content>

You'll notice the TempData message is displayed immediately following a POST-REDIRECT-GET sequence, but if you refresh the page, it won't be displayed again.

Note that this behaviour has changed in ASP.NET MVC 2 - see "Passing State between Action Methods" in this article for more information.

Benjamin Hodgson
  • 42,952
  • 15
  • 108
  • 157
Dylan Beattie
  • 53,688
  • 35
  • 128
  • 197
  • Thanks for the nice explanation. I'm going to take a look at the article since we are on 2.0. I mentioned in my post that I wanted to stay away from the TempData property however if that is the defacto way then maybe it won't be so bad. Thanks again. –  Jul 29 '10 at 15:14
  • 4
    This is an old question, but the link is broken now :( –  Sep 27 '12 at 20:38
  • 3
    Modern(ish) working link for that article (scroll about halfway down): http://msdn.microsoft.com/en-us/library/dd394711(v=vs.100).aspx – Jaxidian Aug 15 '13 at 14:27
4

Never been a fan of TempData either and additionally I didnt want to pass the success flag in the URL as I didnt want to see

App/Settings?saveSuccess=true

in the URL bar of the browser.

My solution uses a temporary cookie:

[HttpPost]
public ActionResult Settings(SettingsViewModel view)
{
    if (ModelState.IsValid)
    {
        //save
        Response.SetCookie(new HttpCookie("SettingsSaveSuccess", ""));
        return RedirectToAction("Settings");
    }
    else
    {
        return View(view);
    }     
}

and in the corresponding Get action check for the presence of this Cookie and delete it:

[HttpGet]
public ActionResult Settings()
{
    var view = new SettingsViewModel();
    //fetch from db and do your mapping
    bool saveSuccess = false;
    if (Request.Cookies["SettingsSaveSuccess"] != null)
    {
        Response.SetCookie(new HttpCookie("SettingsSaveSuccess", "") { Expires = DateTime.Now.AddDays(-1) });
        saveSuccess = true;
    }
    view.SaveSuccess = saveSuccess;
    return View(view);
}

nb this can be a fairly slipperly slope if you start to pass anything more complex than a boolean flag

wal
  • 17,409
  • 8
  • 74
  • 109
  • Hi - what is the danger if you pass the string that would be the confirmation message to the cookie value (e.g. your settings saved ok, or settings not saved)? – Bartosz Jul 14 '15 at 12:41
  • @Bartosz are you able to just use a boolean and then set the response message based on that? If the response message could be more than 2 things then you will have to be pragmatic about it - it feels a bit wrong - ie if you have multiple error messages then it should be shown before the redirect - If your settings didnt save then that should handled by the else statement in the first snippet of code and shouldnt be redirected – wal Jul 14 '15 at 13:43