2012-06-10 101 views
0

我希望你能夠幫助我解決我在開發測試ASP.NET MVC應用程序時遇到的Automapper問題。AutoMapper複雜的ViewModel屬性

我已經看了一下,我找不到任何相當像我試圖用嵌套的ViewModels實現的東西。

基本上,我有這2個領域模型...

namespace Test.Domain.Entities 
{ 
    public class Contact 
    { 
     [HiddenInput(DisplayValue = false)] 
     [Key] 
     public int ID { get; set; } 

     public Name Name { get; set; } 

     public string Contact_Landline { get; set; } 

     public string Contact_Mobile { get; set; } 

     [DataType(DataType.EmailAddress)] 
     public string Contact_Email { get; set; } 
    } 
} 

和..

namespace Test.Domain.Entities 
{ 
    public class Name : DisplayableModel 
    { 
     [HiddenInput(DisplayValue = false)] 
     [Key] 
     public int ID { get; set; } 

     public string Name_Forename { get; set; } 

     public string Name_Surname { get; set; } 

     public string GetFullName() 
     { 
      return Name_Forename + ' ' + Name_Surname; 
     } 
    } 
} 

而且我有這些2周的ViewModels ...

namespace Test.WebUI.Models 
{ 
    public class ContactViewModel : 
    { 
     [HiddenInput(DisplayValue = false)] 
     [Key] 
     public int ID { get; set; } 

     public NameViewModel Name { get; set; } 

     public string Contact_Landline { get; set; } 

     public string Contact_Mobile { get; set; } 

     [DataType(DataType.EmailAddress)] 
     public string Contact_Email { get; set; } 
    } 
} 

而且......

namespace Test.WebUI.Models 
{ 
    public class NameViewModel 
    { 
     [HiddenInput(DisplayValue = false)] 
     [Key] 
     public int ID { get; set; } 

     public string Name_Forename { get; set; } 

     public string Name_Surname { get; set; } 
    } 
} 

我想將ContactViewModel返回到我的視圖,並使用名稱屬性填充名稱屬性來填充聯繫人域對象。

我有我的控制器這段代碼...

Mapper.CreateMap<Name, NameViewModel>(); 
Mapper.CreateMap<Contact, ContactViewModel>(); 
var contact = Mapper.Map<Contact, ContactViewModel>(repository.Contact.Where(c => c.ID == id).Single()); 
return View(contact); 

這是我碰到的問題,我的Name屬性永遠不會填充。

我選擇來設計我的應用程序這種方式是因爲我的意見是由定製模型模板,這樣我可以一直呈現NameViewModel對象不重複的代碼,因爲在這個簡單的例子是因爲...

@model Test.WebUI.Models.NameViewModel 

First 
@Model.Name_Forename 
Last 
@Model.Name_Surname 

如果有人能幫我解釋一下如何用AutoMapper填充ContactViewModel的NameViewModel對象,我會非常感激。

謝謝。 吉姆

回答

1

這應該工作開箱如下所示:

public class Name 
{ 
    [HiddenInput(DisplayValue = false)] 
    [Key] 
    public int ID { get; set; } 

    public string Name_Forename { get; set; } 

    public string Name_Surname { get; set; } 

    public string GetFullName() 
    { 
     return Name_Forename + ' ' + Name_Surname; 
    } 
} 


public class Contact 
{ 
    public int ID { get; set; } 

    public Name Name { get; set; } 

    public string Contact_Landline { get; set; } 

    public string Contact_Mobile { get; set; } 

    public string Contact_Email { get; set; } 
} 

public class NameViewModel 
{ 
    [HiddenInput(DisplayValue = false)] 
    [Key] 
    public int ID { get; set; } 

    public string Name_Forename { get; set; } 

    public string Name_Surname { get; set; } 

} 

public class ContactViewModel 
{ 
    [HiddenInput(DisplayValue = false)] 
    [Key] 
    public int ID { get; set; } 

    public NameViewModel Name { get; set; } 

    public string Contact_Landline { get; set; } 

    public string Contact_Mobile { get; set; } 

    [DataType(DataType.EmailAddress)] 
    public string Contact_Email { get; set; } 
} 


class Program 
{ 
    static void Main() 
    { 
     Mapper.CreateMap<Name, NameViewModel>(); 
     Mapper.CreateMap<Contact, ContactViewModel>(); 

     var contact = new Contact 
     { 
      Name = new Name 
      { 
       Name_Forename = "forename" 
      } 
     }; 
     var vm = Mapper.Map<Contact, ContactViewModel>(contact); 
     Console.WriteLine(vm.Name.Name_Forename); 
    } 
} 

打印效果與預期:

forename 

所以請確保repository.Contact.Where(c => c.ID == id).Single()調用返回Contact實例,其Name屬性正確實例化幷包含其屬性的值。

現在,這是說,有一對夫婦的問題與您的代碼:

  • 你裝飾用[HiddenInput]屬性,是鑑於具體的東西,屬於你的視圖模型您的域模型的屬性。
  • 您已使用[Key]屬性修飾了您的視圖模型屬性。這是視圖模型應該不可知的數據訪問特定的東西。
  • 您正在調用控制器操作中的Mapper.CreateMap<TSource, TDest>方法。這是錯誤的。映射定義應該只在應用程序域的整個生命週期內完成一次。這通常發生在Application_Start內部的幫助程序方法中,以確保您的映射定義只進行一次。在您的控制器操作中,您只應使用Mapper.Map<TSource, TDest>方法來執行實際映射。
+0

感謝Darin,你能否告訴我如何正確實例化Name屬性?還有爲什麼這個映射是自動完成的。 Jim – James

0

正如之前所說的,你應該定義你的映射只有一次(在APP_Start文件夾) 不知道這是否是你所需要的東西,但你可以做你的映射方式如下:

Mapper.CreateMap<Contact, ContactViewModel>() 
.ForMember(c => c.Name, opt => opt.MapFrom(o => o.Name_Forename + " " + o.Name.Lastname); 
+0

我認爲這看起來是正確的,但我需要返回嵌套在ContactViewModel對象中的NameViewModel對象,所以我試着... 'code' Mapper.CreateMap ()。ForMember(c => c。名稱,opt => opt.MapFrom(o => o)); Mapper.CreateMap (); var contact = repository.Contact.Where(c => c.ID == id).Single(); var vm = Mapper.Map (contact); return View(vm); '代碼' 這給了我這個錯誤...缺少類型映射配置或不支持的映射。有什麼想法嗎? – James

+0

哎呀我以爲你的「名稱」屬性是一個字符串。對於名稱完全相同的成員,不需要使用ForMember()函數進行映射。通常,您應該簡單地定義Mapper.CreateMap (); Mapper.CreateMap ();它應該工作。如果沒有,請確保您已加載屬性(如果延遲加載已停用)。 – ckonig

+0

啊,現在我想你可能已經發現了我現在遇到的真正問題。我如何加載屬性,或確保我已加載屬性(如果惰性加載已停用,我認爲是這樣)。 – James