Как получить полное имя хоста + номер порта в Application_Start Global.aspx?

Я пытался

Uri uri = HttpContext.Current.Request.Url;
String host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;

и он хорошо работал на моем локальном компьютере, но при публикации в IIS7 есть исключение, говорящее

System.Web.HttpException: Request is not available in this context

Кто-нибудь знает, как этого добиться?


person Leo    schedule 22.11.2010    source источник
comment
Похоже, вы работаете в интегрированном режиме, а не в классическом (который, я думаю, вы работаете на своем локальном компьютере). Проблема в том, что Request недоступен в Application_Start в IIS7. Взгляните на: mvolo.com/blogs/serverside/archive/2007/11/10/ Это прекрасно объясняет.   -  person Michael Shimmins    schedule 22.11.2010
comment
См. Также stackoverflow.com/a/578083/12484 для более чистого способа получить схему + хост + порт из URL-адреса. (если он у вас есть).   -  person Jon Schneider    schedule 18.09.2014


Ответы (3)


Когда ваше веб-приложение запускается, HTTP-запрос не обрабатывается.

Вы можете определить обработчик метода Application_BeginRequest (Object Sender, EventArgs e), в котором доступен контекст запроса.

Изменить: вот пример кода, вдохновленный блогом Майка Володарского, на который Майкл Шимминс указал:

    void Application_BeginRequest(Object source, EventArgs e)
    {
        HttpApplication app = (HttpApplication)source;
        var host = FirstRequestInitialisation.Initialise(app.Context);
    }

    static class FirstRequestInitialisation
    {
        private static string host = null;
        private static Object s_lock = new Object();

        // Initialise only on the first request
        public static string Initialise(HttpContext context)
        {
            if (string.IsNullOrEmpty(host))
            {
                lock (s_lock)
                {
                    if (string.IsNullOrEmpty(host))
                    {
                        var uri = context.Request.Url;
                        host = uri.GetLeftPart(UriPartial.Authority);
                    }
                }
            }

            return host;
        }
    }
person cspolton    schedule 22.11.2010
comment
Разве это не должно быть Uri uri = context.Request.Url;, также нельзя упростить следующую строку до простого uri.GetLeftPart(UriPartial.Authority); - person Chris Marisic; 06.06.2012
comment
это также должен быть статический класс, и вам не нужно инициализировать хост. - person Steve; 04.12.2013
comment
Значит, нет возможности получить номер порта, пока не поступит самый первый HTTP-запрос? - person PaulK; 31.10.2014
comment
Вообще-то, нет. Веб-сайт ASP.NET может иметь несколько привязок, он может работать на нескольких хостах и ​​с несколькими номерами портов (например, безопасная и незащищенная версия веб-сайта). У вас работает только один экземпляр веб-приложения, входящий запрос содержит информацию о том, какой хост инициировал запрос. Веб-приложение просто знает, что это приложение, у него нет реального контекста того, на каком хосте оно работает. Если ваше приложение имеет две привязки, одну для порта 80 и одну для порта 8080, какую из них вы хотите? Вы не знаете, поэтому вам это нужно для каждого запроса. - person revlayle; 06.05.2015
comment
Довольно элегантное решение. Я обнаружил необходимость получить «базовый» домен при запуске приложения и использовать его при JIT-запуске приложения. В итоге я переместил свою логику в Begin_Request. Application_Start теперь пуст, а Begin_Request содержит логику и простую проверку того, не является ли домен пустым или пустым. - person Dan Atkinson; 13.04.2017
comment
Мне любопытно, зачем две проверки значения host? Я предполагаю, что это проблема параллелизма, если значение установлено в этот небольшой промежуток времени, но просто дважды проверяю, было ли это ошибкой. - person trnelson; 21.04.2017

Принятый ответ хорош, но в большинстве случаев (если первый запрос - это HTTP-запрос) вам лучше использовать событие Session_Start, которое вызывается один раз для каждого пользователя каждые 20 минут или около того (не уверен, как долго сеанс действителен). Application_BeginRequest будет уволен по каждому запросу.

public void Session_Start(Object source, EventArgs e)
{
   //Request / Request.Url is available here :)
}
person VladL    schedule 05.12.2013

Просто отвечу на это, поэтому, если кто-то когда-нибудь решит действительно поискать по этой теме ...

Это работает при запуске приложения в любом режиме ...

typeof(HttpContext).GetField("_request", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(HttpContext.Current)
person Brandon Seydel    schedule 19.03.2015
comment
обратите внимание, что это поле не является общедоступным (т.е. частным). Вы должны быть очень осторожны при использовании недокументированных функций и полей, поскольку они могут измениться без дополнительной информации. - person Stephen Reindl; 19.03.2015
comment
А чем он отличается от _1 _ ??? Я вижу тот же результат - person Andrii; 23.12.2017