我想使用视图模型来显示域模型的内容。我想自定义一个属性进行显示,我该怎么做?使用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提供的链接
答案 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中收到的域实体,无论如何。请记住,控制器操作不应直接使用域实体(您不应该信任直接来自视图的数据 - 让模型确定域实体是否有效)。