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

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

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

Спасибо!


person Costo    schedule 21.09.2008    source источник


Ответы (6)


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

Однако я еще не пробовал это в потоке или событии таймера.


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

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

  • Другой подход: добавьте все нужные мне пути в класс Global. Разрешите эти пути в Application_Start.

person Costo    schedule 21.09.2008
comment
Однако обратите внимание, что вышеуказанное не работает в более поздних версиях IIS. В IIS7 запуск приложения может быть вызван вне HTTP-запроса. То есть пример кода. Я уверен, что HostingEnvironment.MapPath () по-прежнему будет работать, как и раньше. - person Robba; 25.10.2010
comment
Но HostingEnvironment.MapPath () выдает ошибку, если вы передаете его и пустую строку, чтобы напрямую получить путь к папке ... HttpContext.Current.Server.MapPath (); - ›работает HostingEnvironment.MapPath (); - ›вызывает ошибку - person VSP; 02.03.2012

Я не знаю, решит ли это проблему с виртуальными каталогами, но я использую это для 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('/', '\\');
}
person Community    schedule 27.01.2009
comment
path.Replace (~, string.Empty) должен быть path.Replace ('~', '.') - person Slava; 18.03.2016

HostingEnvironment - не идеальное решение, потому что это очень сложный класс для имитации (см. Как выполнить модульное тестирование кода, использующего HostingEnvironment.MapPath).

Для тех, кому нужна возможность тестирования, лучшим способом может быть создание собственного интерфейса сопоставителя путей, как предложено https://stackoverflow.com/a/1231962/85196, кроме как

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

Результат легко подделать, внутренне использует HostingEnvironment и даже потенциально может адресовать проблема ase69s одновременно.

person Mike    schedule 09.07.2012
comment
Это позволило мне предоставить реализацию для разрешения пути для проекта веб-API, не требуя зависимости от System.Web или System.Net в библиотеке, на которую он ссылался. +1 - person David Peterson; 16.09.2015
comment
Поднимите палец вверх за DI и тестируемость этого подхода - person Dilhan Jayathilake; 06.05.2017

А нельзя перед запуском таймера вызвать функцию MapPath и просто кэшировать результат? Обязательно ли иметь вызов MapPath внутри события тика?

person Mark S. Rasmussen    schedule 21.09.2008

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

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

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

person zvikara    schedule 21.09.2008

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

person Vaibhav    schedule 21.09.2008