Могу ли я получить доступ к имени виртуального каталога в global.asax.cs?
Недвижимость HttpContext.Current.Request.ApplicationPath
представляет виртуальный каталог в IIS или WebDev.WebServer.
HttpContext.Current.Request.ApplicationPath evaluates to "/virtualdirectory"
Это может быть использовано в сочетании с VirtualPathUtility
сделать корень пути относительным:
VirtualPathUtility.ToAbsolute("~/images/cat.jpg",
HttpContext.Current.Request.ApplicationPath)
// (this evaluates to "/virtualdirectory/images/cat.jpg")
В IIS6 и WebDev.WebServer объект запроса доступен в global.asax.cs
, но IIS7 жалуется, что он "недоступен в текущем контексте". Поэтому вторая строка кода выше работает, но не в IIS7.
Проблема в том, что мне нужно получить доступ к виртуальному имени директрой global.asax.cs
, Мне нужно, чтобы построить несколько путей, которые используются в динамически создаваемых CSS. Есть ли альтернативный способ доступа к этому значению?
Изменить: это ошибка, которую вы получаете в IIS 7 для вызова HttpContext.Current.Request
в global.asax.cs под Application_Start:
HttpException (0x80004005): Request is not available in this context]
System.Web.HttpContext.get_Request() +8789264
5 ответов
Наконец-то нашел простой ответ!
HttpRuntime.AppDomainAppVirtualPath
Доступно сразу во время Application_Start
Это имеет форму /myapplication
в том числе /
префикс.
Можете ли вы использовать ResolveUrl("~/images/cat.jpg"), чтобы построить свой путь?
Редактировать: ResolveUrl - это метод Control, а не просто класс Page, поэтому вы можете сделать это таким образом (возможно, немного некрасиво):
System.Web.UI.Control c = new Control();
String s = c.ResolveUrl(@"~/images/cat.jpg");
Это лучшее, что я придумал: Application_BeginRequest (через отметку)
Я использую asax так редко, что я временно забыл, что с ним происходят разные события. До сих пор я создавал спрайты CSS в Application_Start
, Перемещение его в BeginRequest было лучшим, что я мог придумать.
Одна логическая проверка для каждого запроса незначительна, но было бы неплохо, если есть другой способ.
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
protected void Application_BeginRequest()
{
if (!_initialized)
{
lock (thisLock)
{
_initialized = true;
GenerateCSSSprites();
}
}
}
Хммм... я не знал об изменении IIS7. Интересно, не будет ли проще отложить эту операцию, пока у вас не появится страница? Например, вы можете попробовать поместить что-то "только один раз" в Application_BeginRequest
или же Session_Start
?
Или (полностью непроверенный) для ловли отписки:
public override void Init() {
base.Init();
EventHandler handler = null;
handler = delegate {
// do stuff, once only
this.BeginRequest -= handler;
};
this.BeginRequest += handler;
}
Хитрость заключается в том, чтобы сделать это только один раз (если несколько запросов поступают одновременно); возможно статический ctor? Например, я думаю, что это срабатывает только один раз, и только когда есть доступная страница в контексте:
static class DelayedLoader {
static DelayedLoader() {
string s = VirtualPathUtility.ToAbsolute("~/images/cat.jpg",
HttpContext.Current.Request.ApplicationPath);
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Init() { }
}
public override void Init() {
base.Init();
EventHandler handler = null;
handler = delegate {
DelayedLoader.Init();
this.BeginRequest -= handler;
};
this.BeginRequest += handler;
}
У меня тоже была эта проблема при переходе на IIS7, но я смог реорганизовать необходимость запроса. Это то, что этот парень также предлагает и предлагает обходной путь, если вы не можете.