Cómo obtener la URL de la página actual en MVC 3

360

Estoy usando el complemento de comentarios de Facebook en un blog que estoy construyendo. Tiene algunas etiquetas FBXML que son interpretadas por el javascript de Facebook al que se hace referencia en la página.

Todo esto funciona bien, pero tengo que pasar la URL actual y totalmente calificada al complemento.

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

¿Cuál es la mejor manera de obtener la URL de la página actual? La URL de solicitud.

Solución

Aquí está el código final de mi solución:

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

Respuestas:

533

Se podría utilizar el Request.RawUrl, Request.Url.OriginalString, Request.Url.ToString()o Request.Url.AbsoluteUri.

Darin Dimitrov
fuente
2
Por alguna razón, esto no parece obtener la URL completa, solo todo después del dominio.
Chev
66
@Chevex, ¿qué tal Request.Url.ToString()o Request.Url.AbsoluteUri?
Darin Dimitrov
99
Casi. Request.Url.AbsoluteUrilo hizo :)
Chev
2
@Chevex: ¿en qué puerto está alojado el sitio? Si es el puerto 80, entonces, sí, no verá uno. Estoy diciendo que en un entorno donde hay un puerto de publicación de IP virtual 80 para una o más máquinas en un puerto diferente (por ejemplo, 81), Asp.Net siempre agregará: 81 a la URL incorrectamente
Andras Zoltan
29
para obtener muestras de los diferentes fragmentos de URL, consulte: cambiaresearch.com/articles/53/…
ms007
48

Agregue este método de extensión a su 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));
}

Y luego puedes ejecutarlo desde RequestContext.HttpContext.Request propiedad.

Hay un error (se puede evitar, ver a continuación) en Asp.Net que surge en máquinas que usan puertos que no son el puerto 80 para el sitio web local (un gran problema si los sitios web internos se publican a través del equilibrio de carga en IP virtual) y los puertos se usan internamente para publicar reglas) por lo que Asp.Net siempre agregará el puerto en elAbsoluteUri propiedad, incluso si la solicitud original no lo usa.

Este código garantiza que la url devuelta siempre sea igual a la url que el navegador solicitó originalmente (incluido el puerto, ya que se incluiría en el encabezado del host) antes de que tenga lugar un equilibrio de carga, etc.

Al menos, lo hace en nuestro entorno (¡bastante complicado!) :)

Si hay algún proxy funky en el medio que reescriba el encabezado del host, entonces esto tampoco funcionará.

Actualización 30 de julio de 2013

Como mencionó @KevinJones en los comentarios a continuación, la configuración que menciono en la siguiente sección se ha documentado aquí: http://msdn.microsoft.com/en-us/library/hh975440.aspx

Aunque tengo que decir que no pude hacerlo funcionar cuando lo probé, pero eso podría ser solo yo haciendo un error tipográfico o algo así.

Actualización 9 de julio de 2012

Me encontré con esto hace un momento, y tenía la intención de actualizar esta respuesta, pero nunca lo hice. Cuando llegó un voto positivo sobre esta respuesta, pensé que debería hacerlo ahora.

El 'error' que menciono en Asp.Net se puede controlar con un valor de configuración de aplicación aparentemente indocumentado, llamado 'aspnet:UseHostHeaderForRequest', es decir:

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

Me encontré con esto mientras miraba HttpRequest.Urlen ILSpy, indicado por --->la izquierda de la siguiente copia / pegado de esa vista de 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 */
       ...

Personalmente no lo he usado, es indocumentado y, por lo tanto, no se garantiza que se quede, sin embargo, podría hacer lo mismo que mencioné anteriormente. Para aumentar la relevancia en los resultados de búsqueda, y para reconocer a alguien más que parece haber descubierto esto, Nick Aceves también ha mencionado la 'aspnet:UseHostHeaderForRequest'configuración en Twitter.

Andras Zoltan
fuente
ok, ¿dónde o cómo está obteniendo la instancia de hombre de HttpRequestBase, digamos si no estaba trabajando con código directamente en un controlador, por ejemplo?
PositiveGuy
@CoffeeAddict Bueno, en mvc3 tienes HttpContext.Current.Request, ya que Asp.net 4 usa las abstracciones básicas. Si está en .net 3.5 o inferior, puede usar HttpRequestWrapper alrededor de la misma propiedad, desde System.Web.Abstraction
Andras Zoltan el
3
Muy tarde para esto, pero UseHostHeaderForRequestUrl está documentado aquí msdn.microsoft.com/en-us/library/hh975440.aspx
Kevin Jones
¡buen lugar! ¡al menos finalmente lo agregaron para la documentación 4.5!
Andras Zoltan
14
public static string GetCurrentWebsiteRoot()
{
    return HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
}
Brian Ogden
fuente
12
Request.Url.PathAndQuery

debería funcionar perfectamente, especialmente si solo desea el Uri relativo (pero manteniendo las cadenas de consulta)

Lucius
fuente
8

Yo también estaba buscando esto por razones de Facebook y ninguna de las respuestas dadas hasta ahora funcionó según sea necesario o es demasiado complicada.

@Request.Url.GetLeftPart(UriPartial.Path)

Obtiene el protocolo completo, el host y la ruta "sin" la cadena de consulta. También incluye el puerto si está utilizando algo distinto del valor predeterminado 80.

johnw182
fuente
Gran descubrimiento! Sospecho que esto no existía a la hora de preguntar? Siento que hubiera visto eso :)
Chev
Pensé que vi dónde se acaba de agregar esto, pero acabo de verificar y parece que ha estado allí desde .NET 1.1. Quién sabe.
johnw182
4

Mi favorito...

Url.Content(Request.Url.PathAndQuery)

o solo...

Url.Action()
Carter Medlin
fuente
Url.Action () solo proporciona el lado derecho de la url, ¿qué sucede si necesita una url completa?
Alok
1

Una cosa que no se menciona en otras respuestas es la distinción entre mayúsculas y minúsculas, si se hará referencia en varios lugares (lo cual no se encuentra en la pregunta original pero vale la pena tener en cuenta ya que esta pregunta aparece en muchas búsquedas similares ) Basado en otras respuestas, encontré que lo siguiente funcionó para mí inicialmente:

Request.Url.AbsoluteUri.ToString()

Pero para ser más confiable, esto se convirtió en:

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

Y luego, para mis requisitos (verificar desde qué nombre de dominio se accede al sitio y mostrar el contenido relevante):

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

Lyall
fuente
Eso no lo hace "más confiable". Si las minúsculas son útiles depende completamente de lo que realmente estás tratando de hacer, y por qué la distinción entre mayúsculas y minúsculas tendría sentido allí. Por lo general , desea que la URL distinga entre mayúsculas y minúsculas.
CodeCaster
1
@CodeCaster Sí, el término 'más confiable' se basó en mi propia experiencia, ya que definitivamente NO quiero que las URL distingan entre mayúsculas y minúsculas, ya que no causa problemas a los clientes.
Lyall
0

Para mí, el problema fue cuando intenté acceder HTTPContexten el constructor del controlador mientras HTTPContextaún no estaba listo. Cuando se movió dentro del método Index funcionó:

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

El caso (estilo de página única) para el historial del navegador

HttpContext.Request.UrlReferrer
Hamit YILDIRIM
fuente