I know it doesn't really answer your question, but just to expand on my comment:-
It sounds like you have something like:-
public class MyModel
{
[Required]
public string Foo { get; set; } // Populated in step 1
[Required]
public string Bar { get; set; } // Populated in step 2
}
You have a problem when you POST step 1 because the user hasn't entered a value for Bar
yet, so there's a ModelStateError
.
My preferred solution, rather than trying to mess around with validation of your persistence model, would be to decouple your View implementation from your Model implementation with a ViewModel for each Wizard step, for example:-
public class MyModel
{
[Required]
public string Foo { get; set; }
[Required]
public string Bar { get; set; }
}
public class StepOneModel
{
[Required]
public string Foo { get; set; }
}
public class StepTwoModel
{
// This really depends on the behaviour you want.
// In this example, the model isn't persisted until
// the last step, but you could equally well persist
// the partial model server-side and just include a
// key in subsequent wizard steps.
[Required]
public StepOneModel StepOne { get; set; }
[Required]
public string Bar { get; set; }
}
Your controller actions look something like:-
public ActionResult StepOne()
{
return View(new StepOneViewModel());
}
[HttpPost]
public ActionResult StepOne(StepOneViewModel model)
{
if(ModelState.IsValid)
{
var stepTwoModel = new StepTwoViewModel ()
{
StepOne = model
};
// Again, there's a bunch of different ways
// you can handle flow between steps, just
// doing it simply here to give an example
return View("StepTwo", model);
}
return View(model);
}
[HttpPost]
public ActionResult StepTwo(StepTwoViewModel model)
{
if (ModelState.IsValid)
{
// You could also add a method to the final ViewModel
// to do this mapping, or use something like AutoMapper
MyModel model = new MyModel()
{
Foo = model.StepOne.Foo
Bar = model.Bar
};
this.Context.MyModels.Add(model);
this.Context.SaveChanges();
}
return View(model);
}
Your StepOne view looks something like:-
@model StepOneModel
@using (html.BeginForm()) {
@html.EditorFor(x => x.Foo);
}
Your StepTwo view looks something like:-
@model StepTwoModel
@using (html.BeginForm("StepTwo")) {
@html.HiddenFor(x => x.StepOne);
@html.EditorFor(x => x.Bar);
}
The major advantage compared to just turning off model validation is that you can put the validation requirements for the current step on your ViewModel - you can ensure that all the values from step one are valid before proceeding to step two.
If you want a more RESTful approach (where your controller doesn't care that the data is coming from a wizard-style view) another popular solution is to wrap each step in a <div> client-side and use javascript to hide/show them as the user progresses.
If your model needs to be persisted between steps, then you'll need to think about the ValidationAttributes on your model, and what they mean. If you've annotated User.DateOfBirth
with Required
, but you need to be able to persist it before the step it gets populated, then in fact User.DateOfBirth
isn't required (e.g. EF CodeFirst can't make the column NOT NULL because we need to be able to persist null values in the meantime). You'll need to do some conditional validation (e.g. IValidatableObject, MvcFoolproof, Fluent Validation) in order to validate your complete model later.