16

Here's what I'm trying to do:

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

[HttpPost]
public ActionResult Index(ContactModel model)
{
    if (ModelState.IsValid)
    {
        // Send email using Model information.

        return RedirectToAction("Gracias", model);
    }

    return View(model);
}

public ActionResult Gracias(ContactModel model)
{
    return View(model);
}

All three action methods are in the same controller. Basically, a user type up some data in the contact form and I want to redirect them to a thank you page using their name in the Model object.

As the code is, it works, but the URL passed along with GET variables. Not ideal.

http://localhost:7807/Contacto/Gracias?Nombre=Sergio&Apellidos=Tapia&Correo=opiasdf&Telefono=oinqwef&Direccion=oinqef&Pais=oinqwef&Mensaje=oinqwef

Any suggestions?

sergserg
  • 21,716
  • 41
  • 129
  • 182

3 Answers3

40

Sounds like a solution for TempData!

[HttpPost]
public ActionResult Index(ContactModel model)
{
  if (ModelState.IsValid)
  {
    // Send email using Model information.
    TempData["model"] = model;
    return RedirectToAction("Gracias");
  }

  return View(model);
}

public ActionResult Gracias()
{
  ContactModel model = (ContactModel)TempData["model"];
  return View(model);
}
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • I had no idea you could save complex types to the TempData dictionary. TIL. Thanks! – sergserg Oct 22 '12 at 21:36
  • 1
    Only as long as they are Serializable!! TempData is stored in session, which only allows Serializable objects/classes. – Erik Philips Oct 22 '12 at 21:37
  • 3
    Temp data could certainly work here but why not just display the "Gracias" view directly from Index (where the model is already in scope). You also save your self a server round trip that is essentially a useless redirect. – John Culviner Oct 22 '12 at 21:41
  • 1
    First, the OP asked how to use RedirectToAction. Secondly, as I mentioned on your answer, the URL would not be `/Gracias`, but `/Index` so it depends on what the OP wants the url to look like. – Erik Philips Oct 22 '12 at 21:42
  • Good point I hadn't thought about the URL displayed really mattering. If it does then TempData is the best solution – John Culviner Oct 22 '12 at 21:44
2

Instead of doing

return RedirectToAction("Gracias", model);

You could do

[HttpPost]
public ActionResult Index(ContactModel model)
{
    if (ModelState.IsValid)
    {
        // Send email using Model information.

        return View("Gracias", model);
    }

    return View(model);
}

and remove your Gracias controller action. Using above the "Gracias" view will be displayed with your ContactModel model.

I don't see the need to have a separate controller action if it uses the same model and is a lock step part of the workflow ex. "a successful POST to Index will always result in the Gracias View being displayed"

You could also store the model in TempData (which is like a 1 request session state) but I don't see any point in doing that in your situation as it just complicates things

Thoughts?

John Culviner
  • 22,235
  • 6
  • 55
  • 51
  • The url would look like `http://localhost:7807/Contacto/Index`, if that is acceptable, this is the easiest way. – Erik Philips Oct 22 '12 at 21:41
  • Yeah that's not acceptable that's why I didn't go this route. – sergserg Oct 22 '12 at 21:44
  • Now just hope someone doesn't hit "http://localhost:7807/Contacto/Gracias" at some other time (or if they hit the back button and the page isn't cached) because the will come back with a view with empty fields and possibly even an exception depending on what your view looks like. Considering that you might not really want another URL being displayed. – John Culviner Oct 22 '12 at 21:46
  • I'll just check if the TempData is empty and redirect if so. – sergserg Oct 22 '12 at 22:02
-1

The quick answer is don't pass the entire model but some identifier that you can use to retrieve the model from the repository:

[HttpPost]
public ActionResult Index(ContactModel model)
{
    if (ModelState.IsValid)
    {
        // Send email using Model information.

        return RedirectToAction("Gracias", model.ID);
    }

    return View(model);
}

public ActionResult Gracias(int contactID)
{
    ContactModel model = new ContractRepository().GetContact(contactID);
    return View(model);
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • 1
    This doesn't work the way you think it does. If I pass in a updated model in the `HttpPost Index()` method, all those changes are *lost* because all the values in the method `Gracias()` are from the database, not the user. – Erik Philips Jan 20 '15 at 17:32