2008-09-24 24 views
59

Esto probablemente se explica más fácilmente con un ejemplo. Estoy intentando encontrar una forma de convertir una URL relativa, p. "/Foo.aspx" o "~/Foo.aspx" en una URL completa, p. http://localhost/Foo.aspx. De esa forma, cuando implemente para probar o escenificar, donde el dominio bajo el cual se ejecuta el sitio es diferente, obtendré http://test/Foo.aspx y http://stage/Foo.aspx.¿Cómo convierto una URL relativa en una URL completa?

¿Alguna idea?

+0

2 respuestas relacionadas en: http: // stackoverflow .com/questions/7413466/how-can-i-get-the-baseurl-of-site y http://stackoverflow.com/questions/3933662/in-asp-net-what-is-the-quickest-way -to-get-the-base-url-for-a-request –

Respuesta

57

tener un juego con esto (modificado from here)

public string ConvertRelativeUrlToAbsoluteUrl(string relativeUrl) { 
    return string.Format("http{0}://{1}{2}", 
     (Request.IsSecureConnection) ? "s" : "", 
     Request.Url.Host, 
     Page.ResolveUrl(relativeUrl) 
    ); 
} 
+3

Tenía la esperanza de que hubiera algo incorporado en ASP .NET, así que no tengo que entrar en el negocio de buscar protocolos, puertos, etc. pero esto debería hacer el trabajo. – gilles27

+7

Solo una nota: cuando utilicé esto, agregué Request.URL.Port entre el host y la URL de la página para que funcionara en el servidor de pruebas Visual Web Dev. – ine

+0

@roviuser Tthis no tiene nada que ver con MVC. Es solo una función de utilidad, así que adhiérelo donde desee. – Oli

5

Ésta es mi función auxiliar para hacer esto

public string GetFullUrl(string relativeUrl) { 
    string root = Request.Url.GetLeftPart(UriPartial.Authority); 
    return root + Page.ResolveUrl("~/" + relativeUrl) ; 
} 
+0

¿Esto todavía funciona para usted en ASP.net 4.0? Tengo un enfoque similar y obtengo la IP del servidor como root, en lugar del dominio. ¿Por qué sería eso? –

2

Ésta es la función de ayuda que he creado para hacer la conversión.

//"~/SomeFolder/SomePage.aspx" 
public static string GetFullURL(string relativePath) 
{ 
    string sRelative=Page.ResolveUrl(relativePath); 
    string sAbsolute=Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery,sRelative); 
    return sAbsolute; 
} 
30

Sólo tiene que crear una nueva URI utilizando el page.request.url y luego obtener el AbsoluteUri de que:

New System.Uri(Page.Request.Url, "Foo.aspx").AbsoluteUri 
+0

Esto parece brillante en su simplicidad, pero ¿el 'Request.Url' normalmente no incluye el nombre de la página ya solicitada? ¿Por qué' OldFoo.aspx' no aparece con 'Foo.aspx'? (Es decir: es' nuevo Uri () 'pelando el URI base antes de combinarlo con la parte relativa?) – ebyrob

+3

@ebyrob El constructor Uri (Uri, cadena) tira cualquier parte relativa del primer parámetro y luego lo combina con el 2 ° parámetro. Los documentos de MSDN en [Uri constructor] (https://msdn.microsoft.com/en-us/library/9hst1w91 (v = vs.110) .aspx) no dejan esto en claro, pero esta [prueba de violín] (https: //dotnetfiddle.net/WHUjkY) verifica el comportamiento. –

37

Ésta ha sido venció a la muerte, pero pensé que había puesto mi propia solución que Creo que es más limpio que muchas de las otras respuestas.

public static string AbsoluteAction(this UrlHelper url, string actionName, string controllerName, object routeValues) 
{ 
    return url.Action(actionName, controllerName, routeValues, url.RequestContext.HttpContext.Request.Url.Scheme); 
} 

public static string AbsoluteContent(this UrlHelper url, string path) 
{ 
    Uri uri = new Uri(path, UriKind.RelativeOrAbsolute); 

    //If the URI is not already absolute, rebuild it based on the current request. 
    if (!uri.IsAbsoluteUri) 
    { 
     Uri requestUrl = url.RequestContext.HttpContext.Request.Url; 
     UriBuilder builder = new UriBuilder(requestUrl.Scheme, requestUrl.Host, requestUrl.Port); 

     builder.Path = VirtualPathUtility.ToAbsolute(path); 
     uri = builder.Uri; 
    } 

    return uri.ToString(); 
} 
+1

Estos métodos son impresionantes. ¡Gracias una tonelada! Gran extensión. Intenté con otro como este, pero esto es mucho más limpio, y me gusta encauzar las cosas mucho mejor. Gracias. – Ryan

+2

Encontré esto. Gracias. Agregué un ligero cambio que evita el esquema URl codificado: 'código' return url.Action (actionName, controllerName, routeValues, url.RequestContext.HttpContext.Request.Url.Scheme); 'código' –

+0

@ LSU.Net: Agregando su cambio. Creo que así es como lo tengo en mi código personal también. –

1

Simplemente:

url = new Uri(baseUri, url); 
3

pensé que me gustaría compartir mi acercamiento a hacer esto en ASP.NET MVC utilizando la clase Uri y un poco de magia de extensión.

public static class UrlHelperExtensions 
{ 
    public static string AbsolutePath(this UrlHelper urlHelper, 
             string relativePath) 
    { 
     return new Uri(urlHelper.RequestContext.HttpContext.Request.Url, 
         relativePath).ToString(); 
    } 
} 

Usted puede entonces enviar una ruta absoluta usando:

// gives absolute path, e.g. https://example.com/customers 
Url.AbsolutePath(Url.Action("Index", "Customers")); 

se ve un poco feo tener el método anidado llama así que prefiero para ampliar aún más UrlHelper con los métodos comunes de actuación para que pueda hacer:

// gives absolute path, e.g. https://example.com/customers 
Url.AbsoluteAction("Index", "Customers"); 

o

Url.AbsoluteAction("Details", "Customers", new{id = 123}); 

La clase extensión completa es la siguiente:

public static class UrlHelperExtensions 
{ 
    public static string AbsolutePath(this UrlHelper urlHelper, 
             string relativePath) 
    { 
     return new Uri(urlHelper.RequestContext.HttpContext.Request.Url, 
         relativePath).ToString(); 
    } 

    public static string AbsoluteAction(this UrlHelper urlHelper, 
             string actionName, 
             string controllerName) 
    { 
     return AbsolutePath(urlHelper, 
          urlHelper.Action(actionName, controllerName)); 
    } 

    public static string AbsoluteAction(this UrlHelper urlHelper, 
             string actionName, 
             string controllerName, 
             object routeValues) 
    { 
     return AbsolutePath(urlHelper, 
          urlHelper.Action(actionName, 
              controllerName, routeValues)); 
    } 
} 
1

En ASP.NET MVC puede utilizar las sobrecargas de HtmlHelper o UrlHelper que tome las o host parámetros. Cuando cualquiera de estos parámetros no están vacíos, los ayudantes generan una URL absoluta. Este es un método de extensión que estoy usando:

public static MvcHtmlString ActionLinkAbsolute<TViewModel>(
    this HtmlHelper<TViewModel> html, 
    string linkText, 
    string actionName, 
    string controllerName, 
    object routeValues = null, 
    object htmlAttributes = null) 
{ 
    var request = html.ViewContext.HttpContext.Request; 
    var url = new UriBuilder(request.Url); 
    return html.ActionLink(linkText, actionName, controllerName, url.Scheme, url.Host, null, routeValues, htmlAttributes); 
} 

Y úsala desde una vista Razor, p.:

@Html.ActionLinkAbsolute("Click here", "Action", "Controller", new { id = Model.Id }) 
0

Antigua pregunta, pero pensé que la respondería ya que muchas de las respuestas están incompletas.

public static string ResolveFullUrl(this System.Web.UI.Page page, string relativeUrl) 
{ 
    if (string.IsNullOrEmpty(relativeUrl)) 
     return relativeUrl; 

    if (relativeUrl.StartsWith("/")) 
     relativeUrl = relativeUrl.Insert(0, "~"); 
    if (!relativeUrl.StartsWith("~/")) 
     relativeUrl = relativeUrl.Insert(0, "~/"); 

    return $"{page.Request.Url.Scheme}{Uri.SchemeDelimiter}{page.Request.Url.Authority}{VirtualPathUtility.ToAbsolute(relativeUrl)}"; 
} 

Esto funciona como una extensión de fuera de la página, al igual que ResolveUrl y ResolveClientUrl de formularios web. Siéntase libre de convertirlo a una extensión HttpResponse si lo desea o necesita usarlo en un entorno que no sea de webforms. Maneja correctamente tanto http como https, en puertos estándar y no estándar, y si hay un componente de nombre de usuario/contraseña. Tampoco usa cadenas codificadas de forma rígida (a saber: //).

0

Aquí hay un enfoque. Esto no le importa si la cadena es relativa o absoluta, pero debe proporcionar una baseUri para que la use.

/// <summary> 
    /// This function turns arbitrary strings containing a 
    /// URI into an appropriate absolute URI. 
    /// </summary> 
    /// <param name="input">A relative or absolute URI (as a string)</param> 
    /// <param name="baseUri">The base URI to use if the input parameter is relative.</param> 
    /// <returns>An absolute URI</returns> 
    public static Uri MakeFullUri(string input, Uri baseUri) 
    { 
     var tmp = new Uri(input, UriKind.RelativeOrAbsolute); 
     //if it's absolute, return that 
     if (tmp.IsAbsoluteUri) 
     { 
      return tmp; 
     } 
     // build relative on top of the base one instead 
     return new Uri(baseUri, tmp); 
    } 

En un contexto ASP.NET, se puede hacer esto:

Uri baseUri = new Uri("http://yahoo.com/folder"); 
Uri newUri = MakeFullUri("/some/path?abcd=123", baseUri); 
// 
//newUri will contain http://yahoo.com/some/path?abcd=123 
// 
Uri newUri2 = MakeFullUri("some/path?abcd=123", baseUri); 
// 
//newUri2 will contain http://yahoo.com/folder/some/path?abcd=123 
// 
Uri newUri3 = MakeFullUri("http://google.com", baseUri); 
// 
//newUri3 will contain http://google.com, and baseUri is not used at all. 
// 
0

Modificado de otra respuesta para el trabajo con los puertos localhost y otros ... im utilizando por ej. enlaces de correo electrónico. Puede llamar desde cualquier parte de la aplicación, no sólo en una página o control de usuario, pongo esto en Global por no necesita pasar HttpContext.Current.Request como parámetro

  /// <summary> 
      /// Return full URL from virtual relative path like ~/dir/subir/file.html 
      /// usefull in ex. external links 
      /// </summary> 
      /// <param name="rootVirtualPath"></param> 
      /// <returns></returns> 
      public static string GetAbsoluteFullURLFromRootVirtualPath(string rootVirtualPath) 
      { 

       return string.Format("http{0}://{1}{2}{3}", 
        (HttpContext.Current.Request.IsSecureConnection) ? "s" : "" 
        , HttpContext.Current.Request.Url.Host 
        , (HttpContext.Current.Request.Url.IsDefaultPort) ? "" : ":" + HttpContext.Current.Request.Url.Port 
        , VirtualPathUtility.ToAbsolute(rootVirtualPath) 
        ); 

      } 
Cuestiones relacionadas