Как получить доступ к методу HttpServerUtility.MapPath в потоке или таймере?
Я использую System.Timers.Timer
в моем приложении Asp.Net, и мне нужно использовать метод HttpServerUtility.MapPath
, который, по-видимому, доступен только через HttpContext.Current.Server.MapPath
.
Проблема в том, что HttpContext.Current
есть null
, когда срабатывает событие Timer.Elapsed
.
Есть ли другой способ получить ссылку на объект HttpServerUtility?
Я мог бы добавить его в конструктор моего класса. Это безопасно? Как я могу быть уверен, что это не будет мусор, собранный в конце текущего запроса?
Спасибо!
Ответы
Ответ 1
Можно использовать HostingEnvironment.MapPath()
вместо HttpContext.Current.Server.MapPath()
Я еще не пробовал это в событии нити или таймера.
Некоторые (нежизнеспособные) решения, которые я рассматривал;
-
Единственный метод, который мне волнует в HttpServerUtility
, - это MapPath
. Поэтому в качестве альтернативы я мог бы использовать AppDomain.CurrentDomain.BaseDirectory
и строить мои пути из этого. Но это не удастся, если ваше приложение использует виртуальные каталоги (Mine делает).
-
Другой подход:
Добавьте все пути, которые мне нужны, к классу Global
. Разрешите эти пути в Application_Start
.
Ответ 2
Я не знаю, решит ли это проблему с вашими виртуальными каталогами, но я использую это для 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('/', '\\');
}
Ответ 3
HostingEnvironment не является идеальным решением, потому что это очень сложный класс, чтобы высмеивать (см. Как unit test код, который использует HostingEnvironment.MapPath).
Для тех, кто нуждается в тестируемости, лучшим способом может быть создание вашего собственного интерфейса маршрута-карты, предложенного fooobar.com/questions/65796/..., за исключением того, чтобы реализовать его как
public class ServerPathMapper : IPathMapper {
public string MapPath(string relativePath) {
return HostingEnvironment.MapPath(relativePath);
}
}
Результат легко макетируется, он использует HostingEnvironment внутри и может даже потенциально адресовать ase69s в то же время.
Ответ 4
Не можете ли вы вызвать функцию MapPath перед запуском таймера и просто кешировать результат? Не обязательно ли иметь вызов MapPath внутри события tick?
Ответ 5
Когда таймер истекает, текущий HTTP-контекст отсутствует. Это связано с тем, что события таймера не связаны с конкретным HTTP-запросом.
Что вам нужно сделать, это использовать HttpServerUtility.MapPath, где доступен HTTP-контекст. Вы можете сделать это в одном из событий конвейера запроса (например, Page_Load) или в событии Global.asax, таком как Application_Start.
Назначьте результат MapPath переменной, доступной из события Timer.Elapsed, где вы можете использовать Path.Combine для получения местоположения определенного файла, который вам нужен.
Ответ 6
Я думаю, что причина того, почему в тот момент это значение null (если вы думаете об этом), заключается в том, что событие с истекшим таймером не встречается как часть HTTP-запроса (следовательно, контекста нет). Это вызвано чем-то на вашем сервере.