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

88

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

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

Благодарность!

Costo
источник

Ответы:

142

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

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


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

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

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

Costo
источник
1
Однако обратите внимание, что вышеуказанное не работает в более поздних версиях IIS. В IIS7 запуск приложения может быть вызван вне HTTP-запроса. То есть пример кода. Я уверен, что HostingEnvironment.MapPath () по-прежнему будет работать, как и раньше.
Робба
Но HostingEnvironment.MapPath () выдает ошибку, если вы передаете его и пустую строку, чтобы напрямую получить путь к папке ... HttpContext.Current.Server.MapPath (""); -> работает HostingEnvironment.MapPath (""); -> вызывает ошибку
ВСП
14

Я не знаю, решит ли это проблему с виртуальными каталогами, но я использую это для 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('/', '\\');
}

источник
path.Replace ("~", string.Empty) должен быть path.Replace ('~', '.')
Слава
13

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

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

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

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

Майк
источник
Это позволило мне предоставить реализацию для разрешения пути для проекта веб-API, не требуя зависимости от System.Web или System.Net в библиотеке, на которую он ссылался. +1
Дэвид Петерсон
Большое спасибо
2

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

Марк С. Расмуссен
источник
2

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

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

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

Звикара
источник
0

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

Вайбхав
источник