Как получить доступ к методу HttpServerUtility.MapPath в потоке или таймере?

Я использую System.Timers.Timer в моем приложении Asp.Net и мне нужно использовать HttpServerUtility.MapPath метод, который, кажется, доступен только через HttpContext.Current.Server.MapPath, Проблема в том, что HttpContext.Current является null когда Timer.Elapsed событие пожары.

Есть ли другой способ получить ссылку на объект HttpServerUtility? Я мог бы добавить его в конструктор моего класса. Это безопасно? Как я могу быть уверен, что в конце текущего запроса это не будет сбор мусора?

Спасибо!

6 ответов

Решение

Можно использовать HostingEnvironment.MapPath() вместо HttpContext.Current.Server.MapPath()

Я еще не попробовал это в потоке или событии таймера все же.


Некоторые (нежизнеспособные) решения, которые я рассмотрел;

  • Единственный способ, которым я забочусь о HttpServerUtility является MapPath, Так что в качестве альтернативы я мог бы использовать AppDomain.CurrentDomain.BaseDirectory и строить мои пути из этого. Но это не удастся, если ваше приложение использует виртуальные каталоги (Mine делает).

  • Другой подход: добавьте все нужные мне пути к 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).

Для тех, кому нужна тестируемость, лучшим способом может быть создание собственного интерфейса преобразователя пути, как это предложено /questions/19817455/kak-mappath-v-modulnom-teste-v-c/19817471#19817471, за исключением того, чтобы реализовать его как

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

Результат легко поддается моделированию, использует HostingEnvironment для внутренних целей и даже может одновременно решить проблему ase69.

По истечении таймера текущий контекст HTTP отсутствует. Это связано с тем, что события таймера не связаны с конкретным HTTP-запросом.

Что вы должны сделать, это использовать HttpServerUtility.MapPath, где доступен HTTP-контекст. Вы можете сделать это в одном из событий конвейера запросов (например, Page_Load) или в событии Global.asax, например Application_Start.

Присвойте результат MapPath переменной, доступной из события Timer.Elapsed, где вы можете использовать Path.Combine, чтобы получить местоположение нужного вам файла.

Разве вы не можете вызвать функцию MapPath перед запуском таймера, а просто кэшировать результат? Является ли абсолютно необходимым иметь вызов MapPath внутри тикового события?

Я думаю, что причина того, почему он является нулевым в это время (если вы об этом думаете), заключается в том, что истекшее время таймера не происходит как часть HTTP-запроса (следовательно, нет контекста). Это вызвано чем-то на вашем сервере.

Другие вопросы по тегам