对于以下视图模型模式的最佳实践 [英] Best practice for following the view model pattern

查看:227
本文介绍了对于以下视图模型模式的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我学习ASP.NET MVC一段时间了。我跟着在互联网上或在书本上发现了一些指导,我想,以确保我按照我的发展有关视图模型模式的良好做法。下面是实施博客的一个简单的例子。请问您能否确认我说,我在正确的道路。比方说,我想在一个视图和下方对这个职位的评论显示文章标题+描述。所以,我有2部分意见认为就可以了。

I'm learning ASP.NET MVC for some times now. I follow some guidelines found on internet or in books and I would like to be sure I follow good practices in my developments regarding the view model pattern. Below is a simple example of implementation of a blog. Could you please confirm me that I'm on the right way. Let's say I would like to display a post title + description on a view and below that comments on this post. So I have a view with 2 partial views on it.

在我的控制器:

    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);
    }

所以在这里,我perpare的两件事组成的视图模型:

So here, I perpare a view model composed of 2 things:


  • 后的信息

  • 注释的枚举。

视图模型将被传递给视图以下视图模型模式。

The view model will be passed to the view for following the view model pattern.

在我的详细信息视图:

@model WebUI.ViewModels.DetailPostViewModel

@{
    ViewBag.Title = "Detail";
}

<h2>Detail</h2>

@Html.Partial("_DetailPost", Model.Post)
@Html.Partial("_Comments",  Model.Comments)

所以在这里,我用我的DetailPostViewModel。对于我的部分观点,我通过这都是实体必要的信息!?我不知道这是正确的方式还是必须通过专门在这里查看车型呢?

So here, I used my DetailPostViewModel. For my partial views, I passed the necessary information which are entities!? I don't know if this is the right way or do I have to pass exclusively view models here too?

在我_DetailPost观点:

@model Domain.Entities.Post

@Html.DisplayForModel()
...

所以,在这里我的部分观点,我使用EN实体模型。它是好还是坏?

So here in my partial view, I used en entity as model. Is it good or bad?

在我_c​​omments查看:

@model IEnumerable<Domain.Entities.Comment>

@foreach (var item in Model)
{
    @Html.DisplayFor(Model => item.Title)
    @Html.DisplayFor(Model => item.Username)
}

所以,在这里我的部分观点,我使用EN实体模型。它是好还是坏?

So here in my partial view, I used en entity as model. Is it good or bad?

感谢您的建议/建议。

修改

我试图实现我的Automapper的帮助视图模型的模式,但我有一些问题,如下所述。我明白了一个对象映射到另一个普林西比。在基本情况下,它工作得很好。现在,让我们看到了一个更复杂的情况:我有一些属性组成的职位(ID,标题,...)和各岗位能够有一些意见(对象)并且每个注释只能有一个用户(对象)附。我想获得我的所有文章视图模型,并为每一个,让所有的意见,并为每个评论得到了用户连接。

I try to implement my view model pattern with the help of Automapper but I have some problems as described below. I understand the principe of mapping one object to another. In a basic situation it works very well. Now, let's see the a more complex situation: I have a post composed of some attributes (id, title, ...) AND each post can have some comments (object) attached AND each comment can have only one user (object) attached. I would like to get a view model with all my posts and for each one, get all the comments and for each comment get the user attached.

下面是域的实体:

public class Post
{
    public int    PostID    { get; set; }
    public string Title     { get; set; }
    ...
    public virtual ICollection<Comment> Comments { get; set; }
}

public class Comment
{
    public int    CommentID   { get; set; }
    public string CommentText { get; set; }
    ...
    public virtual <User> User { get; set; }
}

public class User
{
    public int UserID      { get; set; }
    public string Username { get; set; }
    ...
}

下面是视图模型:

public class PostVM
{
    public int    PostID    { get; set; }
    public string Title     { get; set; }
    ...
    public virtual ICollection<CommentVM> CommentsVM { get; set; }
}

public class CommentVM
{
    public int    CommentID   { get; set; }
    public string CommentText { get; set; }
    ...
    public virtual <UserVM> UserVM { get; set; }
}

public class UserVM
{
    public int UserID      { get; set; }
    public string Username { get; set; }
    ...
}

下面是我的控制器:

// I would like to list all posts in the DB.
public ViewResult Index()
{
    PostVM viewModel = new PostVM 
                           {
                               ...
                           }

    return View(viewModel);
}

如何映射我的(实体)的职位列表对象到我的视图模型对象和所有子对象(注释,用户)?

How do I map my list of (entity) posts objects into my view model object and all sub objects (comments, users)?

谢谢!

推荐答案

您已经接近但对我来说,这不是视图模型的正确用法。您有以下几点:

You are close but for me this is not a correct usage of view models. You have the following:

public class DetailPostViewModel
{
    public Post Post { get; set; }
    public IEnumerable<Comment> Comments { get; set; }
}

这是某种形式的混合伪视图模式。一个真正的视图模型不应该引用任何域模型任何责任。

That's some sort of a hybrid pseudo view model. A real view model should not reference any domain model whatsoever.

有一个更正确的例子是以下内容:

A more correct example would be the following:

public class DetailPostViewModel
{
    public PostViewModel Post { get; set; }
    public IEnumerable<CommentViewModel> Comments { get; set; }
}

在这里当然PostViewModel和CommentViewModel都是各自领域中的实体相应的视图模型。

where of course PostViewModel and CommentViewModel are the corresponding view models for their respective domain entities.

此外,而不是谐音,我会用显示模板:

Also instead of partials I would use display templates:

@model WebUI.ViewModels.DetailPostViewModel

@{
    ViewBag.Title = "Detail";
}

<h2>Detail</h2>

@Html.DisplayFor(x => x.Post)
@Html.DisplayFor(x => x.Comments)

和那么你将有相应的显示模板(〜/查看/共享/ DisplayTemplates / PostViewModel.cshtml

and then you will have the respective display templates (~/Views/Shared/DisplayTemplates/PostViewModel.cshtml):

@model WebUI.ViewModels.PostViewModel
... some properties of a post

和(〜/查看/共享/ DisplayTemplates / CommentViewModel.cshtml

@model WebUI.ViewModels.CommentViewModel
@Html.DisplayFor(x => x.Title)
@Html.DisplayFor(x => x.Username)

显然因为评论是枚举的显示模板将被自动呈现为集合中的每个元素。这样,你不需要编写任何循环在你的看法。

Obviously since Comments is an enumeration the display template will be automatically rendered for each element of the collection. This way you don't need to write any loop in your views.

至于控制器逻辑来讲,我个人喜欢用 AutoMapper 域实体和之间进行映射视图模型。

As far as the controller logic is concerned, personally I like to use AutoMapper to map between the domain entities and the view models.

因此​​,它可能是这样的:

So it might look like this:

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);
}

和那么你的观点会被强类型到PostViewModel:

and then your view will be strongly typed to a PostViewModel:

@model WebUI.ViewModels.PostViewModel

@{
    ViewBag.Title = "Detail";
}

<h2>Detail</h2>

... some properties of a post

@Html.DisplayFor(x => x.Comments)


由于在评论部分要求在这里是如何的域模型和视图模型之间的映射是这样的:


As requested in the comments section here's how the mapping between the domain models and the view models would look like:

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)
);

注:这两个 ForMemeber 通话不会有必要的,如果性能评为视图模型以同样的方式:用户注释。 AutoMapper依赖于标准的命名约定,也可以编写自己的自定义约定的策略,避免单独绘制每个成员。然后,所有你需要的是一致的,定义视图模型时遵循惯例。

Remark: The two ForMemeber calls wouldn't have been necessary if the properties were named the same way in the view model: User and Comments. AutoMapper relies on standard naming conventions and also you could write your own custom conventions strategy to avoid mapping each member individually. Then all you need is to be consistent and follow conventions when defining the view models.

和然后在控制器:

IEnumerable<Post> posts = ...
IEnumerable<PostVm> postVms = Mapper.Map<IEnumerable<Post>, IEnumerable<PostVM>>(posts);
return View(postVms);

这篇关于对于以下视图模型模式的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆