¿Cómo acceder al método HttpServerUtility.MapPath en un hilo o temporizador?


88

Utilizo un System.Timers.Timeren mi aplicación Asp.Net y necesito usar el HttpServerUtility.MapPathmétodo que parece estar solo disponible a través de HttpContext.Current.Server.MapPath. El problema es que HttpContext.Currentes nullcuando Timer.Elapsedse dispara el evento.

¿Hay otra forma de obtener una referencia a un objeto HttpServerUtility? Podría inyectarlo en el constructor de mi clase. Es seguro ? ¿Cómo puedo estar seguro de que no se recopilará basura al final de la solicitud actual?

¡Gracias!

Respuestas:


142

Es posible usar en HostingEnvironment.MapPath()lugar deHttpContext.Current.Server.MapPath()

Sin embargo, todavía no lo he probado en un hilo o evento de temporizador.


Algunas soluciones (no viables) que consideré;

  • El único método que me importa HttpServerUtilityes MapPath. Entonces, como alternativa, podría usar AppDomain.CurrentDomain.BaseDirectoryy construir mis caminos a partir de esto. Pero esto fallará si su aplicación usa directorios virtuales (el mío lo hace).

  • Otro enfoque: agregue todas las rutas que necesito a la Globalclase. Resuelve estos caminos en Application_Start.


1
Sin embargo, tenga en cuenta que lo anterior no funciona en versiones posteriores de IIS. En IIS7, el inicio de la aplicación se puede llamar fuera de una solicitud http. Es decir, el ejemplo de código. Estoy seguro de que HostingEnvironment.MapPath () seguirá funcionando como antes.
Robba

Pero HostingEnvironment.MapPath () da un error si lo pasa y una cadena vacía para obtener la ruta de la carpeta directamente ... HttpContext.Current.Server.MapPath (""); -> funciona HostingEnvironment.MapPath (""); -> genera error
VSP

14

No sé si esto resolverá su problema de directorios virtuales, pero lo uso para MapPath:

public static string MapPath(string path)
{
    if (HttpContext.Current != null)
        return HttpContext.Current.Server.MapPath(path);

    return HttpRuntime.AppDomainAppPath + path.Replace("~", string.Empty).Replace('/', '\\');
}

path.Replace ("~", string.Empty) debe ser path.Replace ('~', '.')
Slava

13

HostingEnvironment no es la solución perfecta porque es una clase muy difícil de burlar (consulte Cómo probar un código que usa HostingEnvironment.MapPath ).

Para aquellos que necesitan capacidad de prueba, una mejor manera podría ser crear su propia interfaz de mapeador de rutas según lo propuesto por https://stackoverflow.com/a/1231962/85196 , excepto implementarlo como

public class ServerPathMapper : IPathMapper { 
 public string MapPath(string relativePath) { 
      return HostingEnvironment.MapPath(relativePath); 
 } 
} 

El resultado es fácilmente burlable, utiliza HostingEnvironment internamente e incluso podría abordar la preocupación de ase69s al mismo tiempo.


Esto me permitió proporcionar una implementación para la resolución de rutas para un proyecto de API web sin requerir una dependencia a System.Web o System.Net en la biblioteca a la que hacía referencia. +1
David Peterson

Aprobado por DI y probabilidad de este enfoque
Dilhan Jayathilake

2

¿No puede llamar a la función MapPath antes de iniciar el temporizador y simplemente almacenar en caché el resultado? ¿Es absolutamente necesario tener la llamada MapPath dentro del evento tick?


2

Cuando transcurre el tiempo, no hay contexto HTTP actual. Esto se debe a que los eventos del temporizador no están relacionados con una solicitud HTTP específica.

Lo que debe hacer es usar HttpServerUtility.MapPath donde el contexto HTTP está disponible. Puede hacerlo en uno de los eventos de canalización de solicitudes (como Page_Load) o en un evento Global.asax como Application_Start.

Asigne el resultado de MapPath a una variable accesible desde el evento Timer.Elapsed, donde podría usar Path.Combine para obtener la ubicación de un archivo específico que necesita.


0

Creo que la razón por la que es nulo en ese momento (si lo piensa) es que el evento transcurrido del temporizador no ocurre como parte de una solicitud HTTP (por lo tanto, no hay contexto). Es causado por algo en su servidor.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.