Come accedere al metodo HttpServerUtility.MapPath in un thread o un timer?


88

Uso un System.Timers.Timernella mia applicazione Asp.Net e devo utilizzare il HttpServerUtility.MapPathmetodo che sembra essere disponibile solo tramite HttpContext.Current.Server.MapPath. Il problema è che HttpContext.Currentè nullquando l' Timer.Elapsedevento si accende.

C'è un altro modo per ottenere un riferimento a un oggetto HttpServerUtility? Potrei iniettarlo nel costruttore della mia classe. È sicuro ? Come posso essere sicuro che non verrà raccolto in Garbage Collected alla fine della richiesta corrente?

Grazie!

Risposte:


142

È possibile utilizzare al HostingEnvironment.MapPath()posto diHttpContext.Current.Server.MapPath()

Tuttavia, non l'ho ancora provato in un thread o in un evento timer.


Alcune soluzioni (non praticabili) che ho considerato;

  • L'unico metodo che mi interessa HttpServerUtilityè MapPath. Quindi in alternativa potrei usare AppDomain.CurrentDomain.BaseDirectorye costruire i miei percorsi da questo. Ma questo fallirà se la tua app usa directory virtuali (la mia fa).

  • Un altro approccio: aggiungi tutti i percorsi di cui ho bisogno alla Globalclasse. Risolvi questi percorsi in Application_Start.


1
Si noti tuttavia che quanto sopra non funziona nelle versioni successive di IIS. In IIS7 l'avvio dell'applicazione può essere richiamato al di fuori di una richiesta http. Cioè, l'esempio di codice. Sono sicuro che HostingEnvironment.MapPath () funzionerà ancora come prima.
Robba

Ma HostingEnvironment.MapPath () restituisce un errore se viene passato e una stringa vuota per ottenere direttamente il percorso della cartella ... HttpContext.Current.Server.MapPath (""); -> funziona HostingEnvironment.MapPath (""); -> genera un errore
VSP

14

Non so se questo risolverà il tuo problema con le directory virtuali, ma lo uso per 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) dovrebbe essere path.Replace ('~', '.')
Slava

13

HostingEnvironment non è la soluzione perfetta perché è una classe molto difficile da deridere (vedere Come eseguire un test unitario del codice che utilizza HostingEnvironment.MapPath ).

Per coloro che necessitano di testabilità, un modo migliore potrebbe essere quello di creare la propria interfaccia di mappatura del percorso come proposto da https://stackoverflow.com/a/1231962/85196 , tranne implementarla come

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

Il risultato è facilmente mockable, utilizza HostingEnvironment internamente e potrebbe anche potenzialmente affrontare la preoccupazione di ase69 allo stesso tempo.


Ciò mi ha consentito di fornire un'implementazione per la risoluzione del percorso per un progetto API Web senza richiedere una dipendenza da System.Web o System.Net nella libreria a cui faceva riferimento. +1
David Peterson

Complimenti per DI e testabilità di questo approccio
Dilhan Jayathilake

2

Non puoi chiamare la funzione MapPath prima di avviare il timer e semplicemente memorizzare nella cache il risultato? È assolutamente necessario che la chiamata MapPath all'interno dell'evento tick?


2

Quando il timer è scaduto, non esiste un contesto HTTP corrente. Questo perché gli eventi del timer non sono correlati a una specifica richiesta HTTP.

Quello che dovresti fare è usare HttpServerUtility.MapPath dove è disponibile il contesto HTTP. Puoi farlo in uno degli eventi della pipeline di richiesta (come Page_Load) o in un evento Global.asax come Application_Start.

Assegna il risultato di MapPath a una variabile accessibile dall'evento Timer.Elapsed, dove puoi usare Path.Combine per ottenere la posizione di un file specifico di cui hai bisogno.


0

Penso che il motivo per cui è nullo in quel momento (se ci pensi), è che l'evento del timer trascorso non si verifica come parte di una richiesta HTTP (quindi non c'è contesto). È causato da qualcosa sul tuo server.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.