2008-11-26 16 views
10

He tratado de usar ASP.NET MVC por un tiempo, luego me enfrenta un problema que no quiero incluir todos mis js y css en la página maestra. ¿Pero cómo puedo registrarlo en el jefe de la página maestra desde mi punto de vista específico?Script & CSS Registration Helper en ASP.NET MVC?

Respuesta

10

La plantilla de página maestra predeterminada incluye un Content PlaceHolder para el encabezado. Si no es así se puede añadir fácilmente uno:

<head runat="server"> 
    <title></title> 
    <asp:ContentPlaceHolder ID="head" runat="server" /> 
</head> 

Sus puntos de vista a continuación, puede poner lo que quieran en la cabeza:

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server"> 
    <script src="Scripts/myScripts.js" type="text/javascript"></script> 
    <link href="Styles/myStyles.css" rel="stylesheet" type="text/css" /> 
</asp:Content> 
+0

¿No se trata de ASP.NET MVC y no de formularios web? –

+0

El motor Razor view se lanzó con MVC 3. Es decir * versión 3 *, ya que en dos versiones completas del producto se lanzaron antes de que se desarrollara/incluyera Razor. Antes de Razor, el motor de vista predeterminado era ASPX. – sliderhouserules

0

técnicamente debe poner todas sus js en la parte inferior de la página para obtener el mejor rendimiento.

Creo que la única forma en que podría hacer esto sería incluir el javascript en el VIewData y tener ViewData en la página maestra (no es una gran solución).

5

No parece que haya una opción sencilla 'incorporado en el marco de ASP.NET MVC por el momento. Si está utilizando un control de usuario (.ascx), que puede ser si está creando controles autónomos que también quieren administrar sus propios requisitos de JavaScript, entonces ni siquiera puede usar los marcadores de posición para ayudarlo.

Al final he creado una clase de ayuda y en ella hay un par de métodos:

private static SortedList<int, string> GetRegisteredScriptIncludes() 
{ 
    var registeredScriptIncludes = System.Web.HttpContext.Current.Items["RegisteredScriptIncludes"] as SortedList<int, string>; 

    if (registeredScriptIncludes == null) 
    { 
     registeredScriptIncludes = new SortedList<int, string>(); 
     System.Web.HttpContext.Current.Items["RegisteredScriptIncludes"] = registeredScriptIncludes; 
    } 

    return registeredScriptIncludes; 
} 

public static void RegisterScriptInclude(this HtmlHelper htmlhelper, string script) 
{ 
    var registeredScriptIncludes = GetRegisteredScriptIncludes(); 
    if (!registeredScriptIncludes.ContainsValue(script)) 
    { 
     registeredScriptIncludes.Add(registeredScriptIncludes.Count, script); 
    } 
} 

public static string RenderScripts(this HtmlHelper htmlhelper) 
{ 
    var registeredScriptIncludes = GetRegisteredScriptIncludes(); 
    var scripts = new StringBuilder(); 
    foreach (string script in registeredScriptIncludes.Values) 
    { 
     scripts.AppendLine("<script src='" + script + "' type='text/javascript'></script>"); 
    } 
    return scripts.ToString(); 
} 

Esa es una forma básica de todos modos para tratar de mostrar la forma en que funciona. Podría mejorarse de muchas maneras, pero en este momento simplemente filtra las solicitudes de inserción de scripts duplicados para usted. Cada vez que desee añadir un nuevo guión en el ascx (o aspx para el caso) puede hacerlo de esta manera:

<% 
    Html.RegisterScriptInclude(Url.Content("~/Scripts/MapLayers/MapLayer.js")); 
    Html.RegisterScriptInclude(Url.Content("~/Scripts/MapLayers/Vehicles.js")); 
%> 

Luego hay que recordar a la salida una vez que haya terminado. Esto se consigue haciendo que la siguiente llamada en el lugar de la página en la que desea dar salida a las etiquetas de script:

<%=Html.RenderScripts() %> 

parece funcionar hasta el momento para mí. Casi esperaba tener problemas de renderización dependiendo de en qué punto se llamara RenderScripts, especialmente si no se hubieran llamado todos los aún, pero hasta ahora parece que hace el trabajo. Si renderizas las secuencias de comandos por último, entonces no deberías tener problemas.

4

@Jason: ADVERTENCIA, no debería utilizar variables estáticas como esta ... En un contexto web, las variables estáticas se comparten entre todos los usuarios y todas las solicitudes de página. Me sorprende que no hayas tenido problemas con tu código. El principio está bien, pero el código es incorrecto y te dará problemas. En este caso, debe usar System.Web.HttpContext.Current.Items. Ver http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx para más.

+0

Gracias por el aviso: aprendes algo nuevo todos los días. Cambié el código de acuerdo con tus comentarios. – Jason

+0

La propiedad estática en cuestión es una referencia a HttpContext.Items (que es específica del contexto de solicitud, según su enlace, no una variable de miembro estática. Es relativamente seguro, a menos que se creen manualmente múltiples subprocesos que accedan a este miembro estático, en En ese caso, sería apropiado un bloqueo en los elementos de contexto actuales (lo mismo para el diccionario, o use un ConcurrentDictionary). – Tracker1

0

Mathew,

Me tomó un vistazo a su blog en Html.Css y Html.Script ayudantes. No me refiero a ser crítico, pero no veo ninguna mención en el blog sobre cómo los ayudantes de Css y Script abordarían el problema discutido aquí. El problema aquí es uno de necesitar referencias de scripts "registradas" en cualquier punto durante el proceso de renderizado, y posiblemente varias veces (en el caso de una plantilla o vista parcial que se usa varias veces y registra sus propios scripts), y luego generar los resultados agregados, sin duplicados, en una sola ubicación.

Si su solución soluciona esto, por favor corríjanme con alguna aclaración.

--Regards, Ken

Cuestiones relacionadas