3

I have a multi step wizard that I have pieced together from useful posts like this its got a few problems however.. here's the setup I have

[Serializable]
public class WizardModel
{

    public IList<IStepViewModel> Steps 
    { 
        get; 
        set; 
    }
    public void Initialize()
    {
        Steps = typeof(IStepViewModel)
            .Assembly
            .GetTypes()
            .Where(t => !t.IsAbstract && typeof(IStepViewModel).IsAssignableFrom(t))
            .Select(t => (IStepViewModel)Activator.CreateInstance(t))
            .ToList();
    }

}

My Wizard controller

    public ActionResult Index()
    {
        var wizard = new WizardModel();     
        wizard.Initialize();
        //this populates wizard.Steps with 3 rows of IStepViewModel
        return View(rollover);       
    }

    [HttpPost]
    public ActionResult Index(
        [Deserialize] WizardModel wizard,
        IStepViewModel step
        )
    {
        //but when this runs wizard is a new class not the one previously Initialized
         wizard.Steps[rollover.CurrentStepIndex] = step;
    }

My issue is that wizard is a fresh object each time its posted - when I'm trying to pass the same model around populating each step in the array. Does anyone have an idea of where I'm going wrong here?

Here's the ModelBinding

Global.asax

   ModelBinders.Binders.Add(typeof(IStepViewModel), new FormTest.Models.StepViewModelBinder());

and

  public class StepViewModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var stepTypeValue = bindingContext.ValueProvider.GetValue("StepType");
        var stepType = Type.GetType((string)stepTypeValue.ConvertTo(typeof(string)), true);
        var step = Activator.CreateInstance(stepType);
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => step, stepType);
        return step;
    }
}

Thanks in advance

Edit:

if I understand, an alternative to using session is to serialize my model (below), and deserialize in my controller action. I set the values on the model that were posted to the controller .. which gets returned to the view for the next step and so on.. until the final step when I have a wizard model populated with each step.

Index.cshtml

   @using (Html.BeginForm())
   {
         @Html.Serialize("wizard", Model);  
         etc...
   }   

so the wizard parameter that I try deserialize here

    [Deserialize] WizardModel wizard,

comes through the controller post action is a new object each time - I would like to see if this is possible without using Session but @Html.Serialize? and Post

Community
  • 1
  • 1
MikeW
  • 4,749
  • 9
  • 42
  • 83

3 Answers3

1

Use session to persist object between requests.

Session["SuperWizard"] = wizard
Mike Chaliy
  • 25,801
  • 18
  • 67
  • 105
  • Thanks for the response. I'm trying to figure out if this is possible with @Html.Serialize ? I added some more info at top. – MikeW Jun 01 '12 at 14:42
1

This code did the job in the end. Inside the controller action,

        var serializer = new MvcSerializer();
        var value = Request["wizard"];
        var wizard = (WizardModel)serializer.Deserialize(value, SerializationMode.Signed);

And in the view

    @Html.Serialize("wizard", Model, SerializationMode.Signed);   
MikeW
  • 4,749
  • 9
  • 42
  • 83
0

Model binding is used to bind POSTed form values to new objects. so if you want the exact same object, like Mike suggests, you will need to use Session or some other persistent store. however, if your objects can be recreated each time, then you just need to put enough data in the form so that when it gets POSTed, everything can be re-data-bound to get the same values in a new object.

Dave Thieben
  • 5,388
  • 2
  • 28
  • 38
  • Thanks for that, the situation you describe where enough data is put into the post is what I want to achieve. Basically using @Html.Serialize of the model, I updated the question with more info. – MikeW Jun 01 '12 at 14:43