Reputation: 4809
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
Upvotes: 3
Views: 589
Reputation: 4809
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);
Upvotes: 1
Reputation: 5427
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.
Upvotes: 0
Reputation: 26648
Use session to persist object between requests.
Session["SuperWizard"] = wizard
Upvotes: 1