Як отримати доступ до методу HttpServerUtility.MapPath у потоці або таймері?


88

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

Чи є інший спосіб отримати посилання на об’єкт HttpServerUtility? Я міг би вколоти його в конструкторі мого класу. Це безпечно? Як я можу бути впевненим, що це не буде Сміття, зібране в кінці поточного запиту?

Дякую!

Відповіді:


142

Можна використовувати HostingEnvironment.MapPath()замістьHttpContext.Current.Server.MapPath()

Я ще не пробував це в потоці або події таймера.


Деякі (нежиттєздатні) рішення я розглядав;

  • Єдиний метод, про який я дбаю, HttpServerUtility- це MapPath. Тож як альтернативу я міг би використати AppDomain.CurrentDomain.BaseDirectoryі будувати на цьому свої шляхи. Але це не вдасться, якщо ваш додаток використовує віртуальні каталоги (Mine робить).

  • Інший підхід: Додайте всі необхідні шляхи до Globalкласу. Вирішіть ці шляхи в Application_Start.


1
Однак зауважте, що вищесказане не працює в пізніших версіях IIS. У IIS7 запуск програми може бути викликаний поза запитом http. Тобто, приклад коду. Я впевнений, що HostingEnvironment.MapPath () все одно працюватиме, як і раніше.
Робба

Але HostingEnvironment.MapPath () видає помилку, якщо ви передаєте її та порожній рядок, щоб отримати шлях до папки безпосередньо ... HttpContext.Current.Server.MapPath (""); -> працює HostingEnvironment.MapPath (""); -> викликає помилку
VSP

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» ).

Для тих, хто потребує перевірки, кращим способом може бути створення власного інтерфейсу map-path, як пропонується https://stackoverflow.com/a/1231962/85196 , за винятком реалізації як

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

Результат легко знущається, він використовує HostingEnvironment внутрішньо і навіть може потенційно одночасно вирішити стурбованість ase69s .


Це дозволило мені забезпечити реалізацію роздільної здатності для проекту Web API, не вимагаючи залежності від System.Web або System.Net у бібліотеці, на яку він посилався. +1
Девід Петерсон,

Великі пальці вгору за DI та
перевірочність

2

Ви не можете викликати функцію MapPath перед запуском таймера, а просто кешувати результат? Чи абсолютно необхідним є виклик MapPath всередині події галочки?


2

Коли таймер минає, поточного контексту HTTP немає. Це пов’язано з тим, що події таймера не пов’язані з певним запитом HTTP.

Потрібно використовувати HttpServerUtility.MapPath там, де доступний контекст HTTP. Ви можете зробити це в одній із подій конвеєру запитів (наприклад, Page_Load) або в події Global.asax, наприклад Application_Start.

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


0

Я думаю, що причиною того, чому він є нульовим на той час (якщо ви задумаєтесь), є те, що минула подія таймера не відбувається як частина запиту HTTP (отже, немає контексту). Це спричинено чимось на вашому сервері.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.