2009-04-28 15 views
7

La propiedad HttpContext.Current.Request.ApplicationPath representa el directorio virtual en IIS o WebDev.WebServer.¿Puedo acceder al nombre del directorio virtual en global.asax.cs?

HttpContext.Current.Request.ApplicationPath evaluates to "/virtualdirectory" 

Esto puede ser usado en conjunción con VirtualPathUtility para hacer una ruta relativa de la raíz:

VirtualPathUtility.ToAbsolute("~/images/cat.jpg", 
           HttpContext.Current.Request.ApplicationPath) 

// (this evaluates to "/virtualdirectory/images/cat.jpg") 

En IIS6 y WebDev.WebServer la solicitud objeto es disponible en global.asax.cs, pero se queja de que IIS7 no está disponible en el contexto actual. Por lo tanto, la segunda línea del código anterior funciona pero no en IIS7.

El problema es que necesito acceder al nombre del directroy virtual dentro de global.asax.cs. Lo necesito para construir algunos caminos que se utilizan en CSS creado dinámicamente. ¿Hay alguna forma alternativa de acceder a este valor?

Editar: Este es el error que se obtiene en IIS 7 para llamar HttpContext.Current.Request en global.asax.cs bajo Application_Start:

HttpException (0x80004005): Request is not available in this context] 
    System.Web.HttpContext.get_Request() +8789264 
+0

No entiendo la pregunta, HttpContext.Current está disponible en global.asax, ¿estás preguntando qué evento? –

+0

@deviant - HttpContext.Current está disponible, pero HttpContext.Current.Request no lo está. He editado la publicación para incluir el error –

Respuesta

13

encontrado por fin la respuesta simple!

HttpRuntime.AppDomainAppVirtualPath 

disponible de inmediato durante Application_Start

Esto es de la forma /myapplication incluyendo el / prefijo.

+0

¿Cómo obtener el nombre completo del directorio? –

+1

¡Entendido! HttpRuntime.AppDomainAppPath –

+1

Usted señor, señor Simon Weaver, lo tiene todo en marcha. – Jimbo

0

Se puede utilizar ResolveUrl ("~/images/cat.jpg") para construir tu camino?

Editar: ResolveUrl es un método de control, no sólo la clase de página, por lo que puede hacerlo de esta manera en vez (tal vez poco feo):

System.Web.UI.Control c = new Control(); 
String s = c.ResolveUrl(@"~/images/cat.jpg"); 
+0

no porque no hay ninguna instancia de la página –

0

Hmmm ... no estaba consciente del cambio de IIS7. Me pregunto si no sería más sencillo diferir esta operación hasta que tenga tenga una página. Por ejemplo, podría intentar poner algo "solo una vez" en Application_BeginRequest o Session_Start?

O (no está comprobado) para una auto-darse de baja del gancho:

public override void Init() { 
     base.Init(); 
     EventHandler handler = null; 
     handler = delegate { 
      // do stuff, once only 
      this.BeginRequest -= handler; 
     }; 
     this.BeginRequest += handler; 
    } 

El truco es hacer que una sola vez (si hay múltiples peticiones llegan a la vez); quizás un ctor estático? Por ejemplo, creo que esto dispara una sola vez, y sólo cuando hay una página disponible en contexto:

static class DelayedLoader { 
     static DelayedLoader() { 
      string s = VirtualPathUtility.ToAbsolute("~/images/cat.jpg", 
          HttpContext.Current.Request.ApplicationPath); 
     } 
     [MethodImpl(MethodImplOptions.NoInlining)] 
     public static void Init() { } 
    } 
    public override void Init() { 
     base.Init(); 
     EventHandler handler = null; 
     handler = delegate { 
      DelayedLoader.Init(); 
      this.BeginRequest -= handler; 
     }; 
     this.BeginRequest += handler; 
    } 
+0

Application_BeginRequest es probablemente la más segura. No estoy seguro del ciclo de vida de Session_Start, pero cuando traté de usarlo, el resultado de la página estaba dañado, creo que está en conflicto con mi compresión, lo cual es muy extraño, pero me quedaré con Begin_Request por ahora –

0

Este es el mejor que se me ocurrió: Application_BeginRequest (a través de la marca)

utilizo asax por lo raramente, que temporalmente lo había olvidado, recibes diferentes eventos con él. Hasta ahora había estado creando los sprites CSS en Application_Start. Moverlo a BeginRequest fue lo mejor que pude encontrar.

Un cheque booleano para cada solicitud es insignificante, pero estaría bien si hubiera una manera diferente.

protected void Application_Start() 
    { 
     RegisterRoutes(RouteTable.Routes); 
    } 

    protected void Application_BeginRequest() 
    { 
     if (!_initialized) 
     { 
      lock (thisLock) 
      { 
       _initialized = true; 
       GenerateCSSSprites(); 
      } 
     } 
    } 
+0

. parece teóricamente posible ejecutar 'GenerateCSSSprites' dos veces si dos solicitudes entran lo suficientemente cerca. Improbable, pero ... es posible que desee utilizar el bloqueo con doble verificación (es decir, comprobar _inicializar dentro del bloqueo también) u otro enfoque (como el truco del ctor estático). –

+0

oops. Gracias. Estaba tratando de evitar bloquear cada solicitud y logré perder eso. es importante ya que ejecutar GenerateCSSSprites dos veces causará una excepción porque agrega elementos a un diccionario global y se queja si esto se hace dos veces. gracias –

+0

en realidad se ejecutó dos veces cuando probé originalmente: GenerateCSSSprites(); _inicializado = verdadero esto es un poco extraño ya que soy la única persona que está accediendo a la página y aunque estoy accediendo a varios recursos en ese host el navegador no puede solicitarlos hasta que se presente la primera solicitud, por lo que IIS7 debe estar haciendo más de un 'pseudo 'solicitud de mi única solicitud real. wierd –

Cuestiones relacionadas