我知道它并不能真正回答您的问题,而只是为了扩展我的评论:-
听起来你有类似的东西: -
public class MyModel
{
[Required]
public string Foo { get; set; } // Populated in step 1
[Required]
public string Bar { get; set; } // Populated in step 2
}
您在发布第 1 步时遇到问题,因为用户尚未输入值Bar
,所以有一个ModelStateError
.
我首选的解决方案,而不是试图搞乱你的持久性模型的验证,将你的 View 实现与你的 Model 实现分离,每个向导步骤都有一个 ViewModel,例如:-
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; }
}
您的控制器操作如下所示:-
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);
}
您的 StepOne 视图类似于:-
@model StepOneModel
@using (html.BeginForm()) {
@html.EditorFor(x => x.Foo);
}
您的 StepTwo 视图类似于:-
@model StepTwoModel
@using (html.BeginForm("StepTwo")) {
@html.HiddenFor(x => x.StepOne);
@html.EditorFor(x => x.Bar);
}
与仅关闭模型验证相比的主要优点是,您可以将当前步骤的验证要求放在 ViewModel 上 - 您可以确保第一步中的所有值都有效,然后再进行第二步。
如果您想要一种更 RESTful 的方法(您的控制器不关心数据来自向导样式的视图),另一种流行的解决方案是将每个步骤包装在 <div> 客户端并使用 javascript 隐藏/显示他们随着用户的进步。
如果您的模型需要在步骤之间保持不变,那么您需要考虑模型上的 ValidationAttributes 以及它们的含义。如果您已使用 注释User.DateOfBirth
,Required
但您需要能够在填充它的步骤之前将其持久化,那么实际上User.DateOfBirth
不需要(例如,EF CodeFirst 不能使列 NOT NULL,因为我们需要能够持久化同时为空值)。您需要进行一些条件验证(例如IValidatableObject、MvcFoolproof、Fluent Validation),以便稍后验证您的完整模型。