0

我希望您能够帮助我解决我正在开发的测试 ASP.NET MVC 应用程序中遇到的 Automapper 问题。

我环顾四周,找不到与我试图通过嵌套 ViewModel 实现的目标完全一样的东西。

基本上,我有这 2 个领域模型……</p>

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 个 ViewModel……</p>

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

还有……</p>

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 域对象的 Name 属性。

我的控制器中有这段代码……</p>

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 对象而无需重复代码,就像在这个简单的示例中一样......</p>

@model Test.WebUI.Models.NameViewModel

First
@Model.Name_Forename
Last
@Model.Name_Surname

如果有人可以帮助向我解释我应该如何使用 AutoMapper 填充 ContactViewModel 的 NameViewModel 对象,我将不胜感激。

谢谢。吉姆

4

2 回答 2

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>方法来执行实际的映射。
于 2012-06-10T19:59:08.677 回答
0

如前所述,您应该只定义一次映射(在 APP_Start 文件夹中)不确定这是否正是您需要的,但您可以通过以下方式进行映射:

Mapper.CreateMap<Contact, ContactViewModel>()
.ForMember(c => c.Name, opt => opt.MapFrom(o => o.Name_Forename + " " + o.Name.Lastname);
于 2012-06-11T09:51:40.517 回答