2012-09-25 14 views
2

我開始使用AutoMapper,並且出現了一些疑問。 將dto映射到域模型的正確方法在哪裏? 我這樣做:將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中使用[Required]是否正確?

回答

1

這是正確的嗎?

我個人看不出什麼毛病讓你的服務做的映射

它是正確的DTO使用[Required]

沒有,DTO的應該沒有業務邏輯的任何。它們應該純粹用於跨應用程序的不同層/層傳輸數據。

DataAnnotations通常用在ViewModels爲客戶機/服務器端驗證,因此,我想補充另一種分離到模型中並引入ViewModelInsert動作例如

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與您的業務模型之間保持清晰的分隔。

+0

那麼我能做些什麼[必需的]? asp.net-mvc使用ModelState.IsValid來驗證用戶輸入..我應該避免這種情況,並在serviceLayer中創建一個邏輯驗證? – MuriloKunze

+0

你會在哪裏放置[必填]註釋?在Person模型上? –

+0

@murilokunze看到我更新的答案。 – James

1

在ASP.NET MVC中,DTO的典型用法是作爲viewmodel的一部分。 Viewmodel是一個將一個到幾個DTO合併爲一個類的類,用於視圖呈現和將值發回服務器。

你所做的是正確的,沒有問題,但數據註釋應該駐留在視圖模型而不是DTO上。除非你打電話給你的DTO視圖模型,那麼它很好。

請閱讀以下有關模型(域模型)與ASP中的ViewModel的文章。NET MVC世界:

希望這有助於

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

庫停留在相同。

這種方式創造了個人的所有邏輯都位於人的工廠方法,所以業務邏輯封裝在領域 - 與你是什麼導出字段,默認字段等

問題做的是必須在用戶界面中創建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 
    } 
} 
+0

非常感謝您的回答,但我得到了一個問題:PersonDTO和Person應該有相同的屬性不應該? – MuriloKunze

+0

@murilokunze我會說是的,除非有很好的理由,否則。 –

1

我要說的是,你的PersonService可以看作領域層的一部分(或應用程序層直接在域的上方),而控制器和DTO位於該層之上。這意味着您不應該在PersonService簽名中參考DTO,而應在此處使用域Person類。所以映射代碼應該進入控制器。這可以確保您的域邏輯不受web服務合同更改的影響,這實際上只是使用PersonService的一種方式。 我還將爲您的存儲庫引入一個接口,該接口被注入到PersonService中,因爲PersonService再次不需要知道具體的數據訪問實現。

至於[Required]屬性,我沒有看到在DTO上有這個問題,因爲它只是說明你的web服務方法的數據契約。任何人打電話給你的webservice都應該遵守這個數據合同。當然,這個要求通常也會反映在你的域代碼的某個地方,可能是拋出一個異常等。

+0

謝謝,我沒有創建注入代碼來簡化示例。 – MuriloKunze

1

我認爲在DTO上有註釋是很好的,比如[Required],MaxLength,Range等。

你的DTO可以來自任何(可能不可信的)源(不僅僅是你的網站,而是來自另一個端點,WCF服務等)。所有請求都將彙集到您的服務/業務層,因此您需要在執行業務邏輯之前驗證輸入(簡單的警戒檢查)。在DTO上註釋只是描述了執行手頭任務所需的輸入。傳遞帶有註釋的對象不會影響驗證。

不過,我相信你應該驗證DTO信息是在服務/業務層正確(和註解是檢查這一個很好的方式)。

只是我對這種情況的想法:)