sábado, 22 de septiembre de 2012

[ASP.NET] Master Page - Referencia relativa a elementos de la página

 

Introducción


Durante el diseño de un sitio web la referencia a los elementos dentro de la página es un aspecto que genera errores en el desarrollo.

Este problema se potencia aun mas si se hace uso de Master Page, pues el diseño del master contendrá objetos que aplicaran con diferentes url relativas según donde se encuentre la página web desarrollada.

Recordemos que al final quien determina la url final es la pagina aspx y no el master page.

 

Detección de problema


Imaginemos que tenemos un desarrollo simple de solo dos paginas y una master page, como ser:

imagen1

Como se observa en la estructura del ejemplo tenemos el master page se encuentra en el raíz del sitio junto con una pagina de inicio, pero también observamos una carpeta que contendrá paginas pertenecientes a un modulo de administración, ambos aspx observados implementaran el mismo MasterPage.

Un diseño lógicamente nos indicaría que aseguráramos que la vista del master page en el Visual Studio este correcta, por lo que si usáramos:

imagen2

En el diseñador del Visual Studio veríamos que parece ir todo sobre ruedas.

Al aplicar el master page a la pagina Default.aspx, no notaríamos mayor problema ya que al igual que la master están ambos al mismo nivel.

imagen3

Pero que sucede si vamos a la pagina que se encuentra dentro de la carpeta Admin

imagen4

Rápidamente se observa que la imagen que define la master no puede ser resuelta adecuadamente, aquí no se observa pero esto mismo que claramente se aprecia con la imagen sucederá con los archivo .js, si se ejecuta la pagina el código cliente fallara porque las librerías de jquery no podrán encontrarse.

 

Resolver el problema


Existen algunas técnicas que pueden ser usadas para resolver el problema de la url relativa.

Una forma simple de lograrlo es por medio del ResolveClientUrl(), si bien en tiempo de diseño no se podrá apreciar el recurso de forma visual en el diseñador del Visual Studio

imagen5

se podrá asegurar con esta técnica que sin importar en que nivel se encuentre la pagina que implementa la master las url generada resolverán de manera correcta.

Ahora al acceder al código de la pagina que se encuentra dentro de la carpeta a un nivel diferente

imagen6

se ha creado la ruta relativa correcta desde la master.

Desde la pagina Default.aspx por encontrarse al mismo nivel la url es distinta pero sigue resolviendo de forma adecuada

imagen7

 

Otras técnicas


Existen otras técnicas que implican código, se podría usar

protected void Page_Load(object sender, EventArgs e)
{
    ScriptManager.RegisterClientScriptInclude(Page, typeof(Page), "jquery", ResolveClientUrl(@"~/Scripts/jquery-1.4.1.js"));
    ScriptManager.RegisterClientScriptInclude(Page, typeof(Page), "jquery.validate", ResolveClientUrl(@"~/Scripts/jquery.validate.js"));
}

El tema es que el ScriptManager.RegisterClientScriptInclude() crea la definición del <script> dentro del tag <form> por lo que el código que podríamos definir en el <head> causaría error.

También se podría intentar usar

protected void Page_Load(object sender, EventArgs e)
{

    HtmlGenericControl jqueryctrl = new HtmlGenericControl("script");
    jqueryctrl.Attributes.Add("type", "text/javascript");
    jqueryctrl.Attributes.Add("src", ResolveClientUrl(@"~/Scripts/jquery-1.4.1.js"));
    this.Page.Header.Controls.Add(jqueryctrl);

    HtmlGenericControl jqvalidatectrl = new HtmlGenericControl("script");
    jqvalidatectrl.Attributes.Add("type", "text/javascript");
    jqvalidatectrl.Attributes.Add("src", ResolveClientUrl(@"~/Scripts/jquery.validate.js"));
    this.Page.Header.Controls.Add(jqvalidatectrl);


}

Esto resolvería el problema anterior colocando el tag <script> dentro del <head>, pero aun así lo ubica por debajo de la sección del ContentPlaceHolder que se define como lugar donde colocar el script de la pagina requiere

Es por eso que lo mas acertado seria definir el html donde se necesita utilizando el ResolveClientUrl()

 

Código


 

13 comentarios:

  1. Excelente maestro Leandro, muchas gracias.

    Tienes razón, esto resuelve mucho mejor mi problema con las url desde la master.

    ResponderEliminar
  2. Muchas gracias Leandro, hace varios días que estoy en el tema de las master page y me has ayudado mucho.

    ResponderEliminar
  3. te recomiendo observar las referencias relativas propias de html:
    relativo a la raíz del dominio "/ruta.."
    relativo a la carpeta "./ruta.."

    ResponderEliminar
  4. hola Juan

    gracias por el consejo
    lo bueno es que ahora que estoy mas con asp.net mvc 4 estos problemas ya no se presentan se pude usar el ~/ que el propio mvc lo resuelve directamente

    saludos

    ResponderEliminar
  5. Muchas gracias, me sacaste de un dolor de cabeza.

    ResponderEliminar
  6. Excelente, me ayudo con mi problema.
    Saludos Maestro Leandro

    ResponderEliminar
  7. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  8. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  9. Muchas gracias Leandro. Este muchos otros de tus aportes me estan ayudando en el proyecto de mi graduacion y prometo tendras una mencion especial si al final, es la voluntad del SEÑOR me gradue. DIOS te bendiga por tomarte el tiempo de compartir parte de esa inteligencia que DIOS te ha dado

    ResponderEliminar
  10. Hola Leandro,

    Utilice lo que mencionas en tu articulo pero no me resulto:

    < link href="<%= ResolveClientUrl("~/css/Propiedades.css") %>" type="text/css" rel="stylesheet" />

    Si lo dejo como estaba anteriormente solo acciona los estilos a los objectos , todo lo relacionado con simples divs no le aplica el estilo que le marco.

    Este problema viene del Foro:
    http://social.msdn.microsoft.com/Forums/es-ES/23166f7e-7d0f-457b-9418-7bdac5f750ec/clase-hover-en-webform-con-masterpage?forum=vcses#23166f7e-7d0f-457b-9418-7bdac5f750ec

    Gracias,

    Jonathan

    ResponderEliminar
  11. hola Jonathan

    respondi en la consulta del foro

    saludos

    ResponderEliminar
  12. Leandro como estas? gracias por todo como siempre.
    consulta recomendas la utilización de bundles?

    ResponderEliminar
  13. Hola Leandro, el tema es viejo pero tengo una necesidad, como puedo ResolveClientUrl ponerle parametros dinamicos desde js?
    ya que las variables que le pongo dentro, marca que no existen
    Muchas gracias por tú tiempo y ayuda.

    ResponderEliminar