Just trying to use MVCWizard.Wizard from NuGet as part of a multipage Wizard UI.
I have some “parent” model class, with “child” classes as subsections e.g.
public class MainModel
{
public virtual int MainModelId { get; set; }
public virtual PersonalDetails CustomerPersonalDetails { get; set; }
public virtual AddressDetails CustomerAddressDetails{ get; set; }
public virtual FinanceDetails CustomerFinanceDetails{ get; set; }
}
Through trial and error, I’ve found that to use MVCWizard.Wizard, I have to create a “WizardManager” per subsection of pages I’d like to display (so one WizardManager, controller, partial views etc. for CustomerPersonalDetails, one for CustomerAddressDetails and so on..)
..so far so good..
Creating the controller for each subsection inherits from WizardController T, where T is the model. What I’d like to do is code the controller each subsection uses to accept the MainModel in its entirity, and from there just pass MainModel.Child to each partialview as required (the way the MVCWizard.Wizard seems to require)
Doing it this way, it all compiles ok but in use, navigating back and forth between the wizard pages (partial views) the data in base.Wizard().WizardModel is getting wiped out.
I found, that to get it to retain data in the Base.Wizard().WizardModel when navigating back and forth, I have to explicitly specify the child class type for each WizardManager..
So.. (Controller)
public MyController : WizardManager < MainModel >...
public PartialViewResult SubsectionPage1(MainModel mdl)..
(View)
@model MainModel
CustName: @Html.TextBoxFor(m => m.CustomerPersonalDetails.CustName)
..looks like it works, but data isn’t retained.. however..
(Controller)
public MyController : WizardManager< PersonalDetails >...
public PartialViewResult SubsectionPage1(PersonalDetails details)..
(View)
@model PersonalDetails
CustName: @Html.TextBoxFor(m => m.CustName)
Works just fine… is there something I’m missing why the MVCWizard.Wizard can’t seem to handle “complex” models which hold one or more “child” types? Ultimately I can code it so I pass these smaller models to the WizardManager and then combine and map them across to my domain model before persisting to the datastore, but I’d be grateful for an explanation..
* EDIT *
Ok, I’ve dug around a bit more and that initial model binding should work just fine within most normal circumstances. But when using MVCWizard.Wizard, the issue seems to be with the “EnableSimpleMerge” feature of the MVCWizard.Wizard. Its used during the page navigation and there seems to be an issue with how that merge function uses reflection to discover the properies within the model. From my initial look, it doesn’t appear to be coded to recurse through and “discover” child objects within a more complex model structure..
private void Merge(T wizard, T model)
{
foreach (PropertyInfo info in model.GetType().GetProperties())
{
object obj2 = info.GetGetMethod().Invoke(model, null);
if (obj2 != null)
{
wizard.GetType().GetProperty(info.Name).GetSetMethod().Invoke(wizard, new object[] { obj2 });
}
}
foreach (FieldInfo info3 in model.GetType().GetFields())
{
object obj3 = info3.GetValue(model);
if (obj3 != null)
{
wizard.GetType().GetField(info3.Name).SetValue(wizard, obj3);
}
}
}
(See comment above 🙂
A more detailed Merge method needed to be written using indepth property reflection