Search code examples
c#asp.net-mvc-3viewmodelpost-redirect-get

How to use RedirectToAction while passing view model to a view with different route


I have a ASP.NET MVC 3 app with a common scenario where there is with an "About" controller using "Contact" and "ThankYou" actions. I want user to go to /about/contact, fill out the form, submit it, and be taken to /about/contact/thankyou * page where the form contents (aka view model) will be displayed.

** Note there is no "Contact" controller nor do I want to create one for this purpose if possible.*

I am using RedirectToAction to prevent resubmission (Post/Redirect/Get pattern) and TempData to pass on view model to thank you page. I can also use TempData to check if thank you page was reached directly and redirect back to contact form page (so it would not register as a "goal" in web analytics)

But one thing I could not figure out is how to use different route for thank you page so it appears as /about/contact/thankyou

Am I doing this right? Is there a better way?

Here are relevant actions in AboutController

<!-- language: c# -->
[RequireHttps]
public ActionResult Contact()
{
    var viewModel = new ContactViewModel();
    return View(viewModel);
}
[RequireHttps]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Contact(ContactViewModel viewModel)
{
    if (!ModelState.IsValid)
    {
        return View(viewModel);
    }       
    // not sure if this is the best way or how to redirect to /contact/thankyou 
    TempData["viewModel"] = viewModel;
    return RedirectToAction("ThankYou");
}               

[RequireHttps]
public ActionResult ThankYou()
{
    var viewModel = TempData["viewModel"];
    // upon direct access, viewModel will be null and missing, so redirect to Contact form
    if (viewModel == null)
    {
        return RedirectToAction("Contact");
    }
    return View(viewModel);
}

Solution

  • You could define a custom route before the default route:

    routes.MapRoute(
        "contact",
        "about/contact/thankyou",
        new { controller = "About", action = "ThankYou" }
    );
    

    Now when you navigate to /about/contact the Contact GET action will be executed (You have to rename it as in your code it is called ContactUs). Then the user fills the form and submits to the Contact POST action. The url stays the same for the moment: /about/contact. After the redirect the ThankYou action is executed and the url changes to /about/contact/thankyou.