使ASP.NET捆绑为CSS捆绑指定media = screen

时间:2012-08-20 17:30:54

标签: asp.net-mvc asp.net-mvc-4 bundling-and-minification asp.net-optimization

我只是尝试ASP.NET 4.5捆绑和缩小,并遇到了一个问题。

我有大约10个css文件,其中2个最初使用属性media =“screen”在布局中引用。

由于将css添加到bundle的语法不允许你指定应该添加这样的属性(有意义,因为该属性将适用于整个bundle),我希望看到@Styles的重载。渲染允许我指定html属性,就像在其他Html助手中一样,但没有。

有一个丑陋的解决方案,因为我知道创建的bundle的url,我可以自己制作标签,但是我会失去ASP.NET处理的缓存机制,允许它渲染标记本身。

有没有办法做到这一点,我错过了什么吗?或者这仅仅是对设计团队的监督?

8 个答案:

答案 0 :(得分:74)

我找到了一个更优雅的解决方案。

我正在使用Styles.RenderFormat(format, bundle)

我有一个BundlesFormats类,其中包含一个名为PRINT的属性,我这样使用它:

public class BundlesFormats
{
    public const string PRINT = @"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />";
}

在cshtml中:

@Styles.RenderFormat(BundlesFormats.PRINT, "~/bundles/Content/print")

答案 1 :(得分:13)

嗯,这是一个丑陋的黑客,但希望团队会在下一个版本中添加一个内置的方法来实现它。

这是我解决它的方法,维护缓存字符串并仍然能够将媒体属性添加到标记。

@{
    var cssMediaBundleUrl = BundleTable.Bundles.ResolveBundleUrl("~/stylesheets/mediacss", true);
}
<link href="@cssMediaBundleUrl" rel="stylesheet" type="text/css" media="screen" />

猜猜我可以把它变成一个Html帮助器,稍后会这样做并编辑。

答案 2 :(得分:6)

在不影响调试能力的情况下解决此问题的另一个选择可能是:

public static IHtmlString Render(string path, IDictionary<string, object> htmlAttributes)
{
    var attributes = BuildHtmlStringFrom(htmlAttributes);

#if DEBUG
    var originalHtml = Styles.Render(path).ToHtmlString();
    string tagsWithAttributes = originalHtml.Replace("/>", attributes + "/>");
    return MvcHtmlString.Create(tagsWithAttributes);
#endif

    string tagWithAttribute = string.Format(
        "<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\"{1} />", 
        Styles.Url(path), attributes);

    return MvcHtmlString.Create(tagWithAttribute);
}

我正在做的只是将给定的html属性附加到标记的末尾(在调试模式下)或附加到唯一链接标记的末尾(当启用缩小/捆绑时)。

视图中的用法:

@Bundles.Render("~/css/print", new { media = "print" })

其余代码:

public static IHtmlString Render(string path, object htmlAttributes)
{
    return Render(path, new RouteValueDictionary(htmlAttributes));
}

private static string BuildHtmlStringFrom(IEnumerable<KeyValuePair<string, object>> htmlAttributes)
{
    var builder = new StringBuilder();

    foreach (var attribute in htmlAttributes)
    {
        builder.AppendFormat(" {0}=\"{1}\"", attribute.Key, attribute.Value);
    }

    return builder.ToString();
}

我写了一篇关于这个主题的博文:http://danielcorreia.net/blog/quick-start-to-mvc4-bundling/

答案 3 :(得分:3)

不幸的是,没有一种很好的方式来挂钩当前如何呈现标记,我们考虑添加一个钩子,以便您可以添加自己的方法来呈现每个脚本/样式标记。听起来我们确实需要这样做。添加起来应该非常简单,我将创建一个工作项来启用此方案......

作为一种临时解决方法,如果您愿意丢失Styles.Render为您提供的调试/发布功能,您可以使用Styles.Url呈现对该包的引用,这样可以为您提供捆绑网址,您可以嵌入在你自己的标签内。

答案 4 :(得分:2)

为什么不直接使用@media打印?查看http://www.phpied.com/5-years-later-print-css-still-sucks/

答案 5 :(得分:0)

Web表单解决方案

在BundleConfig.cs中:

//Print css must be a separate bundle since we are going to render it with a media=print
Bundles.Add(new StyleBundle("~/bundles/printCSS").Include("~/Content/Print.css"));

母版页

<asp:Literal runat="server" ID="litCssPrint" />

母版页代码文件:

litCssPrint.Text = Styles.RenderFormat(@"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />", "~/bundles/printCSS").ToHtmlString();

答案 6 :(得分:0)

我进一步采纳了Adam Tal的建议。

我可能对其进行了过度编码,但是出于可读性考虑,我创建了一个静态类来模仿Styles.Render格式。

public static class StyleExtensions
{
    public enum Format
    {
        Async,
        Preload,
    }

    public static IHtmlString Render(string contentPath, Format format)
    {
        switch (format)
        {
            case Format.Async:
            return contentPath.ToAsyncFormat();
            case Format.Preload:
            return contentPath.ToPreloadFormat();
            default:
            return new HtmlString(string.Empty);
        }
    }

    public static IHtmlString RenderAsync(string contentPath)
    {
        return contentPath.ToAsyncFormat();
    }

    public static IHtmlString RenderPreload(string contentPath)
    {
        return contentPath.ToPreloadFormat();
    }

    public static IHtmlString ToAsyncFormat(this string contentPath)
    {
        return Styles.RenderFormat("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}\" media=\"print\" onload=\"this.media='all';this.onload=null;\">", contentPath);
    }

    public static IHtmlString ToPreloadFormat(this string contentPath)
    {
        return Styles.RenderFormat("<link rel=\"preload\" href=\"{0}\" as=\"style\" onload=\"this.rel='stylesheet';this.onload=null;\">", contentPath);
    }
}

我可能会擦除直接构造函数或枚举构造函数,并且您实际上也可以将字符串扩展名也放入方法中,这取决于对您更有意义的方法,但是您可以相应地使用以下两种方法之一进行调用:

@StyleExtensions.Render("~/Content/bundle-bootstrap", StyleExtensions.Format.Preload)
@StyleExtensions.Render("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap", StyleExtensions.Format.Preload)
@StyleExtensions.Render(Url.Content("~/Content/Styles/Primary.min.css"), StyleExtensions.Format.Async)

@StyleExtensions.RenderPreload("~/Content/bundle-bootstrap")
@StyleExtensions.RenderPreload("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;700&display=swap")
@StyleExtensions.RenderAsync(Url.Content("~/Content/Styles/Primary.min.css"))

答案 7 :(得分:-1)

如此复杂,为什么不使用:

bundles.Add<StylesheetBundle>("~/Css/site.css", b => b.Media = "screen");