2008-10-27 20 views
27

En el escenario WebForms normal, cualquier URL relativos a la raíz (por ejemplo ~/carpeta/archivo.txt) dentro archivos CSS, tales como:ASP.NET MVC automático de URL de resolución en los archivos CSS

.form { background-image: url(~/Content/Images/form_bg.gif); } 

se se resolverá automáticamente durante el tiempo de ejecución si especifico

<head runat="server"> 

En la página de referencia.

Sin embargo, eso ya no ocurre en un sitio web ASP.NET MVC Beta1.

¿Hay alguna manera de habilitar esta funcionalidad sin recurrir a hacks o archivos CSS-loader? Como tal vez HttpModules o algo así?

¿O no estoy diseñando correctamente mi sitio web? ¿Qué se supone que es un buen diseño?

Dado que ASP.NET WebForms original ya tiene esta característica, preferiría utilizar cualquier funcionalidad existente si fuera posible. Pero no tengo mucha idea.

Esta aplicación web se implementará en varios entornos donde la carpeta ~ root puede no ser obvia.


EDIT: me refiero a la url en el contenido del archivo no url del archivo en sí.

Respuesta

46

No me molestaría con el carácter auto-root-finding ~. Entiendo que quiere que la misma solución funcione donde el directorio raíz difiere entre las implementaciones, pero dentro del documento CSS no debería tener problemas al usar rutas relativas. Las rutas en el documento CSS (a la URL de la imagen en su ejemplo) siempre serán relativas a la ubicación del archivo CSS, independientemente de la ruta de acceso de cualquier página que cargue ese archivo CSS. Entonces, si sus imágenes están en ~/Content/Images y sus hojas de estilo están en ~/Content/Stylesheets, siempre podrá usar background-image: url(../Images/form_bg.gif); y funcionará independientemente de la ubicación de la página que cargue la hoja de estilo.

¿Hay alguna razón por la que esto no funcione?

+0

Ah ... era estúpido una vez más. Esto debería funcionar. Voy a tratar de salir. Estaba acostumbrado a tener tilde (~) rutas relativas en CSS en formularios web. Y siempre funciona así que esperaba lo mismo para MVC pero duh .... – chakrit

+0

Tiene algunos problemas con los viejos navegadores de Mac ... pero no creo que nadie los soporte más. – chakrit

+0

También tiene algunos problemas con versiones antiguas de Netscape que analizaron esa regla de estilo de imagen de fondo de una manera no estándar, que es la última vez que me encontré con este problema, de ahí mi sugerencia de utilizar un IHttpModule.Al final, sin embargo, quizás esto servirá, ya que es probable que Netscape haya desaparecido hace mucho tiempo. –

4

Herearesomeresources en la implementación de IHttpModule para interceptar las peticiones web a su aplicación ...

escritura/adaptar uno para comprobar si el tipo de archivo (por ejemplo pseudocódigo: si (solicitud termina con ".css") ...)

a continuación, utilizar una expresión regular para reemplazar todas las instancias de "~ /" con System.Web.VirtualPathUtility.ToAbsolute ("~ /")

no sé lo que esto hará que el rendimiento, corriendo cada solicitud a través de este tipo de filtro, pero probablemente puedas virar con su archivo web.config y/o sus rutas URL MVC para canalizar todas las solicitudes .css a través de este tipo de filtro, omitiendo el mismo para otros archivos.

Ahora que lo pienso, probablemente puedas lograr el mismo efecto dentro de una aplicación ASP.NET MVC al señalar todas tus referencias de CSS en un controlador especial. Acción que realiza este tipo de preprocesamiento para ti. dudo que sea tan eficiente como un IHttpModule sin embargo.

0

Puede usar un URL Rewriter para arreglar la URL a medida que la solicitud entra, aunque no estoy tan seguro de que sea tan elegante como un truco en este caso.

+0

¡Ah idea agradable! Podría usar el marco de enrutamiento para hacer eso. déjame probar – chakrit

0

Creé una clase utilitaria PathHelper que me proporciona todas las rutas que necesito. Por ejemplo

<link href="<%=PathHelper.CssUrl("FormulaIndex.css")%>" rel="Stylesheet" type="text/css"/> 

me da la URL completa correcta con la ayuda de System.Web.VirtualPathUtility.ToAbsolute() y mi propia convención (contenido/css/yourFile.css).

Hice lo mismo para js, xml, t9n, fotos ... Es central, reutilizable y ahora solo tuve que cambiar una línea para ver el movimiento de la carpeta de scripts desde content/js hasta Scripts en todos mis sitios web y páginas.

Un movimiento idiota si me preguntas, pero es la realidad en la actual versión beta :(

+0

Me refiero a las URL en el CONTENIDO del archivo, no la url del archivo en sí. – chakrit

+0

I c. –

1

Si usted está tratando de analizar el ~/ de cualquier archivo, incluyendo archivos de texto, javascript, etc, se puede escribir un controlador que asigna un filtro a la misma y se puede utilizar eso para buscar esos caminos ... por ejemplo ...

public class StringParsingFilter : MemoryStream { 

    public Stream OriginalStream { 
     get { return this.m_OriginalStream; } 
     set { this.m_OriginalStream = value; } 
    } 
    private System.IO.Stream m_OriginalStream; 

    public StringParsingFilter() : base() { 
     this.m_OriginalStream = null; 
    } 

    public override void Flush() { 
     this.m_OriginalStream.Flush(); 
    } 

    public override void Write(byte[] buffer, int offset, int count) { 

     //otherwise, parse for the correct content 
     string value = System.Text.Encoding.Default.GetString(buffer); 
     string contentType = HttpContext.Current.Response.ContentType; 

     //Do any parsing here 
     ... 

     //write the new bytes to the stream 
     byte[] bytes = System.Text.Encoding.Default.GetBytes(value); 
     this.m_OriginalStream.Write(bytes, offset, count + (bytes.Length - buffer.Length)); 

    } 

} 

y vas a escribir un controlador personalizado para saber cuándo asigna este filtro ... como el siguiente ...

public class FilterControlModule : IHttpModule { 

    public void Init(HttpApplication context) { 
     HttpApplication oAppContext = context; 
     oAppContext.BeginRequest += new EventHandler(_HandleSettingFilter);       
    } 

    private void _HandleSettingFilter(object sender, EventArgs e) { 

     //You might check the file at this part to make sure 
     //it is a file type you want to parse 
     //if (!CurrentFile.isStyleSheet()) { return; } 
     ... 

     //assign the new filter 
     StringParsingFilter filter = new StringParsingFilter(); 
     filter.OriginalStream = HttpContext.Current.Response.Filter; 
     HttpContext.Current.Response.Filter = (Stream)filter; 

    } 

} 

En realidad, puede haber sido más fácil decir "buscar IHttpModules", pero este es un código que he utilizado para analizar archivos de rutas distintas de los archivos ASP.net.

También deberá cambiar algunas cosas en su configuración de IIS para permitir que los archivos sean analizados configurando ASP.net ISAPI para que sea un comodín para todos los archivos que se manejan. Puede ver más at this website, si está usando IIS6 que es ...

También puede usar esto para modificar cualquier tipo de archivo para poder asignar algunos filtros para imágenes, algunos para javascript o hojas de estilo o ... realmente cualquier cosa ...

+0

¡Gracias! Ya tengo asignaciones de comodines hechas a primera vista. Conozco los módulos http, pero como el formulario web ASP.NET * ya * tiene esto, estaba pensando que debe haber una manera más simple ... como vincular algunos módulos existentes de formularios web ASP.NET que se han eliminado de MVC. Gracias de todos modos, podría usar tu código – chakrit

5

Un truco que he utilizado en el pasado, era para hacer realidad mi archivo CSS tiene una extensión .ASPX, y establezca la propiedad ContentType en la página de firma:

<%@ Page Language="C#" ContentType="text/css" %> 

body { 
    margin: 0; 
    padding: 0; 
    background: #C32605 url(<%= ResolveUrl("~/Content/themes/base/images/BodyBackground.png") %>) repeat-x; 
    font-family: Verdana, Arial, sans-serif; 
    font-size: small; 
    color: #d7f9ff; 
} 

Esto asegurará que el archivo CSS pasa por el marco ASP.NET y reemplaza el código del lado del servidor con su ruta relativa.

Cuestiones relacionadas