44

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

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

由于将 css 添加到包的语法不允许您指定应添加此类属性(这是有道理的,因为该属性将适用于整个包),我希望看到 @Styles.Render 的重载允许我指定 html 属性,就像在其他 Html 帮助程序中一样,但没有。

有一个丑陋的解决方案,因为我知道创建的包的 url,我可以自己制作标签,但我会失去由 ASP.NET 处理的缓存机制,因为它允许它自己呈现标签。

有没有办法做到这一点,我错过了什么?或者这只是设计团队的疏忽?

4

8 回答 8

77

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

我正在使用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")
于 2013-03-10T19:55:23.700 回答
14

好吧,这是一个丑陋的 hack,但希望团队会在下一个版本中添加一个内置的方法来做到这一点。

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

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

猜猜我可以把它变成一个 Html 助手,稍后再编辑。

于 2012-08-20T20:19:00.790 回答
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/

于 2012-12-05T22:40:53.913 回答
3

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

作为一种临时解决方法,如果您愿意失去 Styles.Render 为您提供的调试/发布功能,您可以使用 Styles.Url 呈现对捆绑包的引用,它只会为您提供捆绑包 url,您可以将其嵌入到您的自己的标签。

于 2012-08-20T19:04:44.653 回答
2

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

于 2013-06-13T08:36:44.933 回答
0

网络表单解决方案

在 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();
于 2016-03-23T23:45:51.840 回答
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"))
于 2020-07-13T17:30:07.750 回答
-1

这么复杂,为什么不使用:

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

?

于 2013-10-11T10:13:33.587 回答