将域模型映射到通过AutoMapper查看模型

时间:2013-05-13 17:39:01

标签: c# asp.net-mvc-4 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"));

但是,使用下面的手动映射似乎很直观。

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

更新3

引自Jimmy Bogard

  

我认为使用AutoMapper是因为你不想使用“=”   操作员有点懒。相反,我们用它来压扁和重塑,   优化目标类型的环境。记得我的   AutoMapper的最初动机是:

     

通过映射到保护域层与其他层保护   DTO的

感谢@AndrewWhitaker提供的链接

1 个答案:

答案 0 :(得分:18)

这是AutoMapper的一个很好的用例(我已经在很多项目上成功地使用了这种方式)。通常,您希望将域实体公开给您的视图(在MVC中,这会将您的模型直接暴露给您的视图,这是不正确的。)

域实体和viewmodel之间不需要1-1映射。您可以使它们看起来完全不同,并在CreateMap<>调用中自定义映射。要使用您的示例:

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

最糟糕的情况是,您可以针对复杂案例抛弃自动播放器,或者使用自动套件的自定义类型解析器来完成工作。

实际上this is how Jimmy Bogard (the author) recommends using AutoMapper。他特别提到了从域实体到ASP.NET MVC ViewModels的映射,以便与强类型视图一起使用。

另一个优点是您可以对映射配置文件进行单元测试。这样,如果最终导致ViewModel与Model不匹配,您将获得失败的单元测试。

<强>更新

我认为您在问题中添加的引用进一步支持使用AutoMapper将域模型映射到ViewModel:

  

相反,我们使用它来展平和重塑,优化目标类型的环境。

因此,在我的示例中,您肯定会针对目标类型的环境进行优化(在本例中为视图)。

另外,根据我在上面引用的链接,使用automapper将映射到域,只有来自。考虑到这一点,您将不得不编写一些逻辑来创建/更新从View中收到的域实体,无论如何。请记住,控制器操作不应直接使用域实体(您不应该信任直接来自视图的数据 - 让模型确定域实体是否有效)。