Asp.net mvc 遵循视图模型模式的最佳实践
我现在正在学习ASP.NETMVC。我遵循一些在互联网上或书籍中找到的指导原则,我希望确保在开发视图模型模式时遵循良好的实践。下面是一个博客实现的简单示例。你能确认一下我走对了路吗。假设我想在一个视图上显示一个帖子标题+描述,并在该帖子的评论下方显示。所以我有一个视图,其中有两个局部视图 在我的控制器中:Asp.net mvc 遵循视图模型模式的最佳实践,asp.net-mvc,Asp.net Mvc,我现在正在学习ASP.NETMVC。我遵循一些在互联网上或书籍中找到的指导原则,我希望确保在开发视图模型模式时遵循良好的实践。下面是一个博客实现的简单示例。你能确认一下我走对了路吗。假设我想在一个视图上显示一个帖子标题+描述,并在该帖子的评论下方显示。所以我有一个视图,其中有两个局部视图 在我的控制器中: public ActionResult DetailPost(int postID) { // retrieve infos Post post
public ActionResult DetailPost(int postID)
{
// retrieve infos
Post postModel = repository.Posts.FirstOrDefault(p => p.PostID == postID);
IEnumerable<Comments> commentsModel = postModel.Comments;
// prepare view model
DetailPostViewModel detailPostViewModel = new DetailPostViewModel
{
Post = postModel,
Comments = commentsModel,
};
return View(detailPostViewModel);
}
@model WebUI.ViewModels.DetailPostViewModel
@{
ViewBag.Title = "Detail";
}
<h2>Detail</h2>
@Html.Partial("_DetailPost", Model.Post)
@Html.Partial("_Comments", Model.Comments)
@model Domain.Entities.Post
@Html.DisplayForModel()
...
@model IEnumerable<Domain.Entities.Comment>
@foreach (var item in Model)
{
@Html.DisplayFor(Model => item.Title)
@Html.DisplayFor(Model => item.Username)
}
所以在我的局部视图中,我使用en实体作为模型。是好还是坏
在我的评论视图中:
public ActionResult DetailPost(int postID)
{
// retrieve infos
Post postModel = repository.Posts.FirstOrDefault(p => p.PostID == postID);
IEnumerable<Comments> commentsModel = postModel.Comments;
// prepare view model
DetailPostViewModel detailPostViewModel = new DetailPostViewModel
{
Post = postModel,
Comments = commentsModel,
};
return View(detailPostViewModel);
}
@model WebUI.ViewModels.DetailPostViewModel
@{
ViewBag.Title = "Detail";
}
<h2>Detail</h2>
@Html.Partial("_DetailPost", Model.Post)
@Html.Partial("_Comments", Model.Comments)
@model Domain.Entities.Post
@Html.DisplayForModel()
...
@model IEnumerable<Domain.Entities.Comment>
@foreach (var item in Model)
{
@Html.DisplayFor(Model => item.Title)
@Html.DisplayFor(Model => item.Username)
}
如何将(实体)发布对象列表映射到视图模型对象和所有子对象(注释、用户)中
谢谢 很接近,但对我来说,这不是视图模型的正确用法。您具有以下功能:
public class DetailPostViewModel
{
public Post Post { get; set; }
public IEnumerable<Comment> Comments { get; set; }
}
public class DetailPostViewModel
{
public PostViewModel Post { get; set; }
public IEnumerable<CommentViewModel> Comments { get; set; }
}
和(~/Views/Shared/DisplayTemplates/CommentViewModel.cshtml
):
显然,由于Comments是一个枚举,因此将为集合的每个元素自动呈现显示模板。这样,您就不需要在视图中编写任何循环
就控制器逻辑而言,我个人喜欢使用它在域实体和视图模型之间进行映射
所以它可能看起来像这样:
public ActionResult DetailPost(int postID)
{
// retrieve infos
var postModel = repository.Posts.FirstOrDefault(p => p.PostID == postID);
var viewModel = new DetailPostViewModel
{
Post = Mapper.Map<Post, PostViewModel>(postModel),
Comments = Mapper.Map<IEnumerable<Comment>, IEnumerable<CommentViewModel>>(postModel.Comments)
};
return View(viewModel);
}
您确实在视图中使用了域模型。视图模型只是域模型的容器 就个人而言,我在视图中使用实体或域模型没有问题。我通常从他们开始。当域/实体模型不能完全满足我的需求时,我会切换到视图模型(而不是在视图中引入逻辑)
没有其他代码依赖于您的视图,这使得重构视图和随时切换模型变得很容易。我看不出有任何问题implementation@Ankur当前位置对我来说最大的问题是关于局部观点。我的意思是,在这些视图上使用实体是一种好的做法吗?或者我也必须在这些局部视图上使用视图模型吗?我问这个问题是因为规则是:“永远不要将任何域模型传递给视图”!我个人不同意
永远不要将任何域模型传递给视图
就我而言,它只是一些需要通过视图显示的数据结构。这些规则可以让你远离真正的问题我同意Ankur的观点。。设计模式和最佳实践是一件伟大的事情,但在它们实际指导您实现可维护性和良好代码时,以及它们只是在哲学问题上自慰时,找到平衡是非常重要的。。“从不将任何域模型传递到视图”规则来自第二类,我认为,通过这种方式,您可以快速完成工作,并且在99%的情况下不会有任何负面影响。我将重构我的示例并稍后重新提交(我现在不得不离开)以征求意见/建议。您好,我更新了我的帖子(编辑部分)以尝试使用Automapper,但我遇到了一些困难,您可以检查一下吗?@Bronzato,第一个问题是:您是否需要视图中的所有属性?回答是肯定的。为了我的学习,我想知道如何做到这一点。谢谢我们在很多情况下都会遇到这个问题。@Bronzato,我已经更新了我的答案,以举例说明映射可能是什么样子。
@model WebUI.ViewModels.CommentViewModel
@Html.DisplayFor(x => x.Title)
@Html.DisplayFor(x => x.Username)
public ActionResult DetailPost(int postID)
{
// retrieve infos
var postModel = repository.Posts.FirstOrDefault(p => p.PostID == postID);
var viewModel = new DetailPostViewModel
{
Post = Mapper.Map<Post, PostViewModel>(postModel),
Comments = Mapper.Map<IEnumerable<Comment>, IEnumerable<CommentViewModel>>(postModel.Comments)
};
return View(viewModel);
}
public class PostViewModel
{
... some properties of a Post
public IEnumerable<CommentViewModel> Comments { get; set; }
}
public ActionResult DetailPost(int postID)
{
// retrieve infos
var postModel = repository.Posts.FirstOrDefault(p => p.PostID == postID);
var viewModel = Mapper.Map<Post, PostViewModel>(postModel);
return View(viewModel);
}
@model WebUI.ViewModels.PostViewModel
@{
ViewBag.Title = "Detail";
}
<h2>Detail</h2>
... some properties of a post
@Html.DisplayFor(x => x.Comments)
Mapper.CreateMap<User, UserVM>();
Mapper
.CreateMap<Comment, CommentVM>()
.ForMember(
dest => dest.UserVM,
opt => opt.MapFrom(src => src.User)
);
Mapper
.CreateMap<Post, PostVM>()
.ForMember(
dest => dest.CommentsVM,
opt => opt.MapFrom(src => src.Comments)
);
IEnumerable<Post> posts = ...
IEnumerable<PostVm> postVms = Mapper.Map<IEnumerable<Post>, IEnumerable<PostVM>>(posts);
return View(postVms);