wake-up-neo.com

Vollständige URL der Aktion in ASP.NET MVC abrufen

Gibt es eine integrierte Möglichkeit, die vollständige URL einer Aktion abzurufen?

Ich suche nach etwas wie GetFullUrl("Action", "Controller"), das etwas wie http://www.fred.com/Controller/Action Zurückgeben würde.

Der Grund, warum ich das suche, besteht darin, das Hardcodieren von URLs in automatisierten E-Mails zu vermeiden, damit die URLs immer relativ zum aktuellen Standort der Site generiert werden können.

360
Alan Spark

Es gibt eine Überladung von Url.Action, die Ihr gewünschtes Protokoll (z. B. http, https) als Argument verwendet. Wenn Sie dies angeben, erhalten Sie eine vollqualifizierte URL.

Hier ist ein Beispiel, das das Protokoll der aktuellen Anforderung in einer Aktionsmethode verwendet:

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

HtmlHelper (@Html) enthält auch eine Überladung der ActionLink-Methode, mit der Sie in razor ein Ankerelement erstellen können, erfordert jedoch auch die Parameter hostName und fragment. Also würde ich einfach wieder @ Url.Action verwenden:

<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

Wie Paddy sagte: Wenn Sie eine Überladung von UrlHelper.Action() verwenden, die das zu verwendende Protokoll explizit angibt, ist die generierte URL absolut und vollständig qualifiziert, anstatt relativ zu sein.

Ich habe einen Blog-Beitrag mit dem Namen Erstellen absoluter Aktions-URLs mit der UrlHelper-Klasse geschrieben, in dem ich aus Gründen der Lesbarkeit eine benutzerdefinierte Erweiterungsmethode vorschlage:

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

Sie können es dann aus Ihrer Sicht einfach so verwenden:

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

Das musst du tun.

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

Diese Frage ist spezifisch für ASP .NET. Ich bin jedoch sicher, dass einige von Ihnen von systemunabhängigem Javascript profitieren werden, was in vielen Situationen von Vorteil ist.

PDATE: Die Art und Weise, wie URLs außerhalb der Seite selbst gebildet werden, ist in den obigen Antworten gut beschrieben.

Oder Sie könnten einen Oneliner wie folgt machen:

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

aus Filter oder:

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

Allerdings muss man ziemlich oft die URL der aktuellen Seite abrufen. In solchen Fällen fühlt es sich unangenehm an, wenn man Html.Action Verwendet und den Namen und den Controller der Seite, in der man sich befindet, in mich eingibt. Ich bevorzuge in solchen Fällen die Verwendung von JavaScript. Dies ist besonders gut in Systemen, die zur Hälfte neu geschrieben wurden. MVT, zur Hälfte Webformulare, zur Hälfte VBSkript, zur Hälfte Gott weiß, was - und um die URL der aktuellen Seite zu erhalten, muss jedes Mal eine andere Methode angewendet werden.

Eine Möglichkeit, JavaScript zum Abrufen der URL zu verwenden, ist window.location.href, Eine andere - document.URL.

0

Das mag sein, dass ich wirklich sehr, sehr wählerisch bin, aber ich definiere Konstanten nur einmal. Wenn Sie einen der oben definierten Ansätze verwenden, wird Ihre Aktionskonstante mehrmals definiert.

Um dies zu vermeiden, können Sie Folgendes tun:

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

Dann erstellen Sie Ihre Controller, zum Beispiel den 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);
    }

Dann benutze es einfach so:

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

Und aus Ihrer .cshtml (oder einem beliebigen Code)

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

Dies ist definitiv viel mehr Arbeit, aber ich weiß, dass die Validierung der Kompilierungszeit auf meiner Seite liegt.

0
Jorge Aguirre

Ich hatte ein Problem damit, mein Server lief hinter einem Load Balancer. Der Load Balancer hat die SSL/TLS-Verbindung beendet. Anschließend wurde die Anforderung über http an die Webserver weitergeleitet.

Bei Verwendung der Url.Action () -Methode mit Request.Url.Schema wurde eine http-URL erstellt, um in meinem Fall einen Link in einer automatisierten E-Mail zu erstellen (was meinem PenTester nicht gefallen hat).

Ich habe vielleicht ein bisschen geschummelt, aber genau das brauchte ich, um eine https-URL zu erzwingen:

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

Eigentlich verwende ich eine web.config AppSetting, damit ich beim lokalen Debuggen http verwenden kann, aber alle Test- und Produktumgebungen verwenden die Transformation, um den https-Wert festzulegen.

0
Matt D