将DTO绑定到域模型的位置

时间:2012-09-25 14:19:31

标签: asp.net-mvc architecture automapper dto domain-model

我开始使用AutoMapper并且出现了一些疑问。 将dto映射到域模型的正确方法在哪里? 我这样做:

DTO:

public class PersonInsert
{
    [Required]
    public string Name { get; set; }
    public string LastName { get; set; }
}

动作:

[HttpPost]
public ActionResult Insert(PersonInsert personInsert)
{
    if (ModelState.IsValid)
    {
        new PersonService().Insert(personInsert);

        return RedirectToAction("Insert");
    }

    return View("Insert");
}

服务:

public class PersonService
{
    public int Insert(PersonInsert personInsert)
    {
        var person = Mapper.Map<PersonInsert, Person>(personInsert);

        return new PersonRepository().Insert(person);
    }
}

存储库:

 public class PersonRepository
    {
        internal int Insert(Person person)
        {
            _db.Person.Add(person);
            _db.SaveChanges();

            return person.Id;
        }
     }

那么,这是正确的吗?我的服务应该知道域名吗?或者我应该只在存储库中进行绑定?在DTO中使用[必需]是否正确?

5 个答案:

答案 0 :(得分:4)

我几乎不会从DTO创建实体 - 我在下面解释原因。我会使用一个请求对象来允许工厂方法来构建实体:

请求:

public class InsertPersonRequest
{ 
    [Required] 
    public string Name { get; set; } 
    public string LastName { get; set; } 
} 

动作:

[HttpPost] 
public ActionResult Insert(InsertPersonViewModel viewModel) 
{ 
    if (ModelState.IsValid) 
    { 
        InsertPersonRequest request = InsertPersonViewModelMapper.CreateRequestFrom(viewModel);
        new PersonService().Insert(request ); 
        return RedirectToAction("Insert"); 
    } 

    return View("Insert"); 
} 

服务:

public class PersonService 
{ 
    public int Insert(InsertPersonRequest request) 
    { 
        var person = Person.Create(request.name, request.LastName);          
        return new PersonRepository().Insert(person); 
    } 
} 

存储库保持不变。

这样,创建Person的所有逻辑都位于person的Factory方法中,因此业务逻辑被封装在域派生字段,默认字段等中。

您正在做的问题是必须在UI中创建DTO,然后所有字段都映射到实体 - 这是业务逻辑渗透到服务层的可靠方法,用户界面,或任何不应该的用户界面。

请再次阅读 - 这是我一次又一次看到的一个非常严重的错误。

但是,我会在服务层中使用AutoMapper来返回DTO:

服务:

public class PersonService 
{ 
    public PersonDto GetById(intid) 
    { 
        var person = new PersonRepository().GetById(id);
        var personDto = Mapper.Map<Person, PersonDto>(person); 
        return personDto
    } 
} 

答案 1 :(得分:2)

  

这是对的吗?

我个人认为让您的服务进行映射没有任何问题

  

在DTO中使用[Required]是否正确

不,DTO应该没有任何业务逻辑。它们应该纯粹用于跨应用程序的不同层/层传输数据。

DataAnnotations通常用于ViewModels用于客户端/服务器端验证,因此,我会在您的模型中添加另一个分隔,并为您的ViewModel操作引入Insert,例如

public class PersonViewModel    
{
    [Required]
    public string Name { get; set; }
    public string LastName { get; set; }
}

public class PersonDto
{
    public string Name { get; set; }
    public string LastName { get; set; }
}

动作:

[HttpPost]
public ActionResult Insert(PersonViewModel personViewModel)
{
     if (ModelState.IsValid)
     {
         var personDto = Mapper.Map<PersonViewModel, PersonDto>(personViewModel);
         new PersonService().Insert(personDto);
         ...
      }
      ...
     }
}

服务:

public class PersonService
{
    public int Insert(PersonDto personDto)
    {
        var person = Mapper.Map<PersonDto, Person>(personDto);

        return new PersonRepository().Insert(person);
    }
}

在这种情况下看起来有些过分(考虑到唯一的区别是[Required]属性)。但是,在典型的MVC应用程序中,您需要确保ViewModel与商业模式之间的清晰分离。

答案 2 :(得分:1)

在ASP.NET MVC中,DTO的典型用法是viewmodel的一部分。 Viewmodel是一个将一个到几个DTO组合成一个类的类,用于视图呈现和将值发布回服务器。

您所做的是正确的,没有问题,但数据注释应该驻留在视图模型上,而不是DTO。除非你将DTO称为视图模型,否则就可以了。

请阅读以下有关ASP.NET MVC世界中的模型(域模型)与ViewModel的帖子:

希望这有帮助

答案 3 :(得分:1)

我想说您的PersonService可以被视为您的架构的域层(或域的正上方的应用层)的一部分,而控制器和DTO位于该层之上。这意味着您不应在PersonService签名中引用DTO,而应在此处使用域Person类。所以Mapping代码应该进入Controller。这可确保您的域逻辑不受Web服务合同更改的影响,这可能只是使用PersonService的一种方式。 我还会为您的PersonService引入一个存储库接口,因为PersonService不需要知道具体的数据访问实现。

对于[Required]属性,我没有看到在DTO上出现此问题,因为它只是说明了您的Web服务方法的数据协定。任何调用您的Web服务的人都应遵守此数据协定。当然,这个要求通常也会反映在您的域代码中的某个地方,可能是通过抛出异常等。

答案 4 :(得分:1)

我认为在DTO上进行注释是很好的,例如[必需],MaxLength,Range等。

您的DTO可以来自任何(可能不受信任的)来源(不只是您的网站,而是来自其他端点,WCF服务等)。所有请求都将汇集到您的服务/业务层,因此您需要在执行业务逻辑(简单保护检查)之前验证输入。在DTO上添加注释只是描述执行手头任务所需的输入。传递带注释的对象不符合验证。

但是,我相信您应该验证服务/业务层中的DTO信息是否正确(注释是一种检查此方法的好方法)。

我对这种情况的看法:)。