我对如何以最好的asp.net mvc实现DDD原则的方式提出了一些问题。实际上,我想知道,你是如何进行验证的(在viewmodel或model中)?
我有这个DomainModel和ViewModel:
public class Product {
public int Id { get; protected set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Stock { get; set; }
public Category Category { get; set; }
public Supplier Supplier { get; set; }
public string Code { get; set; } // it has to be unique
}
public class ProductViewModel {
public int Id { get; set; }
/* other simple properties */
public int IdCategory { get; set; }
public int IdSupplier { get; set; }
public string Code { get; set; }
}
确定。该模型使用NHibernate进行映射,并且工作正常。我想知道,如果最好为ViewModel或DomainModel创建验证?我的意思是,当我在asp.net mvc的动作上收到ViewModel时,我会验证它,但如果我在viewmodel上添加业务规则,我不会做错吗?我问这个是因为我知道将这些业务验证添加到我的域名会更好,但是我应该在保留之前对我的帖子进行两次验证吗?看看我对asp.net mvc的行动:
[Post]
public ActionResult Update(ProductViewModel viewModel) {
// what kind of validations should I do here?
if (invalid) {
return View(viewModel);
}
// how can I return the errors to my View?
// Is here any best pratice to transform from ViewModel to Domain instance?
Product product = ???
_repository.Save(product);
return RedirectToAction("Index");
}
有人可以通过代码做一个例子吗?
答案 0 :(得分:9)
我会说你应该在两个级别进行验证。在您的视图模型中,您将进行表面验证,例如此字段是必填字段,此字段必须是以下格式;而在您的业务层中,您应该验证业务规则,例如用户名已存在,...
让我们举一个典型的POST动作的示例:
[HttpPost]
public ActionResult Update(ProductViewModel viewModel)
{
if (!ModelState.IsValid)
{
// The view model is invalid => redisplay the view in order
// to show the error messages
return View(viewModel);
}
// at this stage we know that the view model is valid =>
// now we can map it to a domain model that we want to update:
Product product = Repository.GetModel(viewModel.Id);
// I use AutoMapper (http://automapper.org/) to map between
// my domain models and my view models. In this example
// we are updating only the properties of the domain model
// that were part of the view model and that the user is allowed
// to modify in this view => we are merging
Mapper.Map<ProductViewModel, Product>(viewModel, product);
// now we can process the domain model
Repository.Update(product);
return RedirectToAction("Index");
}
如果您想处理域模型错误,则有不同的可能性。我个人喜欢TryXXX
模式:
string errorMessage;
if (!Repository.TryUpdate(product, out errorMessage))
{
// the business validation failed => add the error message to the modelstate
// and redisplay the view
ModelState.AddModelError("", errorMessage);
return View(viewModel);
}
另一种可能性是将ModelState
字典传递给业务层,并让它直接添加模型状态错误。通过这种方式,您可以再次在视图中测试if (!ModelState.IsValid)
,以了解业务层中是否出现问题,并重新显示相同的视图以显示错误消息。
就视图模型中的验证而言,有不同的方法。您可以使用Microsoft的官方方式,即通过验证属性修饰视图模型属性。例如:
public class ProductViewModel
{
[Required]
public string Foo { get; set; }
...
}
我个人不使用这些属性。我发现它们非常有限,特别是当你想要使用依赖属性进行更复杂的验证时等等。出于这个原因,我使用FluentValidation.NET integrates very nicely与ASP.NET MVC,并允许我轻松unit test我的验证规则。
答案 1 :(得分:0)
应用于视图模型的验证规则不一定与域模型的验证规则相同。通常,您检查视图模型是否存在输入错误,并检查域模型是否存在业务规则违规。一些验证规则在两个模型中都是相同的,这很好,因为您的域模型独立于视图模型,反之亦然。