C# 是否通过AutoMapper将域模型映射到视图模型

C# 是否通过AutoMapper将域模型映射到视图模型,c#,asp.net-mvc-4,automapper,C#,Asp.net Mvc 4,Automapper,我想用视图模型代替域模型进行显示。我想定制一个用于展示的属性,我应该如何做?使用AutoMapper进行显示是一种良好的做法吗 下面是代码示例: public class BookController : BaseController { private IBookService bookService; public BookController(IBookService bookService) { this.

我想用视图模型代替域模型进行显示。我想定制一个用于展示的属性,我应该如何做?使用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; }
    }
我该怎么做?使用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();
        }
    }
更新3

引自:

我认为使用AutoMapper是因为您不想使用“=” 接线员有点懒。相反,我们用它来展平和重塑, 针对目标类型的环境进行优化。记住,我的 AutoMapper最初的动机是:

通过映射到,启用从其他层保护域层 DTOs


感谢@AndrewHitaker的链接

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

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

Mapper.CreateMap<Book, BookView>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name + " this is for display purpose"));
Mapper.CreateMap<Book, BookView>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name + " Decorated"));
Mapper.CreateMap()
.ForMember(dest=>dest.Name,opt=>opt.MapFrom(src=>src.Name+“装饰”);
最糟糕的情况是,对于复杂的情况,您可以放弃automapper,或者使用带有automapper的自定义类型解析器来完成工作

其实,。他特别提到了从域实体到ASP.NET MVC ViewModels的映射,以用于强类型视图

另一个优点是,您可以对映射配置文件进行单元测试。这样,如果您最终发现ViewModel和Model之间不匹配,您将得到一个失败的单元测试

更新:

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

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

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


此外,根据我上面引用的链接,您不应该使用automapper映射到域,仅从。考虑到这一点,您必须编写一些逻辑来根据从视图中接收到的内容创建/更新域实体,而不管是什么。请记住,控制器操作不应直接获取域实体(您不应信任直接来自视图的数据——让模型确定域实体是否有效)。

根据更新2,它是如何混合不同用途的?ViewModel的目的不是显示域模型吗?Automapper只是一个实现这一点的工具。它与其他映射(例如域到dto)相比,不显示,而且更可能是干净的。您可以为域
-->
dto创建一个完全不同的映射。此外,您不应该使用AutoMapper从任何内容映射到域。根据您的更新(有用),是否有任何示例或链接用于将视图模型转换为域模型,并进行视图模型验证?我不明白您的最后一段。您的意思是我们不应该使用automapper从ViewModel映射到域(POCO)?如果是,如何将用户输入(视图)保存到数据库(模型)?通过手动映射?@Willy:是的,通过手动映射。我们的想法是,域太重要了,不能进行自动映射。为什么域太重要了,不能进行自动映射?我仍然感到困惑。我在患者表上有50个或更多字段。大多数字段必须在注册时填写。如果我手工绘制地图,那是多么无聊。这就是automapper简化映射的目的吗?@Willy:你当然可以随意使用automapper。我认为Jimmy Bogard在我上面链接的文章中更好地解释了这个问题
 public BookView(Book book){
    //mapping here
}
Mapper.CreateMap<Book, BookView>()
    .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name + " Decorated"));