Який найкращий метод в 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

Відповідь така ж, як у MattMitchell, але з деякою модифікацією. Це замість цього перевіряє порт за замовчуванням.

Редагування: оновлений синтаксис та використання, Request.Url.Authorityяк пропонується

$"{Request.Url.Scheme}{System.Uri.SchemeDelimiter}{Request.Url.Authority}"

3
Чи є поле, визначене i .NET, яке я можу використовувати замість ":"? Щось на кшталт System.Uri.PortDelimiter? Знаєте, просто для послідовності. :)
— Ян Аагаард

2
Не те, що я знаю, Ян Аагаард, але ти завжди міг зробити це місцево. Я роблю це для більшості "магічних" рядків і номерів. З цього приводу ви будете використовувати string.Empty замість "" у відповіді Карлоса;)
— vbullinger

8
Ви можете використовувати Request.Url.Authorityяк запропоновано Кораєм замість Request.Url.Hostі Request.Url.Port.
— Шмоллс

4
Замість об'єднувальних рядків слід використовувати клас System.UriBuilder.
— BrainSlugs83

3
@MattMitchell, схоже, не засновані проблеми з повноваженнями, це еквівалент Host + ":" + порт, див. Вихідний код dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…
— Джузеппе Романьйоло

40

Відповідно до цього посилання хорошим початковим пунктом є:

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

Однак, якщо домен http://www.domainname.comwhat00, це не вдасться.

Щось таке, як це, спокушає вирішити це:

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
Я не знаю, чи це допоможе чи ні, але ви також можете спробувати: якщо Request.IsSecureConnection визначити, використовується HTTPS чи ні?
— Ерік Браун

1
@EricBrown - Так, ця відповідь не дуже важлива для ретроспекції через 5 років. Я б пішов з прийнятою відповіддю Карлоса Муньоса, щоб уникнути цього питання.
— Метт Мітчелл


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

Ця помилка змусила мене вставити мій хост домену як рядок у конфігураційні файли.


Зробив точно так само. Мій домен зараз у web.config.
— Кораєм

Я думаю, я розумію, хоча - чому ваш сервер потрапляє на proxyfire? Це ваш сайт? Але, в цілому, має сенс - використання об'єкта, що відповідає запиту, під час події, що стосується додатка, може працювати не надто добре. Чи існує небезпека події, пов’язаної з запитом, наприклад події життєвого циклу сторінки (Page.LoadCompleted тощо)?
— mlhDev

Я не надто важко досліджував, чому це було вирішено проксифір. Це, звичайно, не мій сайт, але він мені вказував, що Current.Request.Url не був на 100% надійним. Після безлічі досліджень я також виявив, що динамічно визначити своє ім’я хоста непросто, завдяки численним NIC-картам, 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);

Проста, але просто приголомшлива відповідь!
— Широй

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

Непогано, але що робити, якщо на вашому веб-сайті є захищені сторінки, тобто https: // Що робити, якщо ваш домен не розміщений на порту 80?
— Метт Мітчелл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.