2012-06-10 5 views
0

J'espérais que vous seriez en mesure de m'aider avec une question Automapper que j'ai dans un test ASP.NET MVC application que je développe.AutoMapper Complex ViewModel propriétés

J'ai regardé autour de moi et je n'ai rien trouvé qui ressemble à ce que j'essaie d'obtenir avec les ViewModels imbriqués.

Fondamentalement, je ces 2 modèles de domaine ...

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

Et ..

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

Et je ces 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; } 
    } 
} 

Et ...

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

Je souhaite renvoyer ContactViewModel à ma vue avec la propriété Name remplie avec la propriété Name qui remplit l'objet de domaine Contact.

J'ai ce code dans mon contrôleur ...

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

C'est là que je rencontre des problèmes, ma propriété Name est jamais peuplée.

La raison de me choisir de concevoir ma demande de cette façon est parce que mes vues sont composées de modèles de modèle personnalisé afin que je puisse rendre constamment des objets NameViewModel sans code de répéter, comme dans cet exemple simple ...

@model Test.WebUI.Models.NameViewModel 

First 
@Model.Name_Forename 
Last 
@Model.Name_Surname 

Si quelqu'un peut m'expliquer comment je dois remplir l'objet NameViewModel du ContactViewModel avec AutoMapper, je serais vraiment reconnaissant.

Merci. Jim

Répondre

1

Cela devrait fonctionner hors de la boîte comme indiqué ici:

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

impressions comme prévu:

forename 

Donc, assurez-vous que le retourne une Contact instance d'appel repository.Contact.Where(c => c.ID == id).Single() dont Name propriété est correctement instancié et contient des valeurs pour ses propriétés.

Maintenant, cela étant dit, il y a quelques problèmes avec votre code:

  • Vous avez décoré vos propriétés du modèle de domaine avec l'attribut [HiddenInput] qui est une vue des choses spécifiques et appartient sur votre modèle de vue.
  • Vous avez décoré les propriétés de votre modèle de vue avec l'attribut [Key]. C'est un accès spécifique aux données dont un modèle de vue devrait être agnostique.
  • Vous appelez la méthode Mapper.CreateMap<TSource, TDest> dans votre action de contrôleur. C'est faux. La définition de mappage doit être effectuée une seule fois pour toute la durée de vie du domaine d'application.Cela se produit généralement dans une méthode d'assistance appelée Application_Start pour vous assurer que vos définitions de mappage sont effectuées une seule fois. À l'intérieur de votre action de contrôleur, vous devez utiliser uniquement la méthode Mapper.Map<TSource, TDest> pour effectuer le mappage réel.
+0

Merci pour ce Darin, serais-tu capable de conseiller sur comment instancier correctement la propriété Name? Et aussi pourquoi cette cartographie est faite automatiquement. Jim – James

0

Comme dit précédemment, vous devez définir vos correspondances qu'une seule fois (dans le dossier APP_Start) Je ne sais pas si cela est exactement ce dont vous avez besoin, mais vous pouvez faire votre cartographie de la manière suivante:

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

Je pense que cela semble à peu près juste mais je dois retourner un objet NameViewModel imbriqué dans l'objet ContactViewModel donc j'ai essayé ... 'code' Mapper.CreateMap (). ForMember (c => c. Nom, opt => opt.MapFrom (o => o)); Mapper.CreateMap (); var contact = référentiel.Contact.Où (c => c.ID == id) .Single(); var vm = Mapper.Map (contact); return (vm); 'code' Cela me donne cette erreur ... Configuration de mappage de type manquant ou mappage non pris en charge. Des pensées? – James

+0

Oups Je pensais que votre propriété "Nom" serait une chaîne. Pour les membres avec exactement le même nom, il n'y a pas besoin d'être un mappage avec la fonction ForMember(). Normalement, vous devez simplement définir Mapper.CreateMap (); Mapper.CreateMap (); et ça devrait marcher. Si ce n'est pas le cas, vérifiez que vous avez chargé les propriétés (si le chargement paresseux est désactivé). – ckonig

+0

Ah, maintenant je pense que vous avez peut-être trouvé le vrai problème que j'ai alors. Comment puis-je charger les propriétés, ou assurez-vous que j'ai chargé les propriétés (si le chargement paresseux est désactivé, ce que je pense qu'il est). – James

Questions connexes