Come trovo l'URL assoluto di un'azione in ASP.NET MVC?


239

Devo fare qualcosa del genere:

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

Sto usando la versione Beta di MVC, ma non riesco a capire come ottenere l'URL assoluto di un'azione. Mi piacerebbe fare qualcosa del genere:

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

C'è un aiuto o un metodo Page per questo?

Risposte:


480

Fare clic qui per ulteriori informazioni, ma in sostanza non sono necessari metodi di estensione. È già cotto, ma non in modo molto intuitivo.

Url.Action("Action", null, null, Request.Url.Scheme);

6
Interessante, quindi se si specifica il protocollo, l'URL è assoluto
Casebash

24
Questa risposta è la migliore, in questo modo Resharper può ancora confermare l'esistenza dell'azione e del controller. Suggerirei l'uso di Request.Url.Scheme invece di http, in questo modo sono supportati sia http che https.
Pbirkoff,

2
@Pbirkoff, accetta che questa è la risposta migliore, ma potresti voler sapere che puoi annotare i tuoi metodi affinché ReSharper sappia che i parametri rappresentano azioni / controller. In questo modo R # può ancora convalidare le stringhe fornite, così come fa bene.
Drew Noakes,

3
Un piccolo miglioramento potrebbe essere quella di sostituire "http" , con Request.Url.Schemein modo che se si utilizza HTTPS l'URL generato anche utilizzare HTTPS.
Erik Schierboom,

1
Funziona anche per Html.ActionLink(uno qualsiasi dei metodi che accettano un protocollo, gli ultimi 2 in MVC 4 per esempio)
Chris

74

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

Quindi chiamalo così

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

MODIFICA - ANNOTAZIONI RESHARPER

Il commento più votato sulla risposta accettata è This answer is the better one, this way Resharper can still validate that the Action and Controller exists.Quindi ecco un esempio di come potresti ottenere lo stesso comportamento.

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

Informazioni di supporto:


3
Aggiungerei anche parametri opzionali per questa soluzione. Questo dovrebbe coprire tutti i casi.
Eugeniu Torica,

Molto bella! Ho usato questo codice ma ho creato l'unico argomento relativeUrl in modo che il chiamante possa crearlo usando qualunque metodo Url preferisca (valori del router ecc.) E il tuo metodo può essere solo responsabile di renderlo relativo. Quindi il mio è: AbsoluteUrl (questo URL UrlHelper, string relativeUrl).
Rob Kent,

26
<%= Url.Action("About", "Home", null, Request.Url.Scheme) %>
<%= Url.RouteUrl("Default", new { Action = "About" }, Request.Url.Scheme) %>

21

Usando la risposta di @Charlino come guida, ho pensato a questo.

La documentazione ASP.NET MVC per UrlHelper mostra che Url.Action restituirà un Url completo se vengono passati un nome host e un protocollo. Ho creato questi helper per forzare la fornitura del nome host e del protocollo. I sovraccarichi multipli rispecchiano i sovraccarichi per 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);
        }

    }
}

4
Grazie per il codice, mi ha aiutato molto, ma c'è un problema con questa soluzione che di solito emerge durante lo sviluppo. Se il sito è ospitato su una porta specifica, le informazioni sulla porta sono incluse in requestUrl.Authority , come localhost: 4423 . Per qualche motivo il metodo Action aggiunge nuovamente la porta. Quindi o questo è un bug all'interno del metodo di azione o non è necessario fornire la porta qui. Ma quale delle Proprietà disponibili sulla richiesta è quella giusta (DnsSafeHost o Host)? Bene, la soluzione è piuttosto semplice: basta fornire null e il metodo Action riempirà il giusto valore.
ntziolis,

Ho aggiornato la risposta per incorporare il suggerimento di @ ntziolis.
Andrew Arnott,

3

Non sono sicuro che esista un modo integrato per farlo, ma potresti usare il tuo metodo HtmlHelper.

Qualcosa di simile al seguente

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

Quindi chiamalo così

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

HTH, Charles


2

La risposta completa con argomenti sarebbe:

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

e questo produrrà un url assoluto


1

Stesso risultato ma un po 'più pulito (nessuna concatenazione / formattazione di stringhe):

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

0

Forse questo (?):

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

0

env: dotnet core versione 1.0.4

Url.Action("Join",null, null,Context.Request.IsHttps?"https":"http");
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.