【问题标题】:Add CSS references to page's <head> from a partial view从局部视图中添加对页面 <head> 的 CSS 引用
【发布时间】:2011-05-11 18:10:02
【问题描述】:

有没有办法从局部视图向页面添加 CSS 引用,并让它们在页面的&lt;head&gt; 中呈现(根据HTML 4.01 spec 的要求)?

【问题讨论】:

  • 您的问题已经回答了好几次了,stackoverflow.com/questions/912755/… & stackoverflow.com/questions/885990/…。在这种情况下我们谈论 css 还是 js 并不重要。
  • @BurningIce - 你说得对,资源的类型并不重要。您链接到的问题具有相同的接受答案,这不适用于部分视图,因为它们不能使用 asp:Content 控件(解析器错误消息:内容控件必须是内容页面中的顶级控件或嵌套引用母版页的母版页。)还是我遗漏了什么?
  • 嗯,有趣的一点。我想这样做的唯一真正方法是将您的脚本/css 分成他们自己的部分视图。然后在头部部分的 asp:Content 中呈现部分内容。这就是我能想到的。
  • 好点,我确实错过了您使用部分视图的事实。

标签: c# asp.net-mvc asp.net-mvc-2 partial-views webforms-view-engine


【解决方案1】:

如果您使用的是 MVC3 和 Razor,将每页项目添加到您的部分的最佳方法是: 1) 从布局页面中调用 RenderSection() 2)在您的子页面中声明相应的部分:

/Views/Shared/_Layout.cshtml:

<head>
    <!-- ... Rest of your head section here ... ->
    @RenderSection("HeadArea")
</head>

/Views/Entries/Index.cshtml:

@section HeadArea {
    <link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" />
}

生成的 HTML 页面随后包含如下所示的部分:

<head>
    <!-- ... Rest of your head section here ... ->
    <link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" />
<head>

【讨论】:

  • 您的解决方案帮助了我。谢谢!
  • @Richard,您在此处描述的内容并非针对 OP 的问题,他说的是局部视图,而 _Layout.cshtml 是布局,而不是局部视图(即包含的实例)在Index.cshtml 内,并希望将脚本直接渲染到_layout.cshtml&lt;head&gt; 标记中。
  • 如果不是所有的view都有"HeadArea",没有的会报错。为避免这种情况,请在 _Layout.cshtml 中使用 @RenderSection("HeadArea", required:false)
  • 也许将评论 &lt;!-- ... Rest of your head section here ... -&gt; 更改为 @* ... Rest of your head section here ... *@ 参考:stackoverflow.com/q/12171576/125981
  • @ShimmyWeitzhandler 你的说法似乎不正确,因为这正是它所做的——在它所说的&lt;head&gt;&lt;/head&gt; 中渲染
【解决方案2】:

您可以使用HttpModule 来操作响应 HTML 并将任何 CSS/脚本引用移动到适当的位置。这并不理想,而且我不确定性能影响,但它似乎是解决问题的唯一方法,无需 (a) 基于 javascript 的解决方案,或 (b) 违反 MVC 原则。

【讨论】:

  • 同意“这并不理想”部分
【解决方案3】:

您还可以使用 Telerik 的 MVC 开源控件并执行以下操作:

<%= Html.Telerik().StyleSheetRegistrar()
                  .DefaultGroup(group => group
                     .Add("stylesheet.css"));

在头部 和

<%= Html.Telerik().ScriptRegistrar()
                  .DefaultGroup(group => group
                     .Add("script.js"));

在页面底部的脚本部分。

您可以继续在任何视图或部分视图上添加脚本,它们应该可以工作。

如果您不想使用该组件,您可以随时从那里激发自己并做一些更自定义的事情。

哦,使用 Telerik,您还可以选择组合和压缩脚本。

【讨论】:

  • +1,我喜欢这个解决方案。虽然我很想知道 Telerik 是如何开展业务的。我可能会去看看。
  • @Chev 他们通过让您使用“免费”版本来开展业务,然后在他们让您获得他们的产品后将其作为任何更新/较新版本的付费版本 - 这可能发生在任何人身上像这样的受版权保护的产品。
【解决方案4】:

以下内容仅在启用 javascript 时才有效。这是我用于您提到的场景的小帮手:

// standard method - renders as defined in as(cp)x file
public static MvcHtmlString Css(this HtmlHelper html, string path)
{
    return html.Css(path, false);
}
// override - to allow javascript to put css in head
public static MvcHtmlString Css(this HtmlHelper html, 
                                string path, 
                                bool renderAsAjax)
{
    var filePath = VirtualPathUtility.ToAbsolute(path);

    HttpContextBase context = html.ViewContext.HttpContext;
    // don't add the file if it's already there
    if (context.Items.Contains(filePath))
        return null;

    // otherwise, add it to the context and put on page
    // this of course only works for items going in via the current
    // request and by this method
    context.Items.Add(filePath, filePath);

    // js and css function strings
    const string jsHead = "<script type='text/javascript'>";
    const string jsFoot = "</script>";
    const string jsFunctionStt = "$(function(){";
    const string jsFunctionEnd = "});";
    string linkText = string.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\"></link>", filePath);
    string jsBody = string.Format("$('head').prepend('{0}');", linkText);

    var sb = new StringBuilder();

    if (renderAsAjax)
    {
        // join it all up now
        sb.Append(jsHead);
        sb.AppendFormat("\r\n\t");
        sb.Append(jsFunctionStt);
        sb.AppendFormat("\r\n\t\t");
        sb.Append(jsBody);
        sb.AppendFormat("\r\n\t");
        sb.Append(jsFunctionEnd);
        sb.AppendFormat("\r\n");
        sb.Append(jsFoot);
    }
    else
    {
        sb.Append(linkText);
    }

    return MvcHtmlString.Create( sb.ToString());
}

用法:

<%=Html.Css("~/content/site.css", true) %>

如前所述,仅在启用 javascript 的情况下才对我有用,因此限制了它的实用性。

【讨论】:

    【解决方案5】:

    另一种违反 MVC 原则的方法是使用 ViewModel 并响应页面的 Init 事件来设置所需的 css/javascript(即 myViewModel.Css.Add(".css") 并在您的head 在你的 viewmodel 上渲染 css-collection 的内容。

    为此,您创建一个基础视图模型类,您的所有其他模型都从该类继承,ala

    public class BaseViewModel
    {
        public string Css { get; set; }
    }
    

    在您的母版页中,您将其设置为使用此视图模型

    <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseViewModel>" %>
    

    你的头部可以写出Css属性的值

    <head runat="server">
        <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
        <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
    
        <%= Model.Css %>
    </head>
    

    现在,在您的局部视图中,您需要这段代码,这在 MVC 中有点难看

    <script runat="server">
        protected override void OnInit(EventArgs e)
        {
            Model.Css = "hej";
    
            base.OnInit(e);
        }
    </script>
    

    【讨论】:

    • 尽管 OP 没有提到部分的 ajax 请求,但这当然可以工作,但只能作为标准页面请求的一部分。我想挑战是让它适用于部分视图,无论是作为单个请求的一部分还是作为 ajax 刷新(除非通过 javascript 将其注入头部部分,否则我看不到它是如何工作的)
    • 哎呀!我一点也不喜欢这个。我宁愿违反将样式保留在 head 部分的协议,也不愿在我的 MVC 应用程序中抛弃关注点分离!
    【解决方案6】:

    您可以将部分视图加载到一个 javascript 块中,该块的样式会下降到头部,但考虑到您可能出于同样的原因希望头部部分中的 javascript 块,这将是愚蠢的。

    不过,我最近发现了一些很酷的东西。您可以将部分视图序列化为字符串并将其作为 JSON 对象的一部分发送回客户端。这使您还可以与视图一起传递其他参数。

    Returning a view as part of a JSON object

    您可以使用 JQuery 和 ajax 获取一个 JSON 对象并使用部分视图加载它,然后另一个 JSON 属性可能是您的样式块。 JQuery 可以检查您是否返回了样式块,如果是,则将其放入 head 部分。

    类似:

    $.ajax(
    {
         url: "your/action/method",
         data: { some: data },
         success: function(response)
         {
              $('#partialViewContainer).html(response.partialView);
              if (response.styleBlock != null)
                   $('head').append(response.styleBlock);
         }
    });
    

    【讨论】:

    • 好主意,这将起作用,但它取决于启用了 javascript 的用户(如果您正在加载脚本资源,这很公平,但对于 CSS 来说就不是那么多了。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多