web-dev-qa-db-fra.com

Obtention de l'URL complète de l'action dans ASP.NET MVC

Existe-t-il un moyen intégré d’obtenir l’URL complète d’une action?

Je cherche quelque chose comme GetFullUrl("Action", "Controller") qui puisse renvoyer quelque chose comme http://www.fred.com/Controller/Action.

La raison pour laquelle je le cherche est d'éviter le codage en dur des URL dans les courriels automatisés générés, de manière à ce que les URL puissent toujours être générées par rapport à l'emplacement actuel du site.

360
Alan Spark

Il existe une surcharge d'URL.Action qui prend comme argument votre protocole souhaité (par exemple, http, https) - si vous le spécifiez, vous obtenez une adresse URL complète.

Voici un exemple qui utilise le protocole de la demande en cours dans une méthode d'action:

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

HtmlHelper (@Html) a également une surcharge de la méthode ActionLink que vous pouvez utiliser dans rasoir pour créer un élément d'ancrage, mais nécessite également les paramètres hostName et fragment. Je voudrais donc simplement choisir d'utiliser à nouveau @ Url.Action:

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

Comme Paddy l’a mentionné: si vous utilisez une surcharge de UrlHelper.Action() qui spécifie explicitement le protocole à utiliser, l’URL générée sera absolue et pleinement qualifiée au lieu d’être relative.

J'ai écrit un article de blog intitulé Comment créer des URL d'action absolues à l'aide de la classe UrlHelper dans lequel je suggère d'écrire une méthode d'extension personnalisée pour des raisons de lisibilité:

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

Vous pouvez ensuite simplement l'utiliser comme ça à votre avis:

@Url.AbsoluteAction("Action", "Controller")
132
Marius Schulz

C'est ce que vous devez faire.

@Url.Action(action,controller, null, Request.Url.Scheme)
1
Salman Zahid

Cette question est spécifique à ASP .NET. Cependant, je suis sûr que certains d'entre vous bénéficieront de javascript sans système, qui est bénéfique dans de nombreuses situations.

PDATE: Le moyen de se faire former une URL en dehors de la page elle-même est bien décrit dans les réponses ci-dessus.

Ou vous pouvez faire un oneliner comme suit:

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

de filtre ou:

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

Cependant, assez souvent, il est nécessaire d'obtenir l'URL de la page en cours. Pour les cas, utiliser Html.Action et mettre le nom et le contrôleur de la page dans laquelle vous vous trouvez me semble difficile. Dans ce cas, ma préférence est d'utiliser JavaScript. Ceci est particulièrement utile dans les systèmes qui sont à moitié réécrits à moitié par MVT, à savoir moitié-formes-Web, moitié-vb-script, Dieu sait quoi - et pour obtenir l'URL de la page actuelle, il est nécessaire d'utiliser une méthode différente à chaque fois.

Une façon d'utiliser JavaScript pour obtenir l'URL est window.location.href une autre - document.URL

0
Matas Vaitkevicius

C'est peut-être juste que je suis vraiment très difficile, mais j'aime bien ne définir qu'une seule fois les constantes. Si vous utilisez l'une des approches définies ci-dessus, votre constante d'action sera définie plusieurs fois.

Pour éviter cela, vous pouvez procéder comme suit:

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

Créez ensuite vos contrôleurs, par exemple le 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);
    }

Ensuite, utilisez-le comme ceci:

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

Et à partir de votre .cshtml (ou de n'importe quel code)

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

C'est certainement beaucoup plus de travail, mais je reste tranquille sachant que la validation du temps de compilation est de mon côté.

0
Jorge Aguirre

J'avais un problème avec cela, mon serveur fonctionnait derrière un équilibreur de charge. L'équilibreur de charge mettait fin à la connexion SSL/TLS. Il a ensuite transmis la demande aux serveurs Web à l'aide de http.

À l'aide de la méthode Url.Action () avec Request.Url.Schema, il a continué à créer une URL http, dans mon cas, pour créer un lien dans un courrier électronique automatisé (ce que mon PenTester n'a pas aimé).

J'ai peut-être un peu triché, mais c'est exactement ce dont j'avais besoin pour forcer une URL https:

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

En fait, j'utilise un AppSetting web.config pour pouvoir utiliser http lors du débogage local, mais tous les environnements de test et de production utilisent la transformation pour définir la valeur https.

0
Matt D