2012-06-10 2 views
0

Я надеялся, что вы сможете помочь мне с вопросом Automapper, который у меня есть в тестовом приложении ASP.NET MVC, которое я разрабатываю.AutoMapper Complex ViewModel properties

У меня был взгляд вокруг, и я не мог найти ничего подобного, чего я пытаюсь достичь с помощью вложенных ViewModels.

В принципе, у меня есть эти два домена модели ...

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 в свой вид с именем, заполненным свойством Name, которое заполняет объект Contact Contact.

У меня есть этот код в мой контроллер ...

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

Это где я бегу в проблемы, моя собственность Имя никогда не заполняется.

Причина для меня выбор, чтобы спроектировать мое приложение таким образом, это потому, что мои взгляды состоят из пользовательских шаблонов модели, так что я могу последовательно оказывать объекты NameViewModel без повторения кода, так как в этом простом примере ...

@model Test.WebUI.Models.NameViewModel 

First 
@Model.Name_Forename 
Last 
@Model.Name_Surname 

Если кто-нибудь может объяснить мне, как я должен заполнить объект NameViewModel ContactViewModel с помощью AutoMapper, я был бы очень благодарен.

Спасибо. Джим

ответ

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

Спасибо за это Дарин, не могли бы вы посоветовать, как я правильно создаю свойство 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

Я думаю, что выглядит правильно, но мне нужно вернуть объект NameViewModel, вложенный в объект ContactViewModel, поэтому я попытался ... 'code' Mapper.CreateMap (). ForMember (c => c. Name, opt => opt.MapFrom (o => o)); Mapper.CreateMap (); var contact = repository.Contact.Where (c => c.ID == id) .Single(); var vm = Mapper.Map (контакт); return View (vm); 'code' Это дает мне эту ошибку ... Отсутствует конфигурация карты типа или неподдерживаемое отображение. Есть предположения? – James

+0

К сожалению, я думал, что ваше свойство «Имя» будет строкой. Для членов с таким же именем не обязательно должно быть сопоставление с функцией ForMember(). Обычно вы должны просто определить Mapper.CreateMap (); Mapper.CreateMap (); и он должен работать. Если это не так, убедитесь, что вы загрузили Свойства (если ленивая загрузка деактивирована). – ckonig

+0

А теперь я думаю, что вы, возможно, нашли настоящую проблему, с которой я столкнулся. Как загрузить свойства или убедиться, что я загрузил свойства (если ленивая загрузка отключена, что я думаю, что это так). – James

Смежные вопросы