Come accedere al metodo HttpServerUtility.MapPath in un thread o timer?
-
02-07-2019 - |
Domanda
Uso un System.Timers.Timer
nella mia applicazione Asp.Net e ho bisogno di usare il metodo HttpServerUtility.MapPath
che sembra essere disponibile solo tramite HttpContext.Current.Server.MapPath
.
Il problema è che HttpContext.Current
è null
quando si attiva l'evento Timer.Elapsed
.
Esiste 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 sarà Garbage Collected alla fine della richiesta corrente?
Grazie!
Soluzione
È possibile utilizzare HostingEnvironment.MapPath ()
anziché HttpContext.Current.Server.MapPath()
Non l'ho ancora provato in un evento thread o timer.
Alcune soluzioni (non praticabili) che ho preso in considerazione;
-
L'unico metodo che mi interessa su
HttpServerUtility
èMapPath
. Quindi, in alternativa, potrei usareAppDomain.CurrentDomain.BaseDirectory
e costruire i miei percorsi da questo. Ma questo fallirà se la tua app utilizza directory virtuali (la mia lo fa). -
Un altro approccio: Aggiungi tutti i percorsi di cui ho bisogno alla classe
Global
. Risolvi questi percorsi inApplication_Start
.
Altri suggerimenti
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('/', '\\');
}
HostingEnvironment non è la soluzione perfetta perché è una classe molto difficile da deridere (vedi Come unit test del codice che utilizza HostingEnvironment.MapPath ).
Per coloro che necessitano di testabilità, un modo migliore potrebbe essere quello di creare la propria interfaccia path-mapper come proposta da https: // stackoverflow .com / a / 1231962/85196 , tranne implementarlo come
public class ServerPathMapper : IPathMapper {
public string MapPath(string relativePath) {
return HostingEnvironment.MapPath(relativePath);
}
}
Il risultato è facilmente deridibile, utilizza HostingEnvironment internamente e potrebbe persino indirizzare potenzialmente preoccupazione di ase69s allo stesso tempo.
Non puoi chiamare la funzione MapPath prima di avviare il timer e semplicemente memorizzare il risultato nella cache? È assolutamente necessario avere la chiamata MapPath all'interno dell'evento tick?
Allo scadere del timer, non esiste alcun contesto HTTP corrente. Questo perché gli eventi 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 della richiesta (come Page_Load) o in un evento Global.asax come Application_Start.
Assegna il risultato MapPath a una variabile accessibile dall'evento Timer.Elapsed, dove puoi usare Path.Combine per ottenere la posizione di un file specifico che ti serve.
Penso che il motivo per cui è nullo in quel momento (se ci pensate), è che l'evento trascorso dal timer non si verifica come parte di una richiesta HTTP (quindi non c'è contesto). È causato da qualcosa sul tuo server.