将MVC2助手移动到MVC3剃刀视图引擎

时间:2011-02-11 14:43:52

标签: asp.net-mvc asp.net-mvc-3 html-helper razor

在我的MVC 2网站中,我有一个html帮助器,我用它为我的页面添加javascripts。在我的母版页中,我有我想要包含的主要javascripts,然后在aspx页面中,我包含页面特定的javascripts。

例如,我的Site.Master有这样的东西:

....
<head>
    <%=html.renderScripts() %> 
</head>
...
//core scripts for main page
<%html.AddScript("/scripts/jquery.js") %>
<%html.AddScript("/scripts/myLib.js") %>
....

然后在子aspx页面中,我可能还想包含其他脚本。

...
//the page specific script I want to use
<% html.AddScript("/scripts/register.aspx.js") %>
...

因此,当整页被渲染时,javascript文件全部被网站管理员占位符函数RenderScripts收集并呈现在头部。这很好。

现在使用MVC 3和razor视图引擎,它们的布局页面表现不同,因为现在我的页面级别javascripts不会被渲染/包含。现在我只看到了LayoutMaster的内容。

如何使用MVC 3和剃刀视图引擎获得解决方案。 (已经重写了帮助程序以返回HTMLString ;-))

供参考:我的MasterLayout看起来像这样:

  ...
  ...
  <head>
  @{
      Html.AddJavaScript("/Scripts/jQuery.js");
      Html.AddJavaScript("/Scripts/myLib.js");
   }
   //Render scripts
   @html.RenderScripts()
  </head>
 ....

,子页面如下所示:

@{
    Layout = "~/Views/Shared/MasterLayout.cshtml";
    ViewBag.Title = "Child Page";
    Html.AddJavaScript("/Scripts/register.aspx.js");
 }
 ....
 <div>some html </div>

感谢您的帮助。

编辑=只是解释,如果这个问题不够清楚。

在制作“页面”时,我会收集设计师想要使用的所有javascript文件,使用html.addJavascript(“filename.js”)并将它们存储在字典中 - (1)阻止人们添加重复的js文件 - 最后当页面准备渲染时,我会在标题中整齐地写出所有的javascript文件。 (2) - 这个帮助器有助于将JS保存在一个地方,并阻止设计人员在整个地方添加javascript文件。这曾经在mvc 2中使用Master / SiteMaster页面正常工作。但是如何用剃刀实现这一目标?

编辑:html助手代码:

....
private const string SCRIPTLINK = 
        "<script src=\"{0}\" type=\"text/javascript\"></script>";

public static HtmlString RenderScripts(this HtmlHelper helper)  {

    OrderedDictionary scripts = 
        helper.ViewContext.HttpContext.Items["JavaScripts"] as OrderedDictionary;

    StringBuilder sb = new StringBuilder(500);
    foreach (DictionaryEntry script in scripts)  {
                sb.AppendFormat(SCRIPTLINK, script.Key);
        }
     return new HtmlString(sb.ToString());
 }
....

3 个答案:

答案 0 :(得分:3)

如果没有看到HtmlHelpers的代码,很难帮助您使用当前的解决方案。然而,替代(并且相当普遍)的方法是使用Razor部分。

在您的布局页面中使用@RenderSection()

定义一个部分placholder
<head>
  <title>Page Title</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>
  @RenderSection("Scripts", required: false)
</head>

然后在您的视图中定义您的部分内容

@section Scripts {
  <script src="myscript.js" type="text/javascript"></script>
}

如果你想节省一些打字并使它更干净,你可以创建一个HtmlHelper来输出你的脚本标签

public static MVcHtmlString AddScript(this HtmlHelper helper, string path) {
  //create script element html here
}

然后你可以使用与你的例子类似的语法风格

@section Scripts {
  @Html.AddScript("myscript.js")
}

答案 1 :(得分:2)

您的代码可能正在为布局页面和视图使用单独的词典。

尝试将字典存储在ViewBagHttpContext.Items

答案 2 :(得分:1)

感谢Slaks和David的帮助和提示。我终于得到了一个似乎有效的解决方案,但有一些我不喜欢的东西。如果有更好的方法,请随时指出。

这是我的孩子页面:

@{
    ViewBag.Title = "Child Page";
 }

 @section Scripts {

     @{Html.AddJavaScript("/Scripts/register.aspx.js");}

  }

 <div>some html </div>

然后我有一个_ViewStart.cshtml:

@{
    this.Context.Items.Add("JavaScripts", 
        new System.Collections.Specialized.OrderedDictionary());

    Layout = "~/Views/Shared/MasterLayout.cshtml";
}

我的MasterLayout看起来像这样:

<html>
   ....
   <title>@ViewBag.Title</title>
   <head>
         @{
            //core scripts
            html.AddScript("/scripts/jquery.js"); 
            html.AddScript("/scripts/myLib.js");
            ....
           }

           @RenderSection("Scripts", required:true) 

           //Have to call render scripts here, but not sure about this?
           @Html.RenderScripts()
   </head>
....
</html>

这会以正确的顺序和位置呈现我的脚本标记,但是需要客户端在子页面中调用html帮助器renderScripts。这没关系,因为我们可以创建模板来帮助解决这个问题。有更好的想法吗?