【问题标题】:Approaches for handling common data in ASP.NET MVC 3 views在 ASP.NET MVC 3 视图中处理常见数据的方法
【发布时间】:2011-02-01 20:57:45
【问题描述】:

我正在为一个看似非常简单的概念而苦苦挣扎。如果我的 ViewBag 中有一个值供我的 _Layout.cshtml 使用,我应该如何以及在哪里设置该值?

以下是我目前看到的最明显的(对我而言)选项:

  1. 在每个控制器中设置值(不是 DRY)
  2. 创建自己的控制器基类,继承自 Controller 并在基类中设置值
  3. 在 Global.asax.cs 中设置值(感觉很脏)
  4. 创建一个ActionFilter来设置数据并全局注册过滤器(也感觉不对)
  5. 在_ViewStart.cshtml中设置值(感觉很不对很脏)

例如:

_Layout.cshtml


<!DOCTYPE html>
<html>
<head runat="server">
    <title>@ViewBag.Title</title>
</head>
<body>
    <div id="header">
       <h1>Welcome @ViewBag.UserName</h2>
    </div>
    <div id="content">
       @RenderBody()
    </div>
</body>
</html>

如果每个控制器都设置了 UserName 值,那并不是很干燥。如果我用 CodeIgniter 之类的东西来解决这个问题,我只需创建自己的基本控制器来处理这些常见项目并按照我的快乐方式行事。 ASP.NET MVC 3 是否有更好的选择?

【问题讨论】:

  • 实际上,在这种特殊情况下 - 我猜“用户名”实际上来自会话/表单身份验证票。因此,您可能希望使用 HTML 帮助程序,该帮助程序使用 FormsAuth 代码从 cookie 中获取用户名并呈现 MvcHtmlString - 只是一个想法......
  • 嗯...好点。也许@ViewBag.UserName 不是最好的例子。不过,我现在真的更关心大局。
  • @RPM1984:“用户名”来自表单身份验证的观点无关紧要。它应该被传入(ViewBag 或其他)。视图不应该“获取”任何东西。还要考虑测试场景,您希望将假数据传递给视图以进行单元测试。如果您的视图正在“获取”事物,则不可能。也几乎使 MVC 模式的全部观点无效。不是在挑剔你,但我刚刚看到这种心态在各种 MVC 文章中重复出现(包括默认的 MVC 项目模板!)
  • @rogerh - 我原则上同意你的观点,观点应该是愚蠢的,而不是“获取”任何东西。但是,读取 Forms Auth 信息的 HTML 助手不会“获取”任何东西。对我来说,“获取”某些东西是数据库调用或对外部服务的调用。 UserName 存在于 Http 上下文中,就像 HTML/URL 助手工作的路由值一样,所以我认为您的观点在这种情况下无效。您仍然可以进行单元测试——通过模拟 Http 上下文——与单元测试任何 HTML 帮助程序的方式相同。
  • @RPM1984:如果视图没有从模型中读取数据,它正在获取它。就那么简单。视图中有很多可用的东西,例如上下文、cookie、路由数据等。我希望不是因为它诱使人们完全按照您的描述去做。如果我不仅想要用户名,还想要他的 UserID 怎么办?还是他上次登录的日期?或者用户是男性还是女性?我要将其转储到 cookie 中,还是在 HttpContext.Items[] 中?为什么要使用模型?为什么不把所有东西都放到一些随机的 HttpContext 值中呢?你明白我要说明什么了吗?

标签: asp.net asp.net-mvc controller asp.net-mvc-3


【解决方案1】:

通用视图模型和基本控制器是 IMO 的出路。使用通用视图模型作为所有视图模型的基类。使用基本控制器中的 OnActionExecuted 方法获取视图模型(用于返回视图的操作)并将其转换为通用视图模型。设置当时的通用属性。

【讨论】:

  • 时髦。很高兴知道我并没有完全脱离基地。
  • 我只知道绝对的西斯交易,但这是唯一正确的答案。视图应该只从模型中读取,并且只有控制器可以写入模型。如果您坚持使用强类型模型,您将需要一个基本模型和一个基本控制器。
  • @tvanfossen。这是一种有趣的方法,我目前正在尝试。一个问题 - 我可以使用 ActionFilter 代替基本控制器并连接到 OnActionExecuted 吗?我需要传递通用数据,但仅限于特定操作,因此认为使用过滤器装饰那些会更好。
【解决方案2】:

假设我想让 ViewBag.PageHeight 的所有页面的默认值为 1000,然后允许任何页面/视图覆盖它。这是我放在_Layout.cshtml中的:

页面高度为@(ViewBag.PageHeight ?? 1000)

这似乎行得通。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-26
    • 2012-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多