Какой лучший метод в ASP.NET для получения текущего домена?

102

Мне интересно, как лучше всего получить текущий домен в ASP.NET?

Например:

http://www.domainname.com/subdir/ должно давать http://www.domainname.com http://www.sub.domainname.com/subdir/ должно давать http://sub.domainname.com

В качестве руководства я должен иметь возможность добавить URL-адрес типа «/Folder/Content/filename.html» (например, созданный с помощью Url.RouteUrl () в ASP.NET MVC) прямо в URL-адрес, и он должен работать.

Мэтт Митчелл
источник
3
Обратите внимание, что «текущий домен» здесь - это фактически то, что пользовательский агент-потребитель использовал для перехода на ваш сайт, что во многих случаях отличается от «официального URL-адреса» вашего сайта, а также от того, что конечный пользователь мог ввести в свой браузер ( обратный прокси, прямой прокси, внутреннее имя хоста, IP-адрес, ...).
bzlm
1
Так есть ли способ получить «официальный URL» (тот, что от IIS?)
Мэтт Митчелл,

Ответы:

186

Тот же ответ, что и у Мэтта Митчелла, но с некоторыми изменениями. Вместо этого проверяется порт по умолчанию.

Изменить: обновленный синтаксис и использование, Request.Url.Authorityкак было предложено

$"{Request.Url.Scheme}{System.Uri.SchemeDelimiter}{Request.Url.Authority}"
Карлос Муньос
источник
3
В .NET определено поле, которое я могу использовать вместо ":"? Что-то вроде System.Uri.PortDelimiter? Знаете, просто для последовательности. :)
Ян Агард
2
Не то, чтобы я знал о Яне Огарде, но вы всегда можете сделать его на месте. Я делаю это для большинства «волшебных» строк и чисел. Если на то пошло, тогда вы бы использовали string.Empty вместо "" в ответе Карлоса;)
vbullinger
8
Вы можете использовать, Request.Url.Authorityкак предлагает Кораем, вместо Request.Url.Hostи Request.Url.Port.
Schmalls
4
Вместо объединения строк следует использовать класс System.UriBuilder.
BrainSlugs83
3
@MattMitchell, похоже, проблем с Authority не обнаружено, это эквивалент Host + ":" + Port, см. Исходный код dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…
Giuseppe Romagnuolo
40

По этой ссылке хорошей отправной точкой является:

Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 

Однако, если домен http://www.domainname.com:500, это не удастся.

Что-то вроде следующего заманчиво решить эту проблему:

int defaultPort = Request.IsSecureConnection ? 443 : 80;
Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host 
  + (Request.Url.Port != defaultPort ? ":" + Request.Url.Port : "");

Однако порт 80 и 443 будет зависеть от конфигурации.

Таким образом, вам следует использовать IsDefaultPortкак в принятом ответе Карлоса Муньоса выше.

Мэтт Митчелл
источник
1
Зачем считать здесь 80-й порт? Если вы уберете это предположение, код будет выглядеть всеобъемлющим. Когда вы предполагаете порт 80, вы потерпите неудачу во многих сценариях (см. Комментарии к другим ответам). Если вы хотите удалить номер порта, если это возможно, вы должны убедиться, что номер порта является номером порта по умолчанию для рассматриваемой схемы и что схема поддерживает номера портов по умолчанию.
bzlm
Да, обратите внимание, что порт 80 может быть плохой идеей. Я не знаю другого способа обойти это, поэтому я упомянул, что это должно зависеть от конфигурации.
Мэтт Митчелл,
1
Я не знаю, поможет это или нет, но вы также можете попробовать: if Request.IsSecureConnection, чтобы определить, используется ли HTTPS или нет?
Эрик Браун
1
@EricBrown - Да, этот ответ не очень хорош в ретропсекте 5 лет спустя. Я бы пошел с принятым ответом Карлоса Муньоса, чтобы избежать этой проблемы.
Мэтт Митчелл
29
Request.Url.GetLeftPart(UriPartial.Authority)

Это включенная схема.

izlence
источник
23
Я хотел бы быть на собрании, когда они придумали это имя
Simon_Weaver
20

ПРЕДУПРЕЖДЕНИЕ! Всем, кто использует Current.Request .Url.Host. Поймите, что вы работаете на ТЕКУЩЕМ ЗАПРОСЕ и что текущий запрос НЕ ВСЕГДА будет на вашем сервере, а иногда может быть на других серверах.

Поэтому, если вы используете это в чем-то вроде Application_BeginRequest () в Global.asax, то в 99,9% случаев все будет хорошо, но в 0,1% вы можете получить что-то другое, кроме имени хоста вашего собственного сервера.

Хорошим примером этого является то, что я обнаружил не так давно. Мой сервер имеет тенденцию время от времени посещать http://proxyjudge1.proxyfire.net/fastenv . Application_BeginRequest () с радостью обработает этот запрос, поэтому, если вы вызовете Request.Url.Host, когда он делает этот запрос, вы получите обратно proxyjudge1.proxyfire.net. Некоторые из вас могут подумать «нет, черт возьми», но это стоит отметить, потому что это было очень трудно заметить, так как это происходило только в 0,1% случаев: P

Эта ошибка вынудила меня вставить мой хост домена в виде строки в файлы конфигурации.

Thirlan
источник
Сделал точно так же. Мой домен сейчас находится в web.config.
Кораем
Я думаю, что понимаю - почему ваш сервер попадает в прокси-сервер? Это ваш сайт? Но в целом это имеет смысл - использование объекта, специфичного для запроса, во время события, специфичного для приложения, может работать не слишком хорошо. Есть ли опасность в событии, связанном с запросом, например событии жизненного цикла страницы (Page.LoadCompleted и т. Д.)?
mlhDev
Я не особо разбирался в том, почему он разрешается на proxyfire. Конечно, это был не мой сайт, но он показал мне, что Current.Request.Url не был на 100% надежным. После долгих исследований я также обнаружил, что динамическое определение имени вашего хоста непросто из-за нескольких сетевых карт, IP-адресов и доменных имен, которые разрешаются на один и тот же IP-адрес. Что касается вашего другого вопроса, Мэтт, я не уверен, что вы имеете в виду: (
Тирлан
так это когда-либо происходило только в Application_BeginRequest? Я не понимаю, как IIS мог когда-либо отправить этот запрос в ваше приложение, если у вас, возможно, не установлен заголовок хоста?
Simon_Weaver
@Thirlan - я пытаюсь отладить проблему, похожую на эту. Я пытаюсь получить поддомен с помощью Request.Url.Host, и «обычно» работает хорошо, но не всегда. Есть ли что-нибудь вокруг этого? Как что-то еще в запросе, что может быть правильным?
scojomodena
14

Почему бы не использовать

Request.Url.Authority

Он возвращает весь домен И порт.

Вам все равно нужно указать http или https

Кораем
источник
2
Это тоже работает. Чтобы «вычислить» http или https, просто поставьте перед ним «//». Так, например, он будет читаться как href = "// @ Request.Url.Authority ..."
EdwardM
2

Простой и короткий способ (поддерживает схему, домен и порт):

Использовать Request.GetFullDomain()

// Add this class to your project
public static class HttpRequestExtensions{
    public static string GetFullDomain(this HttpRequestBase request)
    {
        var uri= request?.UrlReferrer;
        if (uri== null)
            return string.Empty;
        return uri.Scheme + Uri.SchemeDelimiter + uri.Authority;
    }
}

// Now Use it like this:
Request.GetFullDomain();
// Example output:    https://www.example.com:5031
// Example output:    http://www.example.com:5031
// Example output:    https://www.example.com
ОЗУ
источник
1

По-другому:


string domain;
Uri url = HttpContext.Current.Request.Url;
domain= url.AbsoluteUri.Replace(url.PathAndQuery, string.Empty);

источник
Простой, но просто потрясающий ответ!
Широй 02
1

Как насчет:

NameValueCollection vars = HttpContext.Current.Request.ServerVariables;
string protocol = vars["SERVER_PORT_SECURE"] == "1" ? "https://" : "http://";
string domain = vars["SERVER_NAME"];
string port = vars["SERVER_PORT"];
Дерек Лоулесс
источник
0

Использование UriBuilder:

    var relativePath = ""; // or whatever-path-you-want
    var uriBuilder = new UriBuilder
    {
        Host = Request.Url.Host,
        Path = relativePath,
        Scheme = Request.Url.Scheme
    };

    if (!Request.Url.IsDefaultPort)
        uriBuilder.Port = Request.Url.Port;

    var fullPathToUse = uriBuilder.ToString();
Даррен
источник
-1

Как насчет:

String domain = "http://" + Request.Url.Host
Jwalkerjr
источник
Неплохо, но что, если на вашем сайте есть защищенные страницы, например https: // Что делать, если ваш домен не размещен на порту 80?
Мэтт Митчелл,