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