Как получить URL текущей страницы в MVC 3


360

Я использую плагин комментариев Facebook в блоге, который я строю. У него есть некоторые теги FBXML, которые интерпретируются JavaScript-кодом Facebook, на который есть ссылки на странице.

Все это прекрасно работает, но я должен передать текущий полный URL-адрес к плагину.

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

Каков наилучший способ получить URL текущей страницы? URL запроса.

Решение

Вот окончательный код моего решения:

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

Ответы:


534

Вы могли бы использовать Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString()или Request.Url.AbsoluteUri.


2
По какой-то причине, кажется, что не весь URL, а только все после домена.
Chev

6
@ Чевекс, как насчет Request.Url.ToString()или Request.Url.AbsoluteUri?
Дарин Димитров

9
Почти. Request.Url.AbsoluteUriсделал это :)
Chev

2
@Chevex - на каком порту размещен сайт? Если это порт 80, то да, вы его не увидите. Я говорю, что в среде, где есть виртуальный порт публикации IP 80 для одной или нескольких машин на другом порту (например, 81), тогда Asp.Net всегда будет неправильно добавлять: 81 к URL-
Андрас Золтан

29
чтобы получить образцы различных фрагментов URL, взгляните на: cambiaresearch.com/articles/53/…
ms007

48

Добавьте этот метод расширения в ваш код:

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));
}

И тогда вы можете выполнить его за пределами RequestContext.HttpContext.Requestсобственности.

В Asp.Net существует ошибка (ее можно обойти, см. Ниже), которая возникает на компьютерах, которые используют порты, отличные от порта 80, для локального веб-сайта (большая проблема, если внутренние веб-сайты публикуются с помощью балансировки нагрузки на виртуальном IP-адресе и порты используются внутренне для правил публикации), благодаря чему Asp.Net всегда добавляет порт в AbsoluteUriсвойстве - даже если исходный запрос не использует его.

Этот код гарантирует, что возвращаемый URL-адрес всегда будет равен URL-адресу, который первоначально запрашивал браузер (включая порт - как он будет включен в заголовок хоста), прежде чем произойдет какое-либо распределение нагрузки и т. Д.

По крайней мере, в нашей (довольно запутанной!) Среде :)

Если между ними есть какие-нибудь фанки прокси, которые переписывают заголовок хоста, то это тоже не сработает.

Обновление 30 июля 2013

Как упомянуто @KevinJones в комментариях ниже - настройка, о которой я упоминаю в следующем разделе, была задокументирована здесь: http://msdn.microsoft.com/en-us/library/hh975440.aspx

Хотя я должен сказать, что не смог заставить его работать, когда попробовал - но это может быть просто я сделал опечатку или что-то в этом роде.

Обновление 9 июля 2012

Я столкнулся с этим некоторое время назад, и хотел обновить этот ответ, но никогда не делал. Когда на этот ответ пришло возражение, я подумал, что должен сделать это сейчас.

«Ошибка», которую я упоминаю в Asp.Net, может управляться явно недокументированным значением appSettings - называемым 'aspnet:UseHostHeaderForRequest'- то есть:

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

Я сталкивался с этим, просматривая HttpRequest.UrlILSpy - на это указывает --->слева в следующей копии / вставке из этого представления 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 */
       ...

Лично я не использовал его - он не имеет документов и поэтому не гарантированно останется здесь, однако он может сделать то же самое, что я упомянул выше. Для повышения релевантности в результатах поиска - и признать , кто - то другой seeems, что обнаружил это - установка также упоминается Ник Aceves на Twitter'aspnet:UseHostHeaderForRequest'


Хорошо, так где или как вы получаете экземпляр man HttpRequestBase, скажем, если вы, например, не работали с кодом непосредственно в контроллере?
PositiveGuy

@CoffeeAddict Ну, в mvc3 у вас есть HttpContext.Current.Request, поскольку Asp.net 4 использует базовые абстракции. Если на .net 3.5 или ниже, вы можете использовать HttpRequestWrapper вокруг того же свойства, из System.Web.Abstractions
Andras Zoltan

3
Очень поздно, но UseHostHeaderForRequestUrl задокументирован здесь msdn.microsoft.com/en-us/library/hh975440.aspx
Кевин Джонс,

хорошее место! по крайней мере, они наконец-то добавили его для документации 4.5
Андрас Золтан


12
Request.Url.PathAndQuery

должно работать идеально, особенно если вам нужен только относительный Uri (но с сохранением строк запроса)


8

Я тоже искал это по причинам Facebook, и ни один из ответов, приведенных до сих пор, не работал должным образом или был слишком сложным.

@Request.Url.GetLeftPart(UriPartial.Path)

Получает полный протокол, хост и путь "без" строки запроса. Также включает порт, если вы используете что-то, отличное от 80 по умолчанию.


Отличная находка! Я подозреваю, что это не существовало во время запроса? Я чувствую, что видел бы это :)
Chev

Я думал, что видел, где это было только что добавлено, но я только что проверил, и кажется, что это было с .NET 1.1. Кто знает.
johnw182

4

Мое любимое...

Url.Content(Request.Url.PathAndQuery)

или просто...

Url.Action()

Url.Action () предоставляет только правую часть URL, что если вам нужен полный полный URL?
Alok

1

Одна вещь, которая не упоминается в других ответах, это чувствительность к регистру, если на нее будут ссылаться в нескольких местах (чего нет в исходном вопросе, но стоит принять во внимание, так как этот вопрос появляется во многих похожих поисках ). Основываясь на других ответах, я обнаружил, что изначально сработало для меня:

Request.Url.AbsoluteUri.ToString()

Но чтобы быть более надежным, это стало:

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

И затем для моих требований (проверка, с какого доменного имени осуществляется доступ к сайту и показ соответствующего контента):

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


Это не делает его «более надежным». Полезно ли использовать нижний регистр, полностью зависит от того, что вы на самом деле пытаетесь сделать, и почему чувствительность к регистру имеет смысл там. Обычно вы хотите, чтобы URL был чувствительным к регистру.
CodeCaster

1
@CodeCaster Да, термин «более надежный» был основан на моем собственном опыте, так как я определенно НЕ хочу, чтобы URL-адреса чувствительны к регистру, поскольку это не создает никаких проблем для клиентов.
Lyall

0

Для меня проблема была, когда я пытался получить доступ HTTPContextв конструкторе контроллера, пока HTTPContextеще не готов. При перемещении внутри метода Index это работало:

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.