【问题标题】:Why can't I share a variable between two content sections in an ASP.NET MVC View?为什么我不能在 ASP.NET MVC 视图中的两个内容部分之间共享变量?
【发布时间】:2010-06-10 01:29:16
【问题描述】:

我有一个带有典型 TitleContent 和 MainContent 的 ASP.NET MVC 视图,我想计算一个相当复杂的标题,然后在这两个内容部分之间共享,如下所示:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%
    var complicatedTitle = string.Format("{0} - {1}", Model.FirstThing, Model.SecondThing);
%>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    <%: complicatedTitle %>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2><%: complicatedTitle %></h2>

</asp:Content>

但是,这不起作用,因为生成的错误消息会说在包含内容控件的内容页面中只允许直接使用内容控件。

计算肯定属于视图。你如何解决这个问题?

【问题讨论】:

  • 您能否提供更多背景信息?特别是为什么不能在控制器中进行计算?
  • 在这种特定情况下,它实际上并不那么重要:模型中有两个字符串组成了标题,需要用冒号':'分隔,如“类型:恐怖”或“额定:R",但在某些用途中没有第二个字符串(它为 null 或空),并且在这种情况下不需要冒号。这听起来几乎是微不足道的,但是在页面中进行两次相同的计算会使它变得笨拙。在控制器中执行此操作似乎也毫无意义,因为它不应该知道标题是否必须格式化为“{0} : {1}”或“{0} ({1})”。

标签: asp.net-mvc


【解决方案1】:

代码不能位于 Content 控件之外的原因是它需要位于某种类型的服务器端部分中,服务器才能自动呈现它。

我建议在您的 Controller Action 方法中构造此标题并保存到 ViewData 会更常见。

【讨论】:

  • +1,在这里使用 ViewData 更合适。视图不应该进行计算,它们应该只渲染控制器传入的内容。
  • 但是计算是特定于它必须如何呈现的。
  • @Dave:您将在控制器中处理Model 对象,因此可以进行计算。从概念上讲,您遇到了一个可以争论的灰色区域,但 ASP.NET MVC 实现倾向于在控制器中执行此操作。
  • 我强烈反对。这种特定的计算可能因一种观点而异,而相同的模型可以在两种观点中使用。哎呀,不同的操作使用相同的视图。
  • 这完全取决于您将如何使用它。在大多数情况下,您将更改标题数据以为页面提供上下文,最好在控制器中完成。如果您要多次使用此计算,则要么创建 HtmlHelper 方法,要么将逻辑放入模型本身。
【解决方案2】:

另一种方法是添加一个专门用于生成格式良好的标题的 HTML 助手。

public static string FormattedTitle(this HtmlHelper helper, string firstPart, string secondPart)
{
    return firstPart + secondPart;
}

然后调用它

<%: Html.FormattedTitle(firstPart, secondPart) %>

【讨论】:

  • 事实上,我可以摆脱除了助手之外的所有参数,因为我可以从助手中的模型中提取我需要的所有信息。
  • 您打算如何删除这些论点?我不确定我是否关注你。
  • 计算该标题所需的所有信息都可以在视图模型中找到,该视图模型可通过帮助程序获得。这也是 DisplayFor() 和 EditorFor() 的工作原理。
  • 但是您不会明确引用模型中的属性吗? Html 助手应该与领域模型无关。最好遵循关注点分离的原则来实现上面的代码,并带有要连接的参数。
  • 你说得对。我只是评论说这是可能的。
【解决方案3】:

这里是一种方法[编辑:看起来这会导致静态字段 - 所以不要使用它 - 抱歉]

<Script runat="server" language="C#">
    string foo = "first thing " + " second thing";
</Script>

<asp:Content ContentPlaceHolderID="head" runat="server">
    <%= foo %>
</asp:Content>

<asp:Content ContentPlaceHolderID="body" runat="server">
    <%= foo %>
</asp:Content>

(请注意,您不能在脚本中使用 'var')

还有一个第二种方式

  • 使用代码隐藏计算具有视图专用的ComplicatedTitle 属性的属性。您仍然完全依赖视图来执行逻辑,但将其从视图的 HTML 部分中取出 - 毕竟您的所有 aspx 和 aspx.cs 文件最终最终成为同一个类!
  • 有些人被视图中的代码吓坏了,但I think it definitely has its place 如果你谨慎且明智

还有一个第三种方式

我假设您不想在模型中创建第三个属性,但是如果它看起来合适的话,这是一种快速而肮脏的方法。至少你的控制器没有这样做,但这可能不是最好的方法

public class MyModel {

   public string Prop1 {get;set;}
   public string Prop2 {get;set;}

   public string GetFormattedTitle() {
      return Prop1 + " - " + Prop2;
   }    
}

【讨论】:

  • 可能有一个 aspx 指令作为 的快捷方式,但我不记得是否有,但如果它确实存在。
  • 是的有:OP使用的那个-&lt;%
  • @darin - 嗯。那么也许提问者错误地嵌套了 标签。如果你弄乱了 html,你会得到同样的错误。我给出的这个例子确实可以编译和运行,所以我不确定为什么他原来的没有。
  • 你不能在 中使用 var 因为它变成了一个静态字段,其中 var 是不允许的。此外,它是静态的,所以如果我必须从视图模型中提取一些东西,那么毫无意义。
  • 和 之间肯定有区别,因为前者不会给我同样的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 2017-09-13
  • 1970-01-01
相关资源
最近更新 更多