Як отримати 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>

Відповіді:


533

Ви могли б використовувати Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString()або Request.Url.AbsoluteUri.


2
З певної причини, схоже, ця URL-адреса не отримує всю URL-адресу, а лише все після домену.
Шев

6
@Chevex, як щодо Request.Url.ToString()чи Request.Url.AbsoluteUri?
Дарин Димитров

9
Майже. Request.Url.AbsoluteUriзробив це :)
Шев

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.Urlв ILSpy - позначено --->ліворуч від наступної копії / вставки з цього виду 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'


гаразд, де або як ви отримуєте екземпляр людини HttpRequestBase, що дозволяє говорити, якщо ви не працювали з кодом безпосередньо в контролері, наприклад?
PositiveGuy

@CoffeeAddict Ну, у mvc3 у вас є HttpContext.Current.Request, оскільки Asp.net 4 використовує базові абстракції. Якщо на .net 3.5 або нижче, ви можете використовувати HttpRequestWrapper навколо тієї ж власності, від System.Web.Abstractions
Андраш Золтан

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

гарне місце! принаймні, вони нарешті додали його для 4,5 документації!
Андрас Золтан


12
Запит.Url.PathAndQuery

повинен працювати ідеально, особливо якщо ви хочете лише відносного Uri (але зберігаючи запити)


8

Я теж шукав це з причин Facebook, і жоден із наведених відповідей поки що не працював у міру потреби або занадто складний.

@Request.Url.GetLeftPart(UriPartial.Path)

Отримує повний протокол, хост і шлях "без" рядка запиту. Також включає порт, якщо ви використовуєте щось інше, ніж 80 за замовчуванням.


Чудова знахідка! Я підозрюю, що цього не було на момент запитання? Я відчуваю, що бачив би це :)
Шев

Я думав, що побачив, де це було додано, але я щойно перевірив, і, здається, він був з .NET 1.1. Хто знає.
johnw182

4

Мій улюблений...

Url.Content(Request.Url.PathAndQuery)

або просто ...

Url.Action()

Url.Action () надає лише праву частину URL-адреси, що робити, якщо вам потрібен повний повний URL-адрес?
Алок

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до конструктора Controller, поки він 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.