Jak uzyskać bieżący adres URL strony w MVC 3


360

Korzystam z wtyczki komentarzy na Facebooku na blogu, który tworzę. Zawiera niektóre tagi FBXML, które są interpretowane przez javascript na Facebooku, do którego odwołuje się strona.

To wszystko działa dobrze, ale muszę przekazać bieżący, w pełni kwalifikowany adres URL do wtyczki.

<div style="width: 900px; margin: auto;">
    <div id="fb-root"></div>
    <fb:comments href="URL HERE" num_posts="10" width="900"></fb:comments>
</div>

Jaki jest najlepszy sposób na uzyskanie adresu URL bieżącej strony? URL żądania

Rozwiązanie

Oto końcowy kod mojego rozwiązania:

<fb:comments href="@Request.Url.AbsoluteUri" num_posts="15" width="900"></fb:comments>

Odpowiedzi:


533

Można użyć Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString()lub Request.Url.AbsoluteUri.


2
Z jakiegoś powodu nie wydaje się, aby uzyskać cały adres URL, tylko wszystko po domenie.
Chev

6
@Chevex, Request.Url.ToString()a może Request.Url.AbsoluteUri?
Darin Dimitrov

9
Prawie. Request.Url.AbsoluteUrizrobiłem to :)
Chev

2
@Chevex - na jakim porcie znajduje się strona? Jeśli jest to port 80, to tak, nie zobaczysz go. Mówię, że w środowisku, w którym istnieje wirtualny port publikowania IP 80 na jednej lub więcej maszynach na innym porcie (np. 81), Asp.Net zawsze doda: 81 do adresu URL niepoprawnie
Andras Zoltan

29
aby uzyskać próbki różnych fragmentów url rzucić okiem na: cambiaresearch.com/articles/53/...
ms007

48

Dodaj tę metodę rozszerzenia do swojego kodu:

public static Uri UrlOriginal(this HttpRequestBase request)
{
  string hostHeader = request.Headers["host"];

  return new Uri(string.Format("{0}://{1}{2}",
     request.Url.Scheme, 
     hostHeader, 
     request.RawUrl));
}

A następnie możesz wykonać to poza RequestContext.HttpContext.Requestwłaściwością.

W Asp.Net występuje błąd (można go usunąć krokiem, patrz poniżej), który pojawia się na komputerach, które używają portów innych niż port 80 dla lokalnej strony internetowej (duży problem, jeśli wewnętrzne strony internetowe są publikowane poprzez równoważenie obciążenia na wirtualnym IP a porty są używane wewnętrznie do reguł publikowania), dzięki czemu Asp.Net zawsze doda port do AbsoluteUriwłaściwości - nawet jeśli pierwotne żądanie go nie używa.

Ten kod zapewnia, że ​​zwrócony adres URL jest zawsze równy adresowi URL, którego pierwotnie zażądała przeglądarka (w tym port - tak jak byłby zawarty w nagłówku hosta), zanim nastąpi równoważenie obciążenia itp.

Przynajmniej działa w naszym (raczej skomplikowanym!) Środowisku :)

Jeśli między funkcjami przepisują nagłówek hosta jakieś funky proxy, to też nie zadziała.

Zaktualizuj 30 lipca 2013 r

Jak wspomniano w @KevinJones w komentarzach poniżej - ustawienie, o którym wspomniałem w następnej sekcji, zostało udokumentowane tutaj: http://msdn.microsoft.com/en-us/library/hh975440.aspx

Chociaż muszę powiedzieć, że nie mogłem go uruchomić, gdy go wypróbowałem - ale to może być po prostu literówka lub coś takiego.

Zaktualizuj 9 lipca 2012 r

Spotkałem się z tym jakiś czas temu i zamierzałem zaktualizować tę odpowiedź, ale nigdy tego nie zrobiłem. Kiedy właśnie pojawiła się opinia na temat tej odpowiedzi, pomyślałem, że powinienem to zrobić teraz.

„Błąd”, o którym wspomniałem w Asp.Net, można kontrolować za pomocą pozornie nieudokumentowanej wartości appSettings - nazywanej 'aspnet:UseHostHeaderForRequest'- tj .:

<appSettings>
  <add key="aspnet:UseHostHeaderForRequest" value="true" />
</appSettings>

Natknąłem się na to, patrząc na HttpRequest.UrlILSpy - wskazane przez --->po lewej stronie następującej kopii / wklej z tego widoku ILSpy:

public Uri Url
{
  get
  {
    if (this._url == null && this._wr != null)
    {
      string text = this.QueryStringText;
      if (!string.IsNullOrEmpty(text))
      {
        text = "?" + HttpEncoder.CollapsePercentUFromStringInternal(text, 
          this.QueryStringEncoding);
      }
 ---> if (AppSettings.UseHostHeaderForRequestUrl)
      {
        string knownRequestHeader = this._wr.GetKnownRequestHeader(28);
        try
        {
          if (!string.IsNullOrEmpty(knownRequestHeader))
          {
            this._url = new Uri(string.Concat(new string[]
            {
              this._wr.GetProtocol(),
              "://",
              knownRequestHeader,
              this.Path,
              text 
            }));
          }
        }
        catch (UriFormatException)
        { }
     }
     if (this._url == null) { /* build from server name and port */
       ...

Ja osobiście nie korzystałem z niego - jest to nieudokumentowane i dlatego nie ma gwarancji, że będę się trzymał - jednak może zrobić to samo, o czym wspomniałem powyżej. W celu zwiększenia trafności w wynikach wyszukiwania - i potwierdzić ktoś, kto seeems odkryli ten - ustawienie zostało również wymienione przez Nick Aceves na Twitterze'aspnet:UseHostHeaderForRequest'


ok, więc gdzie i jak otrzymujesz instancję man HttpRequestBase, powiedzmy, jeśli na przykład nie pracujesz z kodem bezpośrednio w kontrolerze?
PositiveGuy

@CoffeeAddict Cóż, w mvc3 masz HttpContext.Current.Request, ponieważ Asp.net 4 używa podstawowych abstrakcji. Jeśli korzystasz z .net 3.5 lub niższej, możesz użyć HttpRequestWrapper wokół tej samej właściwości, z System.Web.Abstractions
Andras Zoltan

3
Bardzo późno na to, ale dokumentacja UseHostHeaderForRequestUrl jest tutaj udokumentowana msdn.microsoft.com/en-us/library/hh975440.aspx
Kevin Jones

dobre miejsce! przynajmniej dodali go do dokumentacji 4.5!
Andras Zoltan

14
public static string GetCurrentWebsiteRoot()
{
    return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}

12
Request.Url.PathAndQuery

powinien działać idealnie, zwłaszcza jeśli chcesz tylko względnego Uri (ale zachowując kwerendy)


8

Ja również szukałem tego z powodów na Facebooku i żadna z udzielonych odpowiedzi nie działała w razie potrzeby ani nie była zbyt skomplikowana.

@Request.Url.GetLeftPart(UriPartial.Path)

Pobiera pełny protokół, host i ścieżkę „bez” kwerendy. Obejmuje również port, jeśli używasz czegoś innego niż domyślny 80.


Świetne znalezisko! Podejrzewam, że to nie istniało w momencie zapytania? Czuję, że bym to widział :)
Chev

Myślałem, że widziałem, gdzie to właśnie zostało dodane, ale właśnie sprawdziłem i wydaje się, że jest tam od .NET 1.1. Kto wie.
johnw182,

4

Mój ulubiony...

Url.Content(Request.Url.PathAndQuery)

Lub tylko...

Url.Action()

Url.Action () podaje tylko prawą stronę adresu URL, a jeśli potrzebujesz pełnego pełnego adresu URL?
Alok

1

Jedną rzeczą, która nie jest wymieniona w innych odpowiedziach, jest rozróżnianie wielkości liter, jeśli ma się odwoływać w wielu miejscach (czego nie ma w pierwotnym pytaniu, ale warto je wziąć pod uwagę, ponieważ to pytanie pojawia się w wielu podobnych wyszukiwaniach ). W oparciu o inne odpowiedzi, początkowo stwierdziłem, że dla mnie zadziałały:

Request.Url.AbsoluteUri.ToString()

Ale aby być bardziej niezawodnym, stało się to wtedy:

Request.Url.AbsoluteUri.ToString().ToLower()

A następnie według moich wymagań (sprawdzenie, z jakiej nazwy domeny uzyskuje się dostęp do witryny i wyświetlenie odpowiedniej treści):

Request.Url.AbsoluteUri.ToString().ToLower().Contains("xxxx")


To nie czyni go „bardziej niezawodnym”. To, czy zastosowanie małej litery jest przydatne, zależy całkowicie od tego, co faktycznie próbujesz zrobić, i dlaczego rozróżnianie wielkości liter ma tu sens. Zwykle chcesz , aby w adresie URL rozróżniana była wielkość liter.
CodeCaster

1
@CodeCaster Tak, termin „bardziej niezawodny” został oparty na moim własnym doświadczeniu, ponieważ zdecydowanie NIE chcę, aby w adresach URL rozróżniana była wielkość liter, ponieważ nie powoduje to końca problemów dla klientów.
Lyall,

0

Dla mnie problem polegał na tym, że próbowałem uzyskać dostęp HTTPContextdo konstruktora kontrolera, gdy HTTPContextnie jest on jeszcze gotowy. Po przeniesieniu do metody indeksu działało:

var uri = new Uri(Request.Url.AbsoluteUri);
url = uri.Scheme + "://" + uri.Host + "/";enter code here

0

Przypadek (styl pojedynczej strony) dla historii przeglądarki

HttpContext.Request.UrlReferrer
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.