【问题标题】:How to inject a CSS file from an ASP.NET MVC partial view (server-side)?如何从 ASP.NET MVC 部分视图(服务器端)注入 CSS 文件?
【发布时间】:2010-10-06 10:26:36
【问题描述】:

我有一个局部视图 (.ascx),它应该包含它自己的 CSS 文件,因为它在多个其他视图中使用。如何在页面服务器端注入样式表,即不使用 JavaScript?

【问题讨论】:

  • 我也认为这里的一个好的技术不会多次链接样式表,即使部分包含多次。
  • 为什么不能在部分的开头包含对样式表的引用?
  • @Justin 因为它不是有效的 XHTML。

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


【解决方案1】:

Dario - 由于将其用于部分视图,您将始终遇到文档的 <head> 部分已就位,因此无法修改的问题。如果您想保持 WC3 兼容,那么您必须通过 javascript 将任何进一步的 css 放入 head 部分。这可能是可取的,也可能不是可取的(如果您必须在关闭 javascript 的情况下满足下游浏览器的需求)。

您可能会想到的主要问题是您不能将<asp:contentplaceholders> 放入您的部分。这很痛苦(虽然母版页引用会将部分内容与特定母版页联系得太紧密,但这是可以理解的)。

为此,我创建了一个小助手方法,它可以完成基本的繁重工作以自动将 css 文件放入 head 部分。

edit - (根据 Omu 的 js 建议)这是一个不错的中途小屋:

// standard method - renders as defined in as(cp)x file
public static string Css(this HtmlHelper html, string path)
{
    return html.Css(path, false);
}
// override - to allow javascript to put css in head
public static string 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 "";

    // 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 sb.ToString();
}

用法:

<%=Html.Css("~/Content/yourstyle.Css")%>

或:

<%=Html.Css("~/Content/yourstyle.Css", true)%> // or false if you want!!

如果所有其他方法都失败了,则值得采取自负盈亏的方法。也可以调整上面的逻辑来点击 actionfilter 并将 css 添加到响应头等中,而不是输出 js 字符串。

【讨论】:

【解决方案2】:

您是否有理由不能只将样式表放在主视图页面中?除非它非常大,否则它不会导致您的页面在不使用时加载速度明显变慢,尤其是在压缩之后。

此外,如果部分视图正在通过 ajax 检索,您最终将多次重新下载 css 文件(取决于浏览器的缓存)。

【讨论】:

  • 我希望我的部分视图是独立的(此外,它是在服务器端呈现的,而不是通过 AJAX 加载的)。
【解决方案3】:

我不是 ASP.NET 或 MVC 专家,但我目前正在使用它进行项目。是否可以在母版页的头部包含类似的内容?

<asp:ContentPlaceHolder ID="HeadContent" runat="server"></asp:ContentPlaceHolder>

然后以某种方式将您的 CSS 放入内容占位符中?

<asp:Content ID="styleSheetHolder" ContentPlaceHolderID="HeadContent" runat="server">
  <link rel='stylesheet' href='yourstyle.css' type='text/css' />
</asp:Content>

看起来您必须从调用页面执行此操作,这会导致代码重复。我不知道如何解决这个问题。也许它可以通过 HTML 助手来完成。

【讨论】:

  • 您必须有意识地在部分之外(即在页面中)执行此操作。如果有一个解决方案可以在部分情况下适用于有条件包含的情况,那就太好了。
【解决方案4】:

我工作的一个地方有一个包含许多条件局部视图的站点,随着新事物添加到应用程序中,这些视图可能并且会不时发生变化。我们发现最好的方法是使用命名约定——将局部视图、样式表和脚本命名相同(当然扩展名除外)。

我们向页面的视图模型添加了一个或多个样式表、脚本和部分视图。然后,我们使用自定义 HTML 帮助器循环遍历每个内容部分中的相关数组并插入所需的内容。痛苦是必须为每个组件管理三个或更多文件,但至少我们能够减少托管页面的维护量。

不过,从来没有解决将局部视图放入局部视图的问题。

【讨论】:

    【解决方案5】:

    为什么不把链接标签放在你的局部视图中:

    <link rel="stylesheet" href="yourstyle.css" type="text/css" />
    

    【讨论】:

    • 这会使文档无效。
    • 我猜 html 验证器使其无效。但我确信浏览器正在正确呈现。我没有在规范中看到他们告诉你它只能在head 标签内
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    相关资源
    最近更新 更多