Wie die HttpServerUtility.MapPath Methode in einem Thread oder Timer zugreifen?
-
02-07-2019 - |
Frage
Ich verwende eine System.Timers.Timer
in meiner Asp.Net Anwendung und ich brauche die HttpServerUtility.MapPath
Methode zu verwenden, die nur über HttpContext.Current.Server.MapPath
verfügbar zu sein scheint.
Das Problem ist, dass HttpContext.Current
ist null
wenn die Timer.Elapsed
Ereignis ausgelöst wird.
Gibt es eine andere Art und Weise einen Verweis auf ein HttpServerUtility Objekt zu bekommen? Ich konnte es in meiner Klasse Konstruktor injiziert. Ist es sicher ? Wie kann ich sicher sein, es wird nicht Müll am Ende des aktuellen Auftrags Collected sein?
Danke!
Lösung
Es ist möglich, HostingEnvironment.MapPath()
statt HttpContext.Current.Server.MapPath()
zu verwenden
Ich habe es noch nicht in einem Thread oder Timer-Ereignisse, obwohl versucht.
Einige (nicht lebensfähig) Lösungen, die ich in Betracht gezogen;
-
Die einzige Methode, die ich etwa auf
HttpServerUtility
Pflege istMapPath
. So als Alternative könnte ichAppDomain.CurrentDomain.BaseDirectory
verwenden und meine Pfade daraus bauen. Das wird aber scheitern, wenn Ihre Anwendung virtuelle Verzeichnisse (Bergwerk der Fall ist). verwendet
-
Ein weiterer Ansatz: Fügen Sie alle Pfade ich auf die die
Global
Klasse benötigen. Lösen Sie diese Pfade inApplication_Start
.
Andere Tipps
Ich weiß nicht, ob dies Ihr virtuellen Verzeichnisse Problem lösen, aber ich benutze diese für 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 ist nicht die perfekte Lösung, weil es eine sehr schwierige Klasse ist a href zu verspotten (siehe <= "https://stackoverflow.com/questions/8740498/how-to-unit-test-code-that-uses -hostingenvironment-MapPath "> Wie Unit-Test-Code, die HostingEnvironment.MapPath verwendet).
Für diejenigen, die Testbarkeit benötigen, ein besserer Weg könnte sein, Ihre eigene Weg-Mapper-Schnittstelle zu erstellen, wie vorgeschlagen von https: // Stackoverflow .com / a / 1231962/85196 , mit Ausnahme implementieren es als
public class ServerPathMapper : IPathMapper {
public string MapPath(string relativePath) {
return HostingEnvironment.MapPath(relativePath);
}
}
Das Ergebnis ist leicht mockable nutzt Hostingenvironment intern, und könnte sogar möglicherweise Adresse ase69s Sorge zugleich.
Können Sie nicht die MapPath Funktion aufrufen, bevor Sie den Timer starten und einfach das Ergebnis zwischenspeichern? Ist es unbedingt erforderlich, den MapPath Anruf innerhalb des Tick-Ereignisses hat?
Wenn die Timer verstreichen, gibt es keinen aktuellen HTTP-Kontext ist. Dies liegt daran, die Timer-Ereignisse nicht auf eine bestimmte HTTP-Anfrage in Zusammenhang stehen.
Was Sie tun sollten, ist HttpServerUtility.MapPath verwenden, wo HTTP Kontext zur Verfügung steht. Sie können es in einen der Anforderungspipeline Ereignisse (wie Page_Load) oder in einem Global.asax Ereignisse wie Application_Start.
Weisen Sie das MapPath Ergebnis einer Variablen zugänglich von der Timer.Elapsed Ereignis, wo Sie Path.Combine nutzen, um die Position einer bestimmten Datei, die Sie benötigen.
ich glaube, den Grund dafür, warum es zu diesem Zeitpunkt null ist (wenn man darüber nachdenkt), ist, dass der Timer abgelaufen Ereignis nicht als Teil einer HTTP-Anforderung auftritt (daher kein Zusammenhang). Es zeichnet sich durch etwas auf dem Server verursacht.