1

I have two screens in my application. On the first one, the user selects two values that are passed in to the next controller using the TempData object (we are not able to use the Session object).

Then in the controller for my second page, it reads these values and assigns them to a new model. This all works perfectly unless the user refreshes the page. In this case, the TempData variables are lost, and my model no longer contains the values.

The first controller action (when you select the second item from a select list)

[HttpPost]
public ActionResult Select(ProductSelector model)
{
    if (!ModelState.IsValid)
    {
        ProductSelector newModel = InitialiseProductSelectorModel();
        newModel.ProductId = model.ProductId;
        newModel.StatusId = model.StatusId;
        return View("ProductSelector", newModel);
    }
    TempData["StatusId"] = model.StatusId;
    TempData["ProductId"] = model.ProductId;
    return RedirectToAction("Create", "ProductDetails");
}

My second controller action looks like this:

[HttpGet]
public ActionResult Create()
{
    int ProductId, StatusId;
    // Get ProductId and StatusId from product selector screen
    int.TryParse(TempData["ProductId"].ToString(), out ProductId);
    int.TryParse(TempData["StatusId"].ToString(), out StatusId);
    model.ProductId = ProductId;
    model.StatusId= StatusId;

    return View("OrderCreate", model);
}

How can I get around this? I have another action which takes the model as a parameter, but this is for the POST method.

mikeyq6
  • 1,138
  • 13
  • 27
  • I'm afraid you don't understand fully how the MVC pattern works and how information is passed. To start with, read a bit more about model binding. Then have a look at TempData (http://stackoverflow.com/questions/2642062/asp-net-mvc-does-browser-refresh-make-tempdata-useless) – L-Four Feb 10 '17 at 14:26
  • Can you please elaborate? The only way I can see to pass data from one controller to another is to use the session or tempdata, or pass it in the querystring. If it were all in the same controller, then I would use `return View()` – mikeyq6 Feb 10 '17 at 14:40
  • No, you pass data with model binding. It's the MVC way of passing information, just search for it. – L-Four Feb 10 '17 at 14:46
  • That is for passing data between a controller and a view, not between two different controllers. – mikeyq6 Feb 10 '17 at 14:48
  • 1
    How are you calling "Create" controller action from the original action ? I mean where are you setting TempData before it comes to "Create" ? – Chetan Feb 10 '17 at 14:51
  • You changed the original example. There a model was passed, but nothing done with it. And in your text you talk about next page, not controller. Maybe you should make your question more clear. – L-Four Feb 10 '17 at 14:52
  • I've updated my question with details about the first controller code – mikeyq6 Feb 10 '17 at 14:54
  • Why you can not pass the data as part of querystring when redirecting? – Chetan Feb 10 '17 at 15:02
  • @L-Four I think I've found what I'm looking for here: http://stackoverflow.com/questions/17178164/best-practice-for-a-multipage-form-mvc-web-app Thanks for your help in any case – mikeyq6 Feb 10 '17 at 15:02
  • @ChetanRanpariya Because I am limited in requirements to not passing that information through the querystring – mikeyq6 Feb 10 '17 at 15:04
  • _using the TempData object (we are not able to use the Session object)_? Do you realize `TempData` **is** `Session` :). –  Feb 10 '17 at 23:31
  • @StephenMuecke Yes, that's correct. We are using a load-balanced server, which is why we are not using the `Session` object. While we have setup sticky sessions, ours users tend to use separate tabs in their browser window, which won't work with sessions. `TempData` on the other hand works fine, as the sticky session ensures that the data gets posted back to the correct server. – mikeyq6 Feb 13 '17 at 09:40

1 Answers1

1

Try this way to pass parameters

return RedirectToAction("Create", "ProductDetails", 
                 new { StatusId = StatusId , ProductId = ProductId });

and in next action receive these values

public ActionResult Create(int StatusId, int ProductId)

EDIT:: Another Way (Without Querystring):

In your create action, do this before fetching data back from TempData

[HttpGet]
public ActionResult Create()
{
    int ProductId, StatusId;

    TempData.Keep("ProductId"); // These two lines will keep data
    TempData.Keep("StatusId");  // upon multiple refreshes

    int.TryParse(TempData["ProductId"].ToString(), out ProductId);
    int.TryParse(TempData["StatusId"].ToString(), out StatusId);
    model.ProductId = ProductId;
    model.StatusId= StatusId;

    return View("OrderCreate", model);
}
Lali
  • 2,816
  • 4
  • 30
  • 47
  • That would be ok, except I can't pass data through the querystring. – mikeyq6 Feb 10 '17 at 15:28
  • @mikeyq6 This *isn't* passing data in a query string. It adds those route parameters. If your route is defined such that it doesn't have those parameters defined, it will add them to the query string. So, define your route with parameters. –  Feb 11 '17 at 00:08
  • But in both cases that data gets passed through the url. If you define the route, then that just means that they are not key/value pairs. In the above case, it would mean the difference between: `/ProductDetails/Create/1/2` and `/ProductDetails/Create/1/?ProductId=2`. In either case, the parameters are still being passed in the URL – mikeyq6 Feb 13 '17 at 09:35
  • @Amy I meant that I can't pass data through the URL, sorry for not being clear about that – mikeyq6 Feb 13 '17 at 10:12
  • 1
    HTTP does not support redirection of the POST or PUT verbs. And if your `Create` action is a GET request, passing a message body is not supported. In short, what you're trying to do is not permitted per the HTTP spec. See [this](https://softwareengineering.stackexchange.com/questions/99894/why-doesnt-http-have-post-redirect) –  Feb 13 '17 at 18:47
  • You can `keep` your data across multiple 'refreshes'. I modified the answer. – Lali Feb 14 '17 at 14:23