¿Cómo encuentro la url absoluta de una acción en ASP.NET MVC?

239

Necesito hacer algo como esto:

<script type="text/javascript">
    token_url = "http://example.com/your_token_url";
</script>

Estoy usando la versión Beta de MVC, pero no puedo entender cómo obtener la URL absoluta de una acción. Me gustaría hacer algo como esto:

<%= Url.AbsoluteAction("Action","Controller")) %>

¿Hay un método auxiliar o de página para esto?

Mike Comstock
fuente

Respuestas:

480

Haga clic aquí para obtener más información, pero esencialmente no hay necesidad de métodos de extensión. Ya está horneado, solo que no de una manera muy intuitiva.

Url.Action("Action", null, null, Request.Url.Scheme);
Adam Boddington
fuente
66
Interesante, así que si especifica el protocolo, la URL es absoluta
Casebash
24
Esta respuesta es la mejor, de esta manera Resharper aún puede validar que existe la Acción y el Controlador. Sugeriría el uso de Request.Url.Scheme en lugar de http, de esa manera se admiten http y https.
Pbirkoff
2
@Pbirkoff, acepta que esta es la mejor respuesta, pero te gustaría saber que puedes anotar tus propios métodos para que ReSharper sepa que los parámetros representan acciones / controladores. De esa manera, R # aún puede validar las cadenas que proporciona, como lo hace muy bien.
Drew Noakes
3
Una pequeña mejora podría ser reemplazar "http" por Request.Url.Schemelo que si usa HTTPS, la URL generada también usará HTTPS.
Erik Schierboom
1
Esto también funciona Html.ActionLink(cualquiera de los métodos que toman un protocolo, los 2 últimos en MVC 4, por ejemplo)
Chris
74

Extienda el UrlHelper

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(this UrlHelper url, string action, string controller)
        {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;

            string absoluteAction = string.Format(
                "{0}://{1}{2}",
                requestUrl.Scheme,
                requestUrl.Authority,
                url.Action(action, controller));

            return absoluteAction;
        }
    }
}

Entonces llámalo así

<%= Url.AbsoluteAction("Dashboard", "Account")%>

EDITAR - ANOTACIONES DE RESHARPER

El comentario más votado sobre la respuesta aceptada es This answer is the better one, this way Resharper can still validate that the Action and Controller exists.Entonces, aquí hay un ejemplo de cómo podría obtener el mismo comportamiento.

using JetBrains.Annotations

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(
            this UrlHelper url,
            [AspMvcAction]
            string action,
            [AspMvcController]
            string controller)
        {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;

            string absoluteAction = string.Format(
                "{0}://{1}{2}",
                requestUrl.Scheme,
                requestUrl.Authority,
                url.Action(action, controller));

            return absoluteAction;
        }
    }
}

Información de apoyo:

Charlino
fuente
3
También agregaría parámetros opcionales para esta solución. Esto debería cubrir todos los casos.
Eugeniu Torica
¡Muy agradable! Utilicé este código pero hice el único argumento relativeUrl para que la persona que llama pueda crearlo usando el método de Url que le guste (valores de enrutador, etc.), y su método puede ser responsable de hacerlo relativo. Entonces el mío es: AbsoluteUrl (esta urlHelper url, string relativeUrl).
Rob Kent el
26
<%= Url.Action("About", "Home", null, Request.Url.Scheme) %>
<%= Url.RouteUrl("Default", new { Action = "About" }, Request.Url.Scheme) %>
Ryan Sampson
fuente
21

Usando la respuesta de @Charlino como guía, se me ocurrió esto.

La documentación ASP.NET MVC para UrlHelper muestra que Url.Action devolverá una Url totalmente calificada si se pasa un nombre de host y un protocolo. Creé estos ayudantes para forzar el nombre de host y el protocolo que se proporcionarán. Las múltiples sobrecargas reflejan las sobrecargas de Url.Action:

using System.Web.Routing;

namespace System.Web.Mvc {
    public static class HtmlExtensions {

        public static string AbsoluteAction(this UrlHelper url, string actionName) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, (RouteValueDictionary)null, 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            object routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, new RouteValueDictionary(routeValues), 
                              requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            RouteValueDictionary routeValues) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, null, routeValues, requestUrl.Scheme, null);
        }

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, (RouteValueDictionary)null, 
                              requestUrl.Scheme, null);
        }

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

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

        public static string AbsoluteAction(this UrlHelper url, string actionName, 
                                            string controllerName, object routeValues, 
                                            string protocol) {
            Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
            return url.Action(actionName, controllerName, 
                              new RouteValueDictionary(routeValues), protocol, null);
        }

    }
}
Raleigh Buckner
fuente
44
Gracias por el código, me ayudó mucho, pero hay un problema con esta solución que generalmente aparece durante el desarrollo. Si el sitio está alojado en un puerto específico, la información del puerto se incluye en requestUrl.Authority , como localhost: 4423 . Por alguna razón, el método Action agrega el puerto nuevamente. Entonces, esto es un error dentro del Método de acción o no se supone que debe proporcionar el puerto aquí. Pero, ¿cuál de las propiedades disponibles en la solicitud es la correcta (DnsSafeHost o Host)? Bueno, la solución es bastante simple: simplemente proporcione nulo y el método de acción completará el valor correcto.
ntziolis
He actualizado la respuesta para incorporar la sugerencia de @ ntziolis.
Andrew Arnott
3

No estoy seguro de si hay una forma integrada de hacerlo, pero podría implementar su propio método HtmlHelper.

Algo como lo siguiente

namespace System.Web.Mvc
{
    public static class HtmlExtensions
    {
        public static string AbsoluteAction(this HtmlHelper html, string actionUrl)
        {
            Uri requestUrl = html.ViewContext.HttpContext.Request.Url;

            string absoluteAction = string.Format("{0}://{1}{2}",
                                                  requestUrl.Scheme,
                                                  requestUrl.Authority,
                                                  actionUrl);

            return absoluteAction;
        }
    }
}

Entonces llámalo así

<%= Html.AbsoluteAction(Url.Action("Dashboard", "Account"))%> »

HTHs, Charles

Charlino
fuente
2

La respuesta completa con argumentos sería:

var url = Url.Action("ActionName", "ControllerName", new { id = "arg_value" }, Request.Url.Scheme);

y eso producirá una url absoluta

Dashrath
fuente
1

Mismo resultado pero un poco más limpio (sin concatenación / formateo de cadenas):

public static Uri GetBaseUrl(this UrlHelper url)
{
    Uri contextUri = new Uri(url.RequestContext.HttpContext.Request.Url, url.RequestContext.HttpContext.Request.RawUrl);
    UriBuilder realmUri = new UriBuilder(contextUri) { Path = url.RequestContext.HttpContext.Request.ApplicationPath, Query = null, Fragment = null };
    return realmUri.Uri;
}

public static string ActionAbsolute(this UrlHelper url, string actionName, string controllerName)
{
    return new Uri(GetBaseUrl(url), url.Action(actionName, controllerName)).AbsoluteUri;
}
veggerby
fuente
0

Tal vez esto (?):

<%= 
  Request.Url.GetLeftPart(UriPartial.Authority) + 
  Url.Action("Action1", "Controller2", new {param1="bla", param2="blabla" })
%>
tytusse
fuente
0

env: dotnet core versión 1.0.4

Url.Action("Join",null, null,Context.Request.IsHttps?"https":"http");
Guhyeon
fuente