Jaka jest najlepsza metoda uzyskania bieżącej domeny w ASP.NET?


102

Zastanawiam się, jaki najlepszy sposób uzyskania bieżącej domeny jest w ASP.NET?

Na przykład:

http://www.domainname.com/subdir/ powinno dać http://www.domainname.com http://www.sub.domainname.com/subdir/ powinno dać http://sub.domainname.com

Jako przewodnik powinienem móc dodać adres URL, taki jak „/Folder/Content/filename.html” (powiedzmy, jak wygenerowany przez Url.RouteUrl () w ASP.NET MVC) bezpośrednio do adresu URL i powinno działać.


3
Zwróć uwagę, że „bieżąca domena” jest w rzeczywistości tym, z czego klient użytkownika korzystał, aby dostać się do Twojej witryny, która w wielu przypadkach różni się od „oficjalnego adresu URL” Twojej witryny, a także tego, co użytkownik końcowy mógł wprowadzić w przeglądarce ( odwrotne proxy, przekierowanie proxy, wewnętrzna nazwa hosta, adres IP, ...).
— bzlm

1
Czy jest więc sposób na uzyskanie „oficjalnego adresu URL” (tego z IIS?)
— Matt Mitchell

Odpowiedzi:


186

Taka sama odpowiedź jak MattMitchell, ale z pewnymi modyfikacjami. Zamiast tego sprawdza domyślny port.

Edycja: zaktualizowana składnia i użycie Request.Url.Authorityzgodnie z sugestią

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

3
Czy istnieje zdefiniowane pole i .NET, którego mogę używać zamiast znaku „:”? Coś w rodzaju System.Uri.PortDelimiter? Wiesz, tylko dla spójności. :)
— Jan Aagaard

2
Nie żebym wiedział, Janie Aagaardzie, ale zawsze możesz zrobić to lokalnie. Robię to dla większości „magicznych” łańcuchów i liczb. O to chodzi, by następnie użyć string.Empty zamiast „” w odpowiedzi Carlosa;)
— vbullinger

8
Możesz użyć Request.Url.Authorityzgodnie z sugestią Korayem zamiast Request.Url.Hosti Request.Url.Port.
— Schmalls

4
Zamiast konkatenować ciągi znaków, powinieneś używać klasy System.UriBuilder.
— BrainSlugs83

3
@MattMitchell, wydaje się, że nie założył problemów z Authority, jest to odpowiednik Host + ":" + Port, patrz kod źródłowy dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…
— Giuseppe Romagnuolo

40

Zgodnie z tym linkiem dobrym punktem wyjścia jest:

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

Jeśli jednak domena to http://www.domainname.com:500, to się nie powiedzie.

Coś podobnego do następującego jest kuszące, aby rozwiązać ten problem:

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

Jednak porty 80 i 443 będą zależeć od konfiguracji.

W związku z tym powinieneś użyć tego, IsDefaultPortco w zaakceptowanej odpowiedzi powyżej Carlosa Muñoza.


1
Po co zakładać tutaj port 80? Jeśli usuniesz to założenie, kod będzie wyglądał jak catch-all. Zakładając port 80, odniesiesz porażkę w wielu scenariuszach (zobacz komentarze do innych odpowiedzi). Jeśli chcesz usunąć numer portu, jeśli to możliwe, musisz sprawdzić, czy numer portu jest domyślnym dla danego schematu i czy schemat obsługuje domyślne numery portów.
— bzlm

Tak, zobacz uwagę, że port 80 może być złym pomysłem. Nie znam innego sposobu na obejście tego problemu, dlatego wspomniałem, że będzie to zależało od konfiguracji.
— Matt Mitchell

1
Nie wiem, czy to pomoże, czy nie, ale możesz również spróbować: if Request.IsSecureConnection, aby określić, czy HTTPS jest używany, czy nie?
— Erick Brown

1
@EricBrown - Tak, ta odpowiedź nie jest świetna w retrospekcji 5 lat później. Poszedłbym z zaakceptowaną odpowiedzią Carlosa Muñoza, aby uniknąć tego problemu.
— Matt Mitchell,


20

OSTRZEŻENIE! Do każdego, kto korzysta z Current.Request .Url.Host. Zrozum, że pracujesz w oparciu o CURRENT REQUEST i że bieżące żądanie nie ZAWSZE będzie przychodzić z twoim serwerem, a czasami może być z innymi serwerami.

Więc jeśli użyjesz tego w czymś takim jak Application_BeginRequest () w Global.asax, to w 99,9% przypadków będzie dobrze, ale w 0,1% możesz otrzymać coś innego niż nazwa hosta twojego własnego serwera.

Dobrym tego przykładem jest coś, co odkryłem niedawno. Mój serwer od czasu do czasu trafia na http://proxyjudge1.proxyfire.net/fastenv . Application_BeginRequest () z przyjemnością obsługuje to żądanie, więc jeśli wywołasz Request.Url.Host podczas wysyłania tego żądania, otrzymasz z powrotem proxyjudge1.proxyfire.net. Niektórzy z was mogą pomyśleć „no duh”, ale warto zwrócić na to uwagę, ponieważ był to bardzo trudny do zauważenia błąd, ponieważ zdarzał się tylko w 0,1% przypadków: P

Ten błąd zmusił mnie do wstawienia mojego hosta domeny jako ciągu w plikach konfiguracyjnych.


Zrobiłem dokładnie to samo. Moja domena znajduje się teraz w web.config.
— Korayem

I pomyśleć rozumiem, choć - dlaczego swój serwer hit proxyfire? Czy to Twoja witryna? Ale ogólnie ma sens - użycie obiektu specyficznego dla żądania podczas zdarzenia specyficznego dla aplikacji może nie działać zbyt dobrze. Czy istnieje niebezpieczeństwo w zdarzeniu związanym z żądaniem, takim jak zdarzenie cyklu życia strony (Page.LoadCompleted itp.)?
— mlhDev

Nie zbadałem zbyt mocno, dlaczego doszło do pożaru pośredniego. Z pewnością nie była to moja witryna, ale wskazała mi, że Current.Request.Url nie jest w 100% wiarygodna. Po wielu badaniach odkryłem również, że dynamiczne określanie nazwy hosta nie jest łatwe ze względu na wiele kart sieciowych, adresów IP i nazw domen, które są rozwiązywane na ten sam adres IP. A jeśli chodzi o Twoje drugie pytanie, Matt, nie jestem pewien, co masz na myśli: (
— Thirlan,

więc zdarzało się to tylko w Application_BeginRequest? Nie widzę, jak usługi IIS mogły kiedykolwiek wysłać to żądanie do Twojej aplikacji, chyba że nie masz ustawionego nagłówka hosta?
— Simon_Weaver,

@Thirlan - próbuję debugować problem, który brzmi podobnie do tego. Próbuję uzyskać subdomenę za pomocą Request.Url.Host i „zwykle” działa dobrze, ale nie zawsze. Czy naprawdę jest w tym jakiś sposób? Podoba Ci się coś innego w żądaniu, które może być poprawne?
— scojomodena

14

Dlaczego nie użyć

Request.Url.Authority

Zwraca całą domenę ORAZ port.

Nadal musisz określić http lub https


2
To też działa. Aby „zilustrować” http lub https, wystarczy umieścić przed nim „//”. Na przykład miałoby to postać href = "// @ Request.Url.Authority ..."
— EdwardM

2

Prosty i krótki sposób (obsługuje schemat, domenę i port):

Posługiwać się 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

Inny sposób:


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

Prosta, ale po prostu świetna odpowiedź!
— Shiroy

1

Co powiesz na:

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

Korzystanie z 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

Co powiesz na:

String domain = "http://" + Request.Url.Host

Nieźle, ale co, jeśli Twoja witryna ma bezpieczne strony, np. Https: // A jeśli Twoja domena nie jest hostowana na porcie 80?
— Matt Mitchell,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.