ViewModel的POST和DomainModel上的验证

Fel*_*ani 4 c# nhibernate asp.net-mvc 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() { }
}
Run Code Online (Sandbox Code Playgroud)

它用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));
    }
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用Fluent验证而不是Data Annotations,因为它更灵活,并且可以与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; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

发布您的实体以保持持续的行动?如何验证它并在MVC的ModelState上发布错误?

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

感谢大家!

Dar*_*rov 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");
}
Run Code Online (Sandbox Code Playgroud)

从这个例子中可以看出,我们将处理委托给服务层.实现此服务的方式不符合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))
{
    ...
}
Run Code Online (Sandbox Code Playgroud)