Вопрос

I am trying to implement wizard functionality in my forms using .NET MVC. I came across a method of achieving this by Darin Dimitrov. Basically he has a wizard view model, which contains a list of ISteps. Each step has it's own properties and validation.

He serializes the wizard on the view (as a kind of view state) and then posts that and the current step up to the controller. So each step of the wizard, you validate only that step. If it's successful, increment the current step and repeat.

For the most part - this works quite nicely. However I have come across a problem when validating the individual steps, as some of my steps are dependant on previously submitted values for their validation.

So, I need to add a way to allow the individual wizard steps to access previous steps.

The way I decided to go about this, is to include the wizard on the step.

public interface IWizardStep
{
    WizardViewModel Wizard { get; set; }
}

And then in the model binder Darin provided, add an override for BindModel

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    var step = (IStepViewModel)base.BindModel(controllerContext, bindingContext);
    step.Wizard = (WizardViewModel)serializer.Deserialize(controllerContext.HttpContext.Request.Form["wizard"], SerializationMode.Signed);
    return step;
}

This seems to work, however in my controller I have a ModelStateError:

The parameter conversion from type 'System.String' to type 'Wizard' failed because no type converter can convert between these types.

I assume this is due to the fact that the model binder is trying to bind recursively?

Does anyone know how I could solve this? Or - am I even approaching this correctly? Is there a better way to do this?

I have put all the above is a basic sample project to illustrate the problem I am having.

Это было полезно?

Решение 2

So I never got to the bottom of why this didn't work but decided to save myself the headache and save the wizard in session, rather than serializing and posting it back every step. That way, I can easily get the wizard in the Validate(ValidationContext) method of the view models. Seems to work well.

Другие советы

Add this to your HomeController as line 18...

ModelState.Remove("Wizard");

What you have should work, but a better approach may be to add all your step's properties to a single model class, then use validation groups for each step...

https://nuget.org/packages/Mvc3ValidationGroups

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top