Могу ли я получить доступ к имени виртуального каталога в global.asax.cs? - PullRequest
7 голосов
/ 29 апреля 2009

Свойство 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 ]

14 голосов
/ 03 января 2010

Наконец-то нашел простой ответ!

 HttpRuntime.AppDomainAppVirtualPath

Доступно сразу во время Application_Start

Это имеет форму /myapplication, включая префикс /.

0 голосов
/ 29 апреля 2009

У меня тоже была эта проблема при переходе на IIS7, но я смог рефакторировать необходимость запроса. Это то, что этот парень также предлагает и предлагает обходной путь, если вы не можете.

http://mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx

0 голосов
/ 29 апреля 2009

Хммм ... Я не знал об изменении 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;
    }
0 голосов
/ 29 апреля 2009

Это лучшее, что я придумал: 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();  
            }
        }
    }
0 голосов
/ 29 апреля 2009

Можете ли вы использовать ResolveUrl ("~ / images / cat.jpg"), чтобы построить свой путь?

Редактировать: ResolveUrl - это метод Control, а не просто класс Page, поэтому вы можете сделать это следующим образом (возможно, немного уродливо):

System.Web.UI.Control c = new Control();
String s = c.ResolveUrl(@"~/images/cat.jpg");
...