【问题标题】:ASP.NET MVC2: Views, Viewmodels, and Post requestsASP.NET MVC2:视图、视图模型和发布请求
【发布时间】:2010-11-27 03:36:51
【问题描述】:

我在 ASP.NET MVC2 中遵循良好的面向对象设计时遇到了麻烦,我认为问题在于对用户发布信息时 ViewModel 和 View 应该如何交互的理解不足。

我实现了一个论坛,允许用户使用回复操作创建对主题的回复。我的 ReplyViewModel 包含一个用于 threadId 的 int 和一个用于回复内容的字符串。回复操作使用 ThreadId 创建一个回复视图模型,因此我们将知道用户正在回复哪个线程。回复视图是回复视图模型的强类型,并具有允许用户编辑模型内容的表单。然后,用户可以将 threadId 作为参数发布到回复操作。

它有效,但我认为我这样做的方式不正确。每个帖子都涉及两个ReplyViewModel:一个具有threadId 但内容为空,另一个具有内容但ThreadId 为空。回复视图正在创建一个新的回复视图模型,我认为它应该只是编辑传递给视图的回复视图模型——但我不知道如何。

这是视图的精简版:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<mvcForum.ViewModels.ReplyViewModel>" %>
<%: Html.TextAreaFor(model=> model.content, new{TextMode="multiline", id="postbox"})%>
<input type="submit" value="Reply" />

如果这还不足以回答我的问题,这里是整个视图:http://pastebin.com/BFGL4p67

ViewModel 实际上只是一个字符串(内容)和一个整数(threadId)。

控制器:

[Authorize]
public ActionResult Reply(int id)
{
    ReplyViewModel reply = new ReplyViewModel
    {
        ThreadId = id
    };
    return View(reply);
}
[HttpPost]
public ActionResult Reply(int id, ReplyViewModel model)
{
    /**TODO: Catch when no user*/
    var newPost = new ForumPost
    {
        UserId = (Guid)Membership.GetUser(User.Identity.Name).ProviderUserKey,
        ThreadId = id,
        postContent = model.content
    };
    db.AddToForumPosts(newPost);
    db.SaveChanges();
    return RedirectToAction("Index");
}

所以我的问题是“做我想做的事情的最佳方法是什么?我可以使用 ReplyViewModel 的单个实例从控制器传递到视图,然后再返回到控制器吗?”

【问题讨论】:

  • 我认为您在这里做得很好...不确定您要解决的确切问题是什么?
  • 使用一个类的两个实例来做两件完全独立的事情似乎是错误的,每个实例中只使用一个字段。如果我可以使用相同的实例会更有意义。

标签: asp.net-mvc asp.net-mvc-2


【解决方案1】:

我认为你做的很好。

您正在考虑一个尚未遇到的问题,即用于填充表单的数据与将要发布的数据有很大不同时。这里的“Get”视图模型是“Post”视图模型的子集,所以使用一个视图模型很好,但如果“Get”的数据和“Post”的数据差别很大,你可以使用两个不同的视图模型,例如:

public class GetReplyFromViewModel  //...
public class PostReplyFromViewModel //...

但我建议不要这样做,除非两个视图模型非常不同并且足够复杂以至于需要它们自己的视图模型。

需要记住的重要一点:仅仅因为视图被强类型化为类型'A'并不意味着post方法中的参数类型不能是类型'B'。

  • 视图的类型将简单地确定视图中的编译/智能感知以及视图的类型检查,无论何时创建视图。
  • post 方法参数的类型将简单地使用MVC Model Binding 将发布的HTTP 表单转换为您指定的类型。

换句话说,您的视图类型可能只是

<%@ Page Title="" ... Inherits="System.Web.Mvc.ViewPage<int>" %> 

如果您愿意,整个Model 变量就是ThreadId,如果您的html 字段命名正确,post 方法仍然可以采用相同的参数。

但同样,在这种特殊情况下,我认为当前的实现还不错。

【讨论】:

  • 感谢您的帮助!模型绑定文档的链接特别有用,因为我一直想知道视图如何选择它们将传递给 Post 控制器的参数类型。但是,我仍然想知道,如何(或是否)通过将信息存储在 ViewModel 中,将信息从 Get 控制器传递到 Post 控制器。
  • 嗯,这个想法是让事物保持“无状态”,因为它是一个网络应用程序。基本上,您从 get 中获取的视图模型在您的视图中以 html 形式保存。如果您的视图有一个向服务器执行 HTTP POST 的表单,则所有输入都将进入 POST 消息并由 MVC 模型绑定器处理。这个模型绑定器查看字段名称并将它们映射到您的 post 方法中的对象。因此,要在 Get/Post 方法之间传递内容,您可以将它们存储在表单的隐藏字段中或使用会话。 HTH,T.J.附言如果您想了解更多信息,我建议您使用 TekPub MVC 系列tekpub.com/view/aspmvc/1
  • 再次感谢;我不知道无国籍是一个目标,所以我想我正试图做相反的事情。很高兴知道隐藏字段是可以接受的,因为这似乎是一种非常简单的方法来做我迄今为止想到的任何事情。
  • 您可能想要淘汰传统的 ASP.net Web 表单,因为它基本上可以为您跟踪所有状态。它可能更适合您的案例/设计。
猜你喜欢
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2011-10-24
相关资源
最近更新 更多