2013-05-13 232 views
14

我想使用視圖模型顯示insted域模型。我想定製一個屬性來顯示,我應該怎麼做?是否使用AutoMapper進行顯示是一個好習慣?通過AutoMapper將映射域模型映射到視圖模型

下面是代碼示例:

public class BookController : BaseController 
    { 
     private IBookService bookService; 

     public BookController(IBookService bookService) 
     { 
      this.bookService = bookService; 
     } 

     public ActionResult Details(int id) 
     { 
      var book = bookService.GetBookById(id); 

      return View(Mapper.Map<BookView>(book)); 
     } 
} 

    public class Book 
    {   
     public virtual int Id { get; set; } 
     public virtual string Name { get; set; } 
    } 

    public class BookView 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

如果我用另一種方式,我可以自定義任何屬性,象下面這樣:

public ActionResult Details(int id) 
     { 
      var book = bookService.GetBookById(id); 

      return View(new BookView(book)); 
     } 

    public class BookView 
    { 
     public BookView(Book book){ 
     Name = book.Name +" Decorated"; 
     } 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

我應該怎樣做呢?是否使用AutoMapper進行顯示是一個好習慣?下面

更新

它似乎在方案中使用automapper是比較合適的。例如,將視圖模型映射到如下的域模型。有什麼意見?

[HttpPost] 
    public ActionResult Create(BookView bookView) 
    { 
     try 
     { 
      var book = Mapper.Map<Book>(bookView); //this is wrong 

      bookService.SaveOrUpdate(book); 

      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

更新2

對於通過視圖模型複雜定製顯示,我不想使用automapper映射顯示邏輯,假設automapper可以映射它。因爲它混合了不同的目的。例如:

Mapper.CreateMap<Book, BookView>() 
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name + " this is for display purpose")); 

但是,使用下面的手動映射似乎很直觀。從Jimmy Bogard

public BookView(Book book){ 
    //mapping here 
} 

更新3

報價:

我認爲使用AutoMapper因爲你不希望使用「=」 運營商是有點懶。相反,我們用它來扁平化和重塑, 優化目標類型的環境。請記住,我 原動機AutoMapper是:

啓用保護從映射其他層領域層到 DTO的

感謝@AndrewWhitaker的鏈接

+2

每次更新2,它是如何混合不同的目的? ViewModel的目的不是顯示域模型嗎? Automapper只是完成這一任務的工具。 – 2013-05-13 20:32:56

+0

它與其他映射比較,例如domain到dto,這不是顯示,更可能是乾淨的。 – Pingpong 2013-05-13 20:39:29

+0

您可以爲域' - >'DTO創建一個完全不同的映射。此外,你不應該使用AutoMapper從任何東西映射到域。 – 2013-05-13 20:40:52

回答

18

這是一個很好的使用情況AutoMapper(我在許多成功的項目中廣泛使用了它)。一般來說,你做而不是想要向你的視圖公開域實體(在MVC中,這將直接暴露你的模型到你的視圖,這是不正確的)。

您不需要域實體和視圖模型之間的1-1映射。您可以讓它們看起來完全不同,並在您的CreateMap<>呼叫中自定義映射。要使用你的例子:

Mapper.CreateMap<Book, BookView>() 
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name + " Decorated")); 

最壞的情況,你可以拋棄automapper複雜的情況下,可以使用自定義類型解析與automapper來完成這項工作。

實際上,this is how Jimmy Bogard (the author) recommends using AutoMapper。他特別提到了從域實體到ASP.NET MVC ViewModel的映射,以用於強類型視圖。

另一個優點是您可以單元測試您的映射配置文件。這樣,如果最終出現ViewModel和Model之間的不匹配,您將得到一個失敗的單元測試。

更新:

我想你加入到使用AutoMapper映射從域模型的ViewModels你的問題進一步支持報價:

相反,我們用它來拉平和重塑,優化對於目標類型的環境。

所以在我的例子中,你肯定會是優化目標類型的環境(在這種情況下圖)。

而且每次我在上面你引用鏈接應該是使用automapper映射域,從只有。考慮到這一點,您必須編寫一些邏輯來創建/更新您從視圖中收到的域實體。請記住,控制器操作不應直接採用域實體(不應該信任直接來自視圖的數據 - 讓模型確定域實體是否有效)。

+1

根據您的更新(有幫助),是否有任何示例或鏈接將視圖模型轉換爲領域模型,視圖模型驗證? – Pingpong 2013-05-13 20:56:52

+0

我不明白你的最後一段。你的意思是我們不應該使用ViewModel的automapper映射到域(POCO)?如果是,如何將用戶輸入(View)保存到數據庫(Model)?通過做手動映射? – Willy 2014-04-21 06:31:42

+0

@Willy:是的,通過手動映射。這個想法是,域名太重要了,不能自動映射。 – 2014-04-21 13:43:12

相關問題