asp.net-mvc - una - razor mvc
Hacer agrupamiento ASP.NET especificar medios=pantalla para paquete CSS (7)
Estoy probando la agrupación y minificación de ASP.NET 4.5, y encontré un problema.
Tengo alrededor de 10 archivos css, de los cuales 2 fueron referenciados originalmente en el diseño usando el atributo media = "screen".
Dado que la sintaxis para agregar un CSS al paquete no le permite especificar que dicho atributo deba agregarse (tiene sentido, ya que el atributo se aplicaría a todo el paquete), esperaba ver una sobrecarga de @ Styles.Render que haría Permítanme especificar atributos html, como en otros helpers Html, pero no hay ninguno.
Existe una solución desagradable, en la que, dado que conozco la url del paquete creado, podría crear la etiqueta yo mismo, pero perdería el mecanismo de almacenamiento en caché que maneja ASP.NET al permitirle renderizar la etiqueta.
¿Hay alguna manera de hacer esto? ¿Me estoy perdiendo algo? ¿O es solo un descuido del equipo de diseño?
Solución de formularios web
En 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"));
Página principal:
<asp:Literal runat="server" ID="litCssPrint" />
Archivo de código de página maestra:
litCssPrint.Text = Styles.RenderFormat(@"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />", "~/bundles/printCSS").ToHtmlString();
¿Por qué no usar simplemente @media print? Echa un vistazo a http://www.phpied.com/5-years-later-print-css-still-sucks/
Bueno, es un hack feo, pero con suerte el equipo agregará una forma integrada de hacerlo en la próxima versión.
Así es como lo resolví, manteniendo la cadena de almacenamiento en caché y aún poder agregar el atributo de medios a la etiqueta.
@{
var cssMediaBundleUrl = BundleTable.Bundles.ResolveBundleUrl("~/stylesheets/mediacss", true);
}
<link href="@cssMediaBundleUrl" rel="stylesheet" type="text/css" media="screen" />
Supongo que puedo convertir esto en un ayudante Html, lo haré más tarde y lo editaré.
Encontré una solución más elegante.
Estoy usando Styles.RenderFormat(format, bundle)
.
Tengo una clase BundlesFormats
con una propiedad llamada PRINT
y la uso así:
public class BundlesFormats
{
public const string PRINT = @"<link href=""{0}"" rel=""stylesheet"" type=""text/css"" media=""print"" />";
}
Y en el cshtml:
@Styles.RenderFormat(BundlesFormats.PRINT, "~/bundles/Content/print")
Lamentablemente, no hay una gran manera de engancharnos a cómo se representan actualmente las etiquetas, pensamos en agregar un gancho para que pueda agregar su propio método para representar cada etiqueta de script / estilo. Parece que tenemos que hacer eso. Debería ser bastante simple de agregar, crearé un elemento de trabajo para habilitar este escenario ...
Como una solución temporal, si está dispuesto a perder la funcionalidad de depuración / liberación que le proporciona Styles.Render, puede hacer una referencia al paquete usando Styles.Url que le daría solo la url del paquete, puede insertar eso dentro de su propia etiqueta.
Otra opción para resolver este problema, sin comprometer la capacidad de depuración, podría ser:
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);
}
Lo que estoy haciendo es simplemente agregar los atributos html dados al final de las etiquetas (en el modo de depuración) o al final de la única etiqueta de enlace (cuando la minificación / agrupación está habilitada).
El uso en vistas:
@Bundles.Render("~/css/print", new { media = "print" })
El resto del código:
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();
}
He escrito una publicación en el blog sobre este tema: http://danielcorreia.net/blog/quick-start-to-mvc4-bundling/
Tan complicado, por qué no usar:
bundles.Add<StylesheetBundle>("~/Css/site.css", b => b.Media = "screen");
?