0

I have a form that I'm working on in ASP MVC, and I'd like to persist the data between pages (obviously).

At the moment, I'm using a big view model that contains all fields from the entire form. I then have an action for each step of the form:

// STEP ONE
public ActionResult Step1(MyViewModel model)
{
    return View("Step1", model);
}

// STEP TWO
public ActionResult Step2(MyViewModel model)
{
    return View("Step2", model);
}

// STEP THREE
public ActionResult Step3(MyViewModel model)
{
    return View("Step3", model);
}

// STEP FOUR
public ActionResult Step4(MyViewModel model)
{
    return View("Step4", model);
}

Each form on each page has the action set to the next step, so Step1.cshtml contains a form wherein the action attribute is pointing to step 2.

The problem is, if there's a server-side validation error detected during Step 2, I have no way of sending the user back to Step 1 without losing state.

Does anyone have a relatively tidy solution for this? I've already considered, and would like to avoid, the following if possible:

  1. Using JavaScript to create the illusion of multiple pages, while actually only managing a single form. This really won't work for me as if there are server-side validation errors at the end of Step 1, it will only be detected in Step 4 and it will completely ruin the flow of the form.

  2. Adding an if-condition to select the view depending on the ModelState. This is problematic because it means the view will be out of sync with the URL: i.e. a submit from step 1 will load step 2, which will show the view from step 1. This is likely going to create confusion for the users.

If anyone does have any nice solutions for what I can only assume must be a pretty common problem, I'd love to hear them. Other solutions I've found here seem to fall into one of the above two answers, neither of which will work for me.

1
  • 1
    try TempData["Step2"] = model; Commented Jul 10, 2014 at 6:56

1 Answer 1

2

Lets say you class structure is like this...

public class MyViewModel
{
    public class Step1 { get; set;}
    public class Step2 { get; set;}
    public class Step3 { get; set;}
    public class Step4 { get; set;}
}

You can just validate part of your model and redirect the user

public ActionResult Step2(MyViewModel model)
{

    //Validate the first step
    if(TryValidateModel(model.Step1)
    {
       //The details entered in step 1 are validate to move on to step 2
       return View("Step2", model); 
    }

    //Failed validation redirect to form one and display the errors

    return RedirectToAction("Step1", model)


}

Hope this helps

Sign up to request clarification or add additional context in comments.

7 Comments

Adding an if-condition to select the view depending on the ModelState. This is problematic because it means the view will be out of sync with the URL: i.e. a submit from step 1 will load step 2, which will show the view from step 1. This is likely going to create confusion for the users.
@ArijitMukherjee actually he does seem to have avoided this by redirecting instead of just showing a different view.
@heymega I'm just leaving the office so I'll try this out tomorrow and let you know how it goes. Thanks!
@heymega unfortunately I can't get this to work - redirecting isn't sending the model data with it. :(
@gnack Is having a seperate url for each form step that important to you? I find its more common these days to have one url and dynamically load new content using partialviews and ajax
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.