Make ASP.NET bundling specify media=screen for CSS bundle

22,829

Solution 1

I've found a more elegant solution.

I'm using the Styles.RenderFormat(format, bundle).

I have a BundlesFormats class with a property called PRINT and I use it like so:

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

And in the cshtml:

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

Solution 2

Well, it's an ugly hack, but hopefully the team will add a built-in way to do it in the next release.

This is how I solved it, maintaining the caching string and still being able to add the media attribute to the tag.

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

Guess I can turn this into an Html helper, will do that later and edit.

Solution 3

Another option to solve this issue, without compromising the debug ability, could be:

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);
}

What I'm doing is just appending the given html attributes to the end of the tags (on debug mode) or to the end of the only link tag (when minification/bundling are enabled).

The usage in views:

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

The rest of the code:

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();
}

I've wrote a blog post about this subject: http://danielcorreia.net/blog/quick-start-to-mvc4-bundling/

Solution 4

Unfortunately there isn't a great way to hook into how the tags are rendered currently, we thought about adding a hook so you could add your own method to render each script/style tag. It sounds like we do need to do that. Should be pretty simple to add, I'll create a work item to enable this scenario...

As a temporary workaround, if you are willing to lose the debug/release functionality that Styles.Render gives you, you can render a reference to the bundle using Styles.Url which would give you just the bundle url, you can embed that inside your own tag.

Solution 5

Why not just use @media print? Check out http://www.phpied.com/5-years-later-print-css-still-sucks/

Share:
22,829

Related videos on Youtube

GR7
Author by

GR7

Updated on July 09, 2022

Comments

  • GR7
    GR7 almost 2 years

    I'm just trying out ASP.NET 4.5 bundling and minification, and ran into an issue.

    I've got around 10 css files, of which 2 were originally referenced in the layout using the attribute media="screen".

    Since the syntax for adding a css to the bundle does not let you specify that such attribute should be added (makes sense, since the attribute would apply for the whole bundle), I was hoping to see an overload of @Styles.Render that would allow me to specify html attributes, like in other Html helpers, but there is none.

    There is an ugly solution, in which since I know the url of the bundle created, i could just craft the tag myself, but I'd lose the caching mechanism that is handled by ASP.NET by allowing it to render the tag itself.

    Is there a way to do this, am I missing something? Or is this just an oversight of the design team?

    • Adam Tal
      Adam Tal about 11 years
      Just use @Styles.RenderFormat (look at my answer for more detailed information)
  • GR7
    GR7 over 11 years
    Hao, I'm guessing you're a member of the ASP.NET team? It's weird that other Html Helpers do have overloads to allow the developer to set html attributes and the Bundle renderer methods dont. I'm thinking of hacking the generated tag (which would include the caching string) and just add the media attribute myself, that way i'd still have the caching and i can add it..i just thought it's really weird that this escaped the team.
  • GR7
    GR7 over 11 years
    found a way to do it through the framework, although it's not nice. I'll post it in a bit
  • Hao Kung
    Hao Kung over 11 years
    You can just do this: < link href="@Styles.Url("~/stylehseets/mediacss")" rel="stylesheet" type="text/css" media="screen" />
  • RickAndMSFT
    RickAndMSFT over 11 years
    Yes, Hao is the lead dev at MSFT for the optimization framework.
  • maets
    maets almost 11 years
    Just a note: This solution currently requires the prerelease version of "Microsoft ASP.NET Web Optimization Framework". The stable version does not have the "RenderFormat"-method.
  • IvanL
    IvanL over 10 years
    This is now part of the 1.1.0 release
  • drzaus
    drzaus over 10 years
    unless the blocking issue he refers to has been cleared up, this is a relevant point
  • Andrus
    Andrus over 10 years
    @GR7 After upgrading to VS 2013 Express For Web this start to produce 404 error. I posted it in stackoverflow.com/questions/20052278/… How to fix ?
  • GR7
    GR7 over 10 years
    @Andrus, have you tried any of the alternatives that other people have posted? I haven't revisited this code yet, but will certainly do soon, hopefully.
  • Andrus
    Andrus over 10 years
    No, I havent. Please confirm that your/Hao solution does not work in VS2013 then I start to look into other ways. In this case this should unmarked as answer
  • zacharydl
    zacharydl over 9 years
    I like this method because I can include the print-only file in my main styles bundle.
  • zacharydl
    zacharydl over 9 years
    Took me a minute to realize it can be done on one line: @Styles.RenderFormat("<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />", "~/bundles/Content/print")
  • Flinkman
    Flinkman almost 9 years
    I think this is the most elegant solution, IMO.
  • janv8000
    janv8000 almost 8 years
    What's the package version used here? Microsoft.AspNet.Web.Optimization.1.1.3 does not contain a generic Add method
  • SandRock
    SandRock almost 8 years
    Where does those thing come from? Add<T>() and StylesheetBundle