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

Pin*_*ong 17 c# automapper asp.net-mvc-4

我想使用视图模型来显示域模型的内容.我想自定义一个属性进行显示,我该怎么做?使用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; }
    }
Run Code Online (Sandbox Code Playgroud)

如果我使用其他方式,我可以自定义任何属性,如下所示:

  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; }
    }
Run Code Online (Sandbox Code Playgroud)

我该怎么做?使用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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

更新2

对于通过视图模型的复杂自定义显示,我不想使用automapper来映射显示逻辑,假设automapper可以映射它.因为它混合了不同的目的.例如:

Mapper.CreateMap<Book, BookView>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name + " this is for display purpose"));
Run Code Online (Sandbox Code Playgroud)

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

 public BookView(Book book){
    //mapping here
}
Run Code Online (Sandbox Code Playgroud)

更新3

吉米博加德引用:

我认为使用AutoMapper因为你不想使用"="运算符有点懒.相反,我们使用它来展平和重塑,优化目标类型的环境.请记住,我对AutoMapper的最初动机是:

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

感谢@AndrewWhitaker的链接

And*_*ker 18

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

域实体和视图模型之间不需要1-1映射.您可以使它们看起来完全不同,并自定义CreateMap<>呼叫中的映射.要使用您的示例:

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

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

实际上,这就是Jimmy Bogard(作者)推荐使用AutoMapper的方式.他特别提到了从域实体到ASP.NET MVC ViewModels的映射,以便与强类型视图一起使用.

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

更新:

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

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

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

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