【发布时间】:2012-12-26 04:27:29
【问题描述】:
我有一个大型模型(大型我的意思是模型类包含很多字段/属性,并且每个都至少有一个验证属性(例如Required、MaxLength、MinLength 等))。我不想创建一个包含大量输入的视图来让用户用数据填充模型,我想创建几个视图,用户将在其中填充部分模型字段并进入下一步(某种“wizard”)。在步骤之间重定向时,我将未填充的模型对象存储在 Session 中。如下所示:
型号:
public class ModelClass
{
[MaxLength(100)] ...
public string Prop1{get;set;}
[MaxLength(100)] ...
public string Prop2{get;set;}
...
[Required][MaxLength(100)] ...
public string Prop20{get;set;}
}
控制器:
[HttpPost]
public ActionResult Step1(ModelClass postedModel)
{
// user posts only for example Prop1 and Prop2
// so while submit I have completly emty model object
// but with filled Prop1 and Prop2
// I pass those two values to Session["model"]
var originalModel = Session["model"] as ModelClass ?? new ModelClass();
originalModel.Prop1 = postedModel.Prop1;
originalModel.Prop2 = postedModel.Prop2;
Session["model"] = originalModel;
// and return next step view
return View("Step2");
}
[HttpPost]
public ActionResult Step2(ModelClass postedModel)
{
// Analogically the same
// I have posted only Prop3 and Prop4
var originalModel = Session["model"] as ModelClass;
if (originalModel!=null)
{
originalModel.Prop3 = postedModel.Prop3;
originalModel.Prop4 = postedModel.Prop4;
Session["model"] = originalModel;
// return next step view
return View("Step3");
}
return View("SomeErrorViewIfSessionBrokesSomeHow")
}
Step1 视图只有Prop1 和Prop2 的输入,Step2 视图包含Prop3 和Prop4 等的输入。
但事情是这样的
当用户打开时,例如,第 1 步,并用长度超过 100 个字符的值填充 Prop1,客户端验证工作正常。但是,当然,我必须在控制器的服务器端验证这个值。如果我有完整的模型,我会执行以下操作:
if(!ModelState.IsValid) return View("the same view with the same model object");
所以用户必须再次填写表格并更正。
但是在第 1 步用户只填写了 20 个属性,我需要验证它们。我不能使用ModelState.IsValid,因为模型状态将无效。如您所见,Prop20 标记有[Required] 属性,当用户提交Prop1 和Prop2 时,Prop20 为空,这就是ModelState 无效的原因。当然,我可以允许用户进入第 2 步,填写所有步骤并仅在最后一步验证模型状态,但我不想让用户进入第 2 步,如果他填写的第 1 步不正确。我希望在控制器中进行此验证。 所以问题是:
如何仅验证模型的一部分?如何验证只有部分模型属性与其验证属性匹配?
【问题讨论】:
-
您可以为每个步骤创建不同的视图模型,这可能是一个单独的视图。像 ProductStep1ViewModel 和 ProductStep1View,但我会比这更好地命名它们。
-
@NickBray,ModelClass 是视图模型类,从原始模型映射,所以如果我创建 ModelClass 作为其他特定步骤类的组合,我将不得不为映射器添加大约 40 个映射规则来映射这些模型类,这将是一堆代码。我已经考虑过了,但感谢您的建议。
-
@DmytroTsiniavsky 您可以改用Value Injecter 之类的东西来避免必须明确设置映射规则。
标签: c# asp.net-mvc model-view-controller model