Comment trouver l'URL absolue d'une action dans ASP.NET MVC?

239

Je dois faire quelque chose comme ça:

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

J'utilise la version bêta de MVC, mais je ne sais pas comment obtenir l'url absolue d'une action. Je voudrais faire quelque chose comme ça:

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

Existe-t-il une méthode d'assistance ou de page pour cela?

Mike Comstock
la source

Réponses:

480

Cliquez ici pour plus d'informations, mais essentiellement, il n'y a pas besoin de méthodes d'extension. Il est déjà intégré, mais pas de manière très intuitive.

Url.Action("Action", null, null, Request.Url.Scheme);
Adam Boddington
la source
6
Intéressant, donc si vous spécifiez le protocole, l'URL est absolue
Casebash
24
Cette réponse est la meilleure, de cette façon, Resharper peut toujours valider que l'action et le contrôleur existent. Je suggérerais l'utilisation de Request.Url.Scheme au lieu du http, de cette façon, http et https sont tous deux pris en charge.
Pbirkoff
2
@Pbirkoff, convenez que c'est la meilleure réponse mais vous aimerez peut-être savoir que vous pouvez annoter vos propres méthodes pour que ReSharper sache que les paramètres représentent des actions / contrôleurs. De cette façon, R # peut toujours valider les chaînes que vous fournissez, comme il le fait si bien.
Drew Noakes
3
Une petite amélioration pourrait être de remplacer "http" par Request.Url.Schemepour que si vous utilisez HTTPS, l'url générée utilisera également HTTPS.
Erik Schierboom
1
Cela fonctionne Html.ActionLinkaussi (toutes les méthodes qui prennent un protocole, les 2 dernières dans MVC 4 par exemple)
Chris
74

Étendre 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;
        }
    }
}

Alors appelle ça comme ça

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

MODIFIER - ANNOTATIONS PLUS RÉDUITES

Le commentaire le plus voté sur la réponse acceptée est This answer is the better one, this way Resharper can still validate that the Action and Controller exists.donc voici un exemple comment vous pourriez obtenir le même comportement.

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

Informations complémentaires:

Charlino
la source
3
J'ajouterais également des paramètres facultatifs pour cette solution. Cela devrait couvrir tous les cas.
Eugeniu Torica,
Très agréable! J'ai utilisé ce code mais j'ai fait le seul argument relativeUrl pour que l'appelant puisse le créer en utilisant la méthode Url qu'il souhaite (valeurs du routeur, etc.), et votre méthode peut simplement être responsable de la rendre relative. Le mien est donc: AbsoluteUrl (cette URL UrlHelper, chaîne relativeUrl).
Rob Kent
26
<%= Url.Action("About", "Home", null, Request.Url.Scheme) %>
<%= Url.RouteUrl("Default", new { Action = "About" }, Request.Url.Scheme) %>
Ryan Sampson
la source
21

En utilisant la réponse de @Charlino comme guide, j'ai trouvé ceci.

La documentation ASP.NET MVC pour UrlHelper montre que Url.Action renverra une URL complète si un nom d'hôte et un protocole sont transmis. J'ai créé ces assistants pour forcer le nom d'hôte et le protocole à être fournis. Les multiples surcharges reflètent les surcharges pour Url.

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
la source
4
Thx pour le code m'a beaucoup aidé, mais il y a un problème avec cette solution qui survient généralement pendant le développement. Si le site est hébergé sur un port spécifique, les informations sur le port sont incluses dans requestUrl.Authority , comme localhost: 4423 . Pour une raison quelconque, la méthode Action ajoute à nouveau le port. Donc, soit c'est un bogue dans la méthode d'action, soit vous n'êtes pas censé fournir le port ici. Mais laquelle des propriétés disponibles sur la demande est la bonne (DnsSafeHost ou Host)? Eh bien, la solution est plutôt simple: il suffit de fournir null et la méthode Action remplira la bonne valeur.
ntziolis
J'ai mis à jour la réponse pour incorporer la suggestion de @ ntziolis.
Andrew Arnott
3

Je ne sais pas s'il existe une méthode intégrée pour le faire, mais vous pouvez rouler votre propre méthode HtmlHelper.

Quelque chose comme ce qui suit

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

Alors appelle ça comme ça

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

HTHs, Charles

Charlino
la source
2

La réponse complète avec arguments serait:

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

et cela produira une URL absolue

Dashrath
la source
1

Même résultat mais un peu plus propre (pas de concaténation / formatage de chaîne):

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
la source
0

Peut être ça (?):

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

env: dotnet core version 1.0.4

Url.Action("Join",null, null,Context.Request.IsHttps?"https":"http");
guhyeon
la source