Como obter o URL da página atual no MVC 3

360

Estou usando o plug-in de comentários do Facebook em um blog que estou criando. Ele possui algumas tags FBXML que são interpretadas pelo javascript do facebook mencionado na página.

Isso tudo funciona bem, mas eu tenho que passar a URL atual e totalmente qualificada para o plug-in.

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

Qual é a melhor maneira de obter o URL da página atual? O URL da solicitação.

Solução

Aqui está o código final da minha solução:

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

Respostas:

533

Você pode usar o Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString()ou Request.Url.AbsoluteUri.

Darin Dimitrov
fonte
2
Por alguma razão, isso não parece ter o URL inteiro, apenas tudo depois do domínio.
Chev
6
@ Chevex, que tal Request.Url.ToString()ou Request.Url.AbsoluteUri?
precisa
9
Quase. Request.Url.AbsoluteUrifez isso :)
Chev
2
@ Chevex - em que porta está o site hospedado? Se for a porta 80, sim, você não verá uma. Eu estou dizendo que em um ambiente onde há um IP virtual de publicação a porta 80 para uma ou mais máquinas em um diferente porta (por exemplo, 81), em seguida, Asp.Net sempre acrescentar: 81 para o URL incorretamente
Andras Zoltan
29
para obter amostras dos diferentes fragmentos de URL têm uma olhada: cambiaresearch.com/articles/53/...
ms007
48

Adicione este método de extensão ao seu código:

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

E então você pode executá-lo fora da RequestContext.HttpContext.Requestpropriedade.

Existe um bug (pode ser evitado, veja abaixo) no Asp.Net que surge em máquinas que usam portas diferentes da porta 80 para o site local (um grande problema se sites internos forem publicados via balanceamento de carga no IP virtual e ports são usados ​​internamente para publicar regras), em que o Asp.Net sempre adiciona a porta à AbsoluteUripropriedade - mesmo que a solicitação original não a utilize.

Esse código garante que a URL retornada seja sempre igual à URL solicitada originalmente pelo navegador (incluindo a porta - como seria incluída no cabeçalho do host) antes que qualquer balanceamento de carga etc. ocorra.

Pelo menos, acontece em nosso ambiente (bastante complicado!) :)

Se houver proxies descolados que reescrevam o cabeçalho do host, isso também não funcionará.

Atualização 30 de julho de 2013

Conforme mencionado por @ KevinJones nos comentários abaixo - a configuração mencionada na próxima seção foi documentada aqui: http://msdn.microsoft.com/en-us/library/hh975440.aspx

Embora eu tenha que dizer que não consegui fazê-lo funcionar quando tentei - mas isso poderia ser apenas eu cometendo um erro de digitação ou algo assim.

Atualização 9 de julho de 2012

Me deparei com isso há pouco tempo e pretendia atualizar essa resposta, mas nunca o fiz. Quando um voto positivo apareceu nesta resposta, pensei que deveria fazê-lo agora.

O 'bug' mencionado no Asp.Net pode ser controlado com um valor appSettings aparentemente não documentado - chamado 'aspnet:UseHostHeaderForRequest'- ou seja:

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

Me deparei com isso enquanto olhava no HttpRequest.UrlILSpy - indicado pelo --->lado esquerdo da seguinte cópia / pasta a partir dessa exibição do 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 */
       ...

Eu pessoalmente não o usei - não é documentado e, portanto, não é garantido que permaneça por aqui - no entanto, pode fazer a mesma coisa que mencionei acima. Para aumentar a relevância nos resultados de pesquisa - e reconhecer alguém que parece ter descoberto isso - a 'aspnet:UseHostHeaderForRequest'configuração também foi mencionada por Nick Aceves no Twitter

Andras Zoltan
fonte
ok então onde ou como você está recebendo a instância man do HttpRequestBase, digamos se você não estava trabalhando com código diretamente em um controlador, por exemplo?
PositiveGuy
@CoffeeAddict Bem, no mvc3 você tem o HttpContext.Current.Request, já que o Asp.net 4 usa as abstrações de base. Se em .NET 3.5 ou inferior, você pode usar HttpRequestWrapper em torno da mesma propriedade, de System.Web.Abstractions
Andras Zoltan
3
Muito tarde para isso, mas o UseHostHeaderForRequestUrl está documentado aqui msdn.microsoft.com/en-us/library/hh975440.aspx
Kevin Jones
bom lugar! pelo menos eles finalmente o adicionaram para a documentação 4.5!
Andras Zoltan
14
public static string GetCurrentWebsiteRoot()
{
    return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}
Brian Ogden
fonte
12
Request.Url.PathAndQuery

deve funcionar perfeitamente, especialmente se você deseja apenas o Uri relativo (mas mantendo as strings de consulta)

Lucius
fonte
8

Eu também estava procurando por razões do Facebook e nenhuma das respostas dadas até agora funcionou conforme necessário ou é muito complicada.

@Request.Url.GetLeftPart(UriPartial.Path)

Obtém o protocolo completo, host e caminho "sem" a string de consulta. Também inclui a porta se você estiver usando algo diferente do padrão 80.

johnw182
fonte
Ótima descoberta! Eu suspeito que isso não existia no momento da pergunta? Eu sinto que eu teria visto que :)
Chev
Eu pensei ter visto onde isso foi adicionado, mas verifiquei e parece que existe desde o .NET 1.1. Quem sabe.
precisa saber é o seguinte
4

Meu favorito...

Url.Content(Request.Url.PathAndQuery)

ou apenas...

Url.Action()
Carter Medlin
fonte
Url.Action () fornece apenas o lado direito do URL, e se você precisar de um URL completo?
Alok
1

Uma coisa que não é mencionada em outras respostas é a distinção entre maiúsculas e minúsculas, se ela será referenciada em vários lugares (o que não está na pergunta original, mas vale a pena levar em consideração, pois essa pergunta aparece em muitas pesquisas semelhantes ) Com base em outras respostas, achei o seguinte funcionou para mim inicialmente:

Request.Url.AbsoluteUri.ToString()

Mas, para ser mais confiável, isso se tornou:

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

E depois, para meus requisitos (verificar de que nome de domínio o site está sendo acessado e mostrar o conteúdo relevante):

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

Lyall
fonte
Isso não o torna "mais confiável". Se o uso de letras minúsculas é útil depende inteiramente do que você está realmente tentando fazer e por que a distinção entre maiúsculas e minúsculas faria sentido. Geralmente, você deseja que o URL faça distinção entre maiúsculas e minúsculas.
CodeCaster
11
@CodeCaster Sim, o termo 'mais confiável' foi baseado em minha própria experiência, pois eu definitivamente NÃO quero que os URLs diferenciam maiúsculas de minúsculas, pois isso não causa problemas para os clientes.
precisa
0

Para mim, o problema foi quando tentei acessar HTTPContexto construtor do Controlador enquanto HTTPContextainda não estava pronto. Quando movido para dentro do método Index, funcionou:

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

O caso (estilo de página única) para o histórico do navegador

HttpContext.Request.UrlReferrer
Hamit YILDIRIM
fonte