Pregunta

¿Hay alguna manera de agregar referencias CSS a una página desde una vista parcial? y hacer que se representen en la página <head> (según lo exige el Especificaciones HTML 4.01)?

¿Fue útil?

Solución 4

Se puede utilizar un HttpModule para manipular la respuesta HTML y mover cualquier referencia CSS / script a los lugares apropiados. Esto no es ideal, y no estoy seguro de las implicaciones de rendimiento, pero parece que la única manera de resolver el problema sin que ninguno (a) una solución basada en Javascript, o (b) que trabajan en contra de los principios MVC.

Otros consejos

Si está utilizando MVC3 y la maquinilla de afeitar, la mejor manera de añadir objetos por-página a su sección es: 1) Llamar RenderSection () desde dentro de su diseño de página 2) Declarar una sección correspondiente dentro de su hijo páginas:

/Views/Shared/_Layout.cshtml:

<head>
    <!-- ... Rest of your head section here ... ->
    @RenderSection("HeadArea")
</head>

/Views/Entries/Index.cshtml:

@section HeadArea {
    <link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" />
}

La página HTML resultante a continuación incluye una sección que es similar al siguiente:

<head>
    <!-- ... Rest of your head section here ... ->
    <link rel="Stylesheet" type="text/css" href="/Entries/Entries.css" />
<head>

También puede utilizar los controles de código abierto Telerik para MVC y hacer algo como:

<%= Html.Telerik().StyleSheetRegistrar()
                  .DefaultGroup(group => group
                     .Add("stylesheet.css"));

en la sección de la cabeza y

<%= Html.Telerik().ScriptRegistrar()
                  .DefaultGroup(group => group
                     .Add("script.js"));

en la sección de escritura en el botttom de su página.

Y se puede seguir añadiendo secuencias de comandos en cualquier punto de vista, o vistas parciales y que debe trabajar.

Si no desea utilizar el componente siempre se puede inspirarse a partir de ahí y hacer algo más personalizado.

Oh, con Telerik también tiene opciones de combinar y comprimir las secuencias de comandos.

Usted podría tener el punto de vista de carga parcial en un bloque de javascript que cae en el estilo de la cabeza, pero eso sería tonto teniendo en cuenta que es probable que desee el bloque de JavaScript en la sección de cabeza por la misma razón.

Recientemente he descubierto algo muy fresco sin embargo. Puede serializar una vista parcial en una cadena y enviarla de vuelta al cliente como parte de un objeto JSON. Esto le permite pasar otros parámetros, así, junto con la vista.

Volviendo una vista como parte de un objeto JSON

Se podría agarrar un objeto JSON con jQuery y Ajax y lo han cargado con la vista parcial, y luego otra propiedad JSON podría ser su bloque de estilo. JQuery pudo comprobar que ya envió un bloque de estilo, si es así, soltarlo en la sección de la cabeza.

Algo así como:

$.ajax(
{
     url: "your/action/method",
     data: { some: data },
     success: function(response)
     {
          $('#partialViewContainer).html(response.partialView);
          if (response.styleBlock != null)
               $('head').append(response.styleBlock);
     }
});

Otro enfoque, que anula los principios de MVC, es utilizar un ViewModel y responder al evento de inicio de su página para configurar el CSS/javascript deseado (es decir, myViewModel.Css.Add(".css") y en su cabeza representar el contenido de la colección CSS en su modelo de vista.

Para hacer esto, crea una clase de modelo de vista base de la que todos sus otros modelos heredan, ala

public class BaseViewModel
{
    public string Css { get; set; }
}

En su página maestra la configuró para usar este modelo de vista.

<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage<BaseViewModel>" %>

y en su sección de encabezado puede escribir el valor de la propiedad CSS

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />

    <%= Model.Css %>
</head>

Ahora, en tu vista parcial necesitas tener este código, que es un poco feo en MVC

<script runat="server">
    protected override void OnInit(EventArgs e)
    {
        Model.Css = "hej";

        base.OnInit(e);
    }
</script>

La siguiente funcionaría sólo si se habilita Javascript. que es un poco de ayuda que yo uso para exactamente el escenario que mencionas:

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

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

uso:

<%=Html.Css("~/content/site.css", true) %>

funciona para mí, aunque como se ha dicho, sólo si está activado Javascript, lo que limita su utilidad un poco.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top