2011-09-01 44 views
4

我一直在开发一个使用asp.net mvc和nhibernate的web应用程序。我试图遵循一些DDD原则和Asp.Net MVC的最佳实践。我的问题是关于使用VIewModels清理POST。为了说明我的问题,看在我的域模型这个实体:ViewModel POST和DomainModel验证

[Validator(typeof(EntityValidator))] 
public class MyEntity { 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual string Email { get; set; } 
    public virtual decimal UnitPrice { get; set; } 
    public virtual Category Category { get; set; } 

    public MyEntity() { } 
} 

它与NHibernate映射和工作正常。为了验证,我用流利的验证,我有这个类:

public class EntityValidator : AbstractValidator<MyEntity> 
{ 
    protected IEntityRepository EntityRepository { get; set; } 
    public EntityValidator(IEntityRepository entityRepository) { // injected by a IoC Container 
     this.EntityRepository = entityRepository; 

     RuleFor(x => x.Name).NotEmpty(); 
     RuleFor(x => x.UnitPrice).GreaterThan(0); 
     RuleFor(x => x.Category).NotNull(); 
     RuleFor(x => x.Email).NotEmpty().EmailAddress().Must((entity, email) => EntityRepository.ExisteEmail(entity.Email)); 
    } 
} 

我preffer使用流利的验证比数据注释,因为它更灵活,正常工作与Asp.Net MVC。它的配置和工作正常。所以,我有这样的视图模型:

public class EntityViewModel { 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Email { get; set; } 
    public decimal UnitPrice { get; set; } 
    public int IdCategory { get; set; } 
} 

现在,我试图做一个视图模型,使我的实体的清理POST在某些操作(如INSERT,UPDATE),因为我使用NHibernate。我

不知道是否正确创建viewmodel的验证,因为我有我自己的实体,所以,我该怎么做?你是如何做

要发布您的实体上的行动来坚持它?如何验证它并在MVC的ModelState上发布错误?

我想看看如何做到这一点的代码,如果可能的话。

谢谢大家!

回答

11

不知道是否为viewmodel创建验证是正确的,因为 我有我自己的实体,所以,我该怎么做?

我个人为我的视图模型定义了流利的验证器。它们包含对所需属性,格式等简单事物的验证规则......以便可以直接在视图上处理这些验证。

域模型也可以包含验证,但那些将是业务验证。这里有一个POST控制器动作的通常流程:

[HttpPost] 
public ActionResult Insert(UpdateViewModel viewModel) 
{ 
    if (!ModelState.IsValid) 
    { 
     // the surface validation on our view model failed => redisplay the view so 
     // that the user can fix errors 
     return View(viewModel); 
    } 

    // at this stage the view model is valid => we can map it back to a domain model 
    // I use AutoMapper for this: 
    var domainModel = Mapper.Map<UpdateViewModel, DomainViewModel>(viewModel); 

    // then we pass the domain model to the service layer for processing: 
    string error; 
    if (!_service.Insert(domainModel, out error)) 
    { 
     // something wrong happened on the service layer 
     ModelState.AddModelError("key", error); 
     return View(viewModel); 
    } 

    // everything went fine 
    return RedirectToAction("Success"); 
} 

你可以从这个例子中我们的委托加工业务层看到的。实现此服务的方式对ASP.NET MVC应用程序没有任何兴趣或意义。您可能正在使用NHibernate,Entitiy Framework,可以调用其他一些服务,任何您能想到的,我们应该关心的一切就是我们正在处理我们的域模型,准备好进行处理,并向我们报告错误(如果有的话)。你在服务层上处理验证的方式对于ASP.NET MVC应用程序来说也没什么重要性=>你可以使用Castle Validator,Fluent Validation,Data Annotations,无论如何......

只要映射关注如果您正在更新现有的域实体,则可能会有额外的步骤。在这种情况下,视图模型可能不包含域模型的所有属性,因为在此特定视图中,例如,我们只允许编辑一些属性。在这种情况下,流程将如下所示:

// Fetch the original domain model we want to update 
var domainModel = _service.Get(viewModel.Id); 

// Update only the properties that are present on the view: 
Mapper.Map<UpdateViewModel, DomainViewModel>(viewModel, domainModel); 

// Pass to the service layer for processing: 
string error; 
if (!_service.Update(domainModel, out error)) 
{ 
    ... 
} 
+0

感谢Darin,我也一直在使用automapper,但现在我有两个adicional问题。 1)我已经在第一个代码中看到,您在ModelState中添加了一个名为“Key”的键,您将如何在View上显示它?2)如果我们使用automapper,如何配置automapper将IdCategory转换为Category对象?非常感谢你! –

+0

@Felipe,关于你的第一个问题,键应该用你想突出显示的字段的名称替换,或者如果它不存在,你仍然可以使用ValidationSummary助手来显示所有错误,或者你可以从模型状态错误并将其显示在视图上。关于你的第二个问题,我没有看到你如何将一个整数转换为一个Category对象。不应该你的视图模型有这个类别的附加属性而不是一个单一的ID? –

+0

我一直在使用ViewBag为用户创建一个类别组合,选择类别并传递类别的标识以发布操作。我的域模型在属性中使用了一个Category对象。那么,我不知道这是不是一个好的approuch,但你建议如何使用这样的复杂属性?我认为原始类型对ViewModels更好。 –