1

I have been searching high/low on the GooglePlex and here for a sample MVC3 Wizard (multi-step) that does NOT invlove the clientsidevalidation elements of MVC3 (and jQuery). I have seen at least one detailed explanation of some elements here: multi-step registration process issues in asp.net mvc (splitted viewmodels, single model), but I have not been able to get it to work properly.

Being new to MVC3 and programming in general, I suspect its my experience level that's preventing me from getting that to work.

Anyhow, any guidance to non-Jquery MVC3 wizard samples would be great. Thank you in advance.

Community
  • 1
  • 1
M E Moriarty
  • 231
  • 1
  • 6
  • 15
  • 1
    Can you elaborate on the "no jQuery" requirement? Is any JavaScript allowed? Are any JavaScript libraries or frameworks allowed? – David Nov 08 '11 at 17:38
  • @David Thanks for the quick response. I am using OrchardCMS v1.3 and ClientSideValidation is not currently workable in that context. Additionally, I am using some dynamic elements and my understanding is that ClientSideValidation in that context does not work well (see http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/); although, given my first limitation the workaround there does not help. – M E Moriarty Nov 08 '11 at 17:43
  • N.B.: The elaborate solution at http://stackoverflow.com/questions/6402628/multi-step-registration-process-issues-in-asp-net-mvc-splitted-viewmodels-sing?answertab=votes#tab-top has a comment about it not being sound practice for 9 "steps" to persist that much info. For my purposes that too might be a problem, as I have broken up my form into at least 7 steps (although the last one is a confirmation). – M E Moriarty Nov 08 '11 at 17:52

2 Answers2

4

I would do something like this if jQuery/javascript is not allowed to be used

  1. Create a controller for the wizard
  2. Create a model that contains all fields that the wizard will set.
  3. Create one Action per wizard page, all actions should use the same model
  4. Create a final action that saves everything to the DB.
jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • It seems to me that this wouldn't work, since you won't use all data in a Action, when you post back to the controller you will loose all fields that you didn't used. So you either have to use the session or use hidden fields (creating some sort of viewstate). Is that true? – Bruno Brant May 20 '13 at 00:24
  • Thanks, I just added a div and added all elements there. It worked like a charm. Thanks... – Bruno Brant May 20 '13 at 22:26
3

Jonas is absolutely right. A little further breakdown below.

public class MyModel
{
     [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     public Guid Id { get; set };
     public string StepOneData { get; set; }
     public string StepTwoData { get; set; }
}

The above coed is stupid simple so replace your fields in there. Next we start with a simple action that initiates our wizard.

    public ActionResult WizardStep1()
    {
        return View(new MyModel());
    }

This calls the view "WizardStep1.cshtml (if using razor that is). You can use the create template wizard if you want. We will just be redirecting the post to a different action.

<WizardStep1.cshtml>
@using (Html.BeginForm("WizardStep2", "MyWizard")) {

The thing of note is that we will be posting this to a different action; the WizardStep2 action

    [HttpPost]
    public ActionResult WizardStep2(MyModel myModel)
    {
        return ModelState.IsValid ? View(myModel) : View("WizardStep1", myModel);
    }

In this action we check if our model is valid, and if so we send it to our WizardStep2.cshtml view else we send it back to step one with the validation errors. In each step we send it to the next step, validate that step and move on. Now some savvy developers might say well we can't move between steps such as this if we use [Required] attributes or other data annotations between steps. And you would be right, so remove the errors on items that are yet to be checked. like below.

    [HttpPost]
    public ActionResult WizardStep3(MyModel myModel)
    {
        foreach (var error in ModelState["StepTwoData"].Errors)
        {
            ModelState["StepTwoData"].Errors.Remove(error);
        }

Finally we would save the model once to the data store. This also prevents a user that starts a wizard but doesn't finish it not to save incomplete data to the database.

I hope you find this method of implementing a wizard much easier to use and maintain than any of the previously mentioned methods.

Thanks for reading.

Darroll
  • 438
  • 4
  • 10
  • How would we handle the situation where the wizard is not a simple next, next, next, but has logic to decide what view to display next based on the answers fro the previous view? Thanks – Sam Delaney Sep 25 '12 at 14:33
  • 1
    This begs for a complete sample. ;) @SamDelaney, you might try and do some if/else logic in the controller (if radio button 1 on step 1 is yes, then do this, else do this). – REMESQ Jan 10 '13 at 19:25