ViewModel的POST和DomainModel上的验证

时间:2011-09-01 12:29:02

标签: c# asp.net-mvc nhibernate domain-driven-design viewmodel

我一直在使用asp.net mvc和nhibernate开发一个Web应用程序。我正在尝试遵循DDD的一些原则和Asp.Net MVC的最佳实践。我的问题是关于用VIewModel清理POST。为了说明我的问题,请在我的域模型上查看此实体:

[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映射并且工作正常。为了验证,我正在使用Fluent验证,我有这个类:

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));
    }
}

我更倾向于使用Fluent验证而不是数据注释,因为它更灵活,并且可以与Asp.Net MVC一起使用。它配置和工作正常。所以,我有这个ViewModel:

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; }
}

现在,我正在尝试使用ViewModel在某些操作(如INSERT,UPDATE)中清理我的实体,因为我正在使用nhibernate。我

不知道为viewmodel创建验证是否正确,因为我在我的实体上有自己的验证,所以,我该怎么办呢?你过得怎么样?

将您的实体发布给要保留的操作吗?如何验证它并在MVC的ModelState上发布错误?

如果有可能的话,我想看一些如何做的代码。

谢谢大家!

1 个答案:

答案 0 :(得分: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应用程序来说也是不重要的=&gt;你可以使用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))
{
    ...
}