2010-01-05 31 views
325

¿Existe una forma integrada de obtener la URL completa de una acción?Obtener la URL de acción completa en ASP.NET MVC

Estoy buscando algo como GetFullUrl("Action", "Controller") que devolvería algo así como http://www.fred.com/Controller/Action.

La razón por la que estoy buscando esto es evitar las URL de codificación rígida en los correos electrónicos automáticos que se generan para que las URL siempre se puedan generar en relación con la ubicación actual del sitio.

+0

Vea también: http://stackoverflow.com/q/434604 – Andrew

Respuesta

503

Hay una sobrecarga de Url.Action que toma el protocolo deseado (por ejemplo, http, https) como argumento; si especifica esto, obtiene una URL totalmente calificada.

He aquí un ejemplo que utiliza el protocolo de la solicitud actual en un método de acción:

var fullUrl = this.Url.Action("Edit", "Posts", new { id = 5 }, this.Request.Url.Scheme); 

HtmlHelper (@Html) también tiene una sobrecarga del método ActionLink que se puede utilizar en la maquinilla de afeitar para crear un ancla elemento, pero también requiere los parámetros hostName y fragment. Así que me acaba de optar por usar @ Url.Action nuevo:

<span> 
    Copy 
    <a href='@Url.Action("About", "Home", null, Request.Url.Scheme)'>this link</a> 
    and post it anywhere on the internet! 
</span> 
+4

No moleste, podría pensar que todavía debería haber una mejor manera de hacerlo, pero bueno ... – Paddy

+0

Al realizar pruebas locales con el emulador de Azure esto devuelve el puerto 82 en lugar del puerto correcto 81. No estoy seguro si esto funciona bien cuando se publica o no. La respuesta propuesta por Marius Schulz funciona perfecto sin embargo. – angularsen

+1

La URL correcta es 'https: // 127.0.0.1/Home/Index' pero genera' https: //127.0.0.1: 444/Home/Index'. No debe tener puerto. Estoy ejecutando el emulador de Azure. Por favor ayuda. – fiberOptics

123

Como se mencionó arroz: si se utiliza una sobrecarga de UrlHelper.Action() que especifica explícitamente el protocolo a utilizar, la URL generada será absoluta y totalmente cualificado en lugar de ser relativo.

escribí un post llamado How to build absolute action URLs using the UrlHelper class en el que sugiero escribir un método de extensión personalizada para facilitar la lectura:

/// <summary> 
/// Generates a fully qualified URL to an action method by using 
/// the specified action name, controller name and route values. 
/// </summary> 
/// <param name="url">The URL helper.</param> 
/// <param name="actionName">The name of the action method.</param> 
/// <param name="controllerName">The name of the controller.</param> 
/// <param name="routeValues">The route values.</param> 
/// <returns>The absolute URL.</returns> 
public static string AbsoluteAction(this UrlHelper url, 
    string actionName, string controllerName, object routeValues = null) 
{ 
    string scheme = url.RequestContext.HttpContext.Request.Url.Scheme; 

    return url.Action(actionName, controllerName, routeValues, scheme); 
} 

continuación, puede simplemente usarlo como que en su opinión:

@Url.AbsoluteAction("Action", "Controller") 
+0

Desearía tener más votos positivos, esto es en realidad una obviedad que debería estar en el marco IMO – Roger

+7

Lo único que agregaría (o modificaría) es reemplazar el literal "http" con HttpContext.Current.Request.Url.Scheme . Esto permitirá que https se use cuando sea apropiado. – Jay

+0

@Jay, gracias por su sugerencia, he actualizado el ejemplo de mi código. Recibí los mismos comentarios en mi blog ;-). –

0

Esta pregunta es específica de ASP .NET, sin embargo, estoy seguro de que algunos de ustedes se beneficiarán de javascript independiente del sistema que es beneficioso en muchas situaciones.

ACTUALIZACIÓN: La forma de obtener url formó fuera de la página se describe bien en las respuestas anteriores.

O usted podría hacer un oneliner como siguiente:

new UrlHelper(actionExecutingContext.RequestContext).Action(
    "SessionTimeout", "Home", 
    new {area = string.Empty}, 
    actionExecutingContext.Request.Url!= null? 
    actionExecutingContext.Request.Url.Scheme : "http" 
); 

de filtro o:

new UrlHelper(this.Request.RequestContext).Action(
    "Details", 
    "Journey", 
    new { area = productType }, 
    this.Request.Url!= null? this.Request.Url.Scheme : "http" 
); 

Sin embargo a menudo es necesario para obtener la URL de la página actual, para aquellos casos utilizando Html.Action y poner el nombre y el controlador de la página en la que me encuentras se siente incómodo. Mi preferencia en tales casos es usar JavaScript en su lugar. Esto es especialmente bueno en sistemas que están medio reescritos MVT medio web-forms medio vb-script medio Dios sabe qué - y para obtener el URL de la página actual uno necesita usar un método diferente cada vez.

Una forma es utilizar JavaScript para obtener la URL es otra window.location.href - document.URL

+1

Esto solo funcionaría para presentar la URL de la página actual. Lo que el OP quiere hacer es pasar los nombres de un controlador .Net y Ver para generar la URL para llegar a esa página. – Matthew

0

esto puede ser justo que yo estaba muy, muy exigente, pero me gusta definir solamente una vez constantes. Si usa cualquiera de los enfoques definidos anteriormente, su constante de acción se definirá varias veces.

Para evitar esto, se puede hacer lo siguiente:

public class Url 
    { 
     public string LocalUrl { get; } 

     public Url(string localUrl) 
     { 
      LocalUrl = localUrl; 
     } 

     public override string ToString() 
     { 
      return LocalUrl; 
     } 
    } 

    public abstract class Controller 
    { 
     public Url RootAction => new Url(GetUrl()); 

     protected abstract string Root { get; } 

     public Url BuildAction(string actionName) 
     { 
      var localUrl = GetUrl() + "/" + actionName; 
      return new Url(localUrl); 
     } 

     private string GetUrl() 
     { 
      if (Root == "") 
      { 
       return ""; 
      } 

      return "/" + Root; 
     } 

     public override string ToString() 
     { 
      return GetUrl(); 
     } 
    } 

A continuación, crear sus controladores, digamos por ejemplo el DataController:

public static readonly DataController Data = new DataController(); 
    public class DataController : Controller 
    { 
     public const string DogAction = "dog"; 
     public const string CatAction = "cat"; 
     public const string TurtleAction = "turtle"; 

     protected override string Root => "data"; 

     public Url Dog => BuildAction(DogAction); 
     public Url Cat => BuildAction(CatAction); 
     public Url Turtle => BuildAction(TurtleAction); 
    } 

A continuación, sólo usarlo como:

// GET: Data/Cat 
    [ActionName(ControllerRoutes.DataController.CatAction)] 
    public ActionResult Etisys() 
    { 
     return View(); 
    } 

Y desde su .cshtml (o cualquier código)

<ul> 
    <li><a href="@ControllerRoutes.Data.Dog">Dog</a></li> 
    <li><a href="@ControllerRoutes.Data.Cat">Cat</a></li> 
</ul> 

Esto es definitivamente mucho más trabajo, pero estoy tranquilo sabiendo que la validación del tiempo de compilación está de mi parte.

1

Esto es lo que debe hacer.

@Url.Action(action,controller, null, Request.Url.Scheme) 
+2

Esto es lo mismo que la respuesta aceptada. Las respuestas se publican mejor cuando se introduce algo nuevo. – Doomsknight

0

Estaba teniendo un problema con esto, mi servidor funcionaba detrás de un equilibrador de carga. El equilibrador de carga estaba terminando la conexión SSL/TLS. Luego pasó la solicitud a los servidores web usando http.

Usando el método Url.Action() con Request.Url.Schema, siguió creando una url http, en mi caso para crear un enlace en un correo electrónico automático (que a mi PenTester no le gustó).

que puede haber una pequeña trampa, pero es exactamente lo que necesitaba para forzar una URL https:

<a href="@Url.Action("Action", "Controller", new { id = Model.Id }, "https")">Click Here</a> 

realidad yo uso un web.config appSetting para que pueda utilizar http al depurar localmente, pero todos los entornos de prueba y prod utilizan transformación para establecer el valor https.

Cuestiones relacionadas