Как получить доступ к HttpServerUtility.Метод MapPath в потоке или таймере?
-
02-07-2019 - |
Вопрос
Я использую System.Timers.Timer
в моем приложении Asp.Net и мне нужно использовать HttpServerUtility.MapPath
метод, который, кажется, доступен только через HttpContext.Current.Server.MapPath
.Проблема в том, что HttpContext.Current
является null
когда Timer.Elapsed
срабатывает событие.
Есть ли другой способ получить ссылку на объект HttpServerUtility?Я мог бы внедрить это в конструктор моего класса.Безопасно ли это ?Как я могу быть уверен, что в конце текущего запроса не будет собран мусор?
Спасибо!
Решение
Это можно использовать HostingEnvironment.MapPath()
вместо того, чтобы HttpContext.Current.Server.MapPath()
Однако я еще не пробовал это в потоке или событии таймера.
Некоторые (нежизнеспособные) решения, которые я рассматривал;
Единственный метод, который меня волнует на
HttpServerUtility
являетсяMapPath
.Так что в качестве альтернативы я мог бы использоватьAppDomain.CurrentDomain.BaseDirectory
и строю свои пути исходя из этого. Но это приведет к сбою, если ваше приложение использует виртуальные каталоги (У меня так и есть).Другой подход:Добавьте все пути, которые мне нужны, к
Global
класс.Разрешите эти пути вApplication_Start
.
Другие советы
Я не знаю, решит ли это проблему с вашими виртуальными каталогами, но я использую это для 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 не является идеальным решением, потому что это очень сложный класс для моделирования (см. Как выполнить модульное тестирование кода, использующего среду HostingEnvironment.MapPath).
Для тех, кому нужна возможность тестирования, лучшим способом может быть создание собственного интерфейса path-mapper, как предложено https://stackoverflow.com/a/1231962/85196, за исключением реализации его как
public class ServerPathMapper : IPathMapper {
public string MapPath(string relativePath) {
return HostingEnvironment.MapPath(relativePath);
}
}
Результат легко поддается макетированию, использует HostingEnvironment внутренне и даже потенциально может адресовать беспокойство ase69s в одно и то же время.
Можете ли вы не вызывать функцию MapPath перед запуском таймера, а просто кэшировать результат?Абсолютно ли необходимо иметь вызов MapPath внутри события tick?
По истечении таймера текущий HTTP-контекст отсутствует.Это связано с тем, что события таймера не связаны с конкретным HTTP-запросом.
Что вам следует сделать, так это использовать HttpServerUtility.MapPath, где доступен контекст HTTP.Вы можете сделать это в одном из событий конвейера запросов (например, Page_Load) или в глобальном событии.asax, таком как Application_Start .
Присвоите результат MapPath переменной, доступной из таймера.Прошедшее событие, где вы могли бы использовать Path .Объедините, чтобы получить местоположение определенного файла, который вам нужен.
Я думаю, причина, по которой в данный момент оно равно null (если вы подумаете об этом), заключается в том, что событие истечения таймера не происходит как часть HTTP-запроса (следовательно, нет контекста).Это вызвано чем-то на вашем сервере.