这是一个非常普遍的问题。
第一个问题是您是否同意通常形式 B 通常更好?
我唯一不使用表格 B的时候是我上传文件的时候。否则,我不相信任何人都应该需要使用Form A。我认为人们使用Form A的原因是对 ASP.Net 版本的 MVC 的能力缺乏了解。
其次,如果使用 Form B,那么装饰器类型验证似乎需要在 ViewModel 中。
排序/它取决于。我给你举个例子:
public IValidateUserName
{
[Required]
string UserName { get; set; }
}
public UserModel
{
string UserName { get; set; }
}
[MetadataType(typeof(IValidateUserName))]
public UserValiationModel : UserModel
{
}
验证装饰器位于接口中。我在派生类上使用 MetadataType 来验证派生类型。我个人喜欢这种做法,因为它允许可重复使用的验证,并且 MetadataType/Validation 不是 ASP.NET 核心功能的一部分,因此它可以在 ASP.Net (MVC) 应用程序之外使用。
在 ViewModels 中嵌入实体是否有优势..
是的,我尽我最大的努力从不将基本模型传递给视图。这是我不做的一个例子:
public class person { public Color FavoriteColor { get; set; } }
ActionResult Details()
{
Person model = new Person();
return this.View(model);
}
当您想将更多数据传递给您的视图(对于部分或布局数据)时会发生什么?大多数情况下,该信息与 Person 无关,因此将其添加到 Person 模型是没有意义的。相反,我的模型通常看起来像:
public class DetailsPersonViewModel()
{
public Person Person { get; set; }
}
public ActionResult Details()
{
DetailsPersonViewModel model = new DetailsPersonViewModel();
model.Person = new Person();
return this.View(model);
}
现在,我可以添加DetailsPersonViewModel
该视图所需的数据,超出了 Person 知道的范围。例如,假设这将显示一个包含所有颜色的 for 供 Person 选择收藏夹。所有可能的颜色都不是人的一部分,也不应该是人模型的一部分,所以我将它们添加到 DetailPersonViewModel。
public class DetailsPersonViewModel()
{
public Person Person { get; set; }
public IEnumerable<Color> Colors { get; set; }
}
..并仅在实体级别进行验证?
System.ComponentModel.DataAnnotations
并非旨在验证属性的属性,因此请执行以下操作:
public class DetailsPersonViewModel()
{
[Required(property="FavoriteColor")]
public Person Person { get; set; }
}
不存在也没有意义。为什么 ViewModel 不应该包含对需要验证的实体的验证。
如果没有默认构造函数,则此编辑操作将失败,您必须使用第一种方法。
正确,但是为什么 ViewModel 中的 ViewModel 或 Entity 没有无参数构造函数?听起来像是一个糟糕的设计,即使对此有一些要求,也可以通过 ModelBinding 轻松解决。这是一个例子:
// Lets say that this person class requires
// a Guid for a constructor for some reason
public class Person
{
public Person(Guid id){ }
public FirstName { get; set; }
}
public class PersonEditViewModel
{
public Person Person { get; set; }
}
public ActionResult Edit()
{
PersonEditViewModel model = new PersonEditViewModel();
model.Person = new Person(guidFromSomeWhere);
return this.View(PersonEditViewModel);
}
//View
@Html.EditFor(m => m.Person.FirstName)
//Generated Html
<input type="Text" name="Person.FirstName" />
现在我们有了一个用户可以输入新名字的表单。我们如何取回这个构造函数中的值?很简单,ModelBinder 不关心它绑定到什么模型,它只是将 HTTP 值绑定到匹配的类属性。
[MetadataType(typeof(IPersonValidation))]
public class UpdatePerson
{
public FirstName { get; set; }
}
public class PersonUpdateViewModel
{
public UpdatePerson Person { get; set; }
}
[HttpPost]
public ActionResult Edit(PersonUpdateViewModel model)
{
// the model contains a .Person with a .FirstName of the input Text box
// the ModelBinder is simply populating the parameter with the values
// pass via Query, Forms, etc
// Validate Model
// AutoMap it or or whatever
// return a view
}