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ć.

Matt Mitchell
źródło
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}"
Carlos Muñoz
źródło
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.

Matt Mitchell
źródło
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,
29
Request.Url.GetLeftPart(UriPartial.Authority)

Jest to schemat uwzględniony.

niezadowolenie
źródło
23
Bardzo chciałbym być na spotkaniu, kiedy
wymyślili
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.

Thirlan
źródło
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

Korayem
źródło
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
Baran
źródło
1

Inny sposób:


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

źródło
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"];
Derek Lawless
źródło
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();
Darren
źródło
-1

Co powiesz na:

String domain = "http://" + Request.Url.Host
jwalkerjr
źródło
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,