2010-01-05 6 views
325

Gibt es eine integrierte Möglichkeit, die vollständige URL einer Aktion abzurufen?Vollständige URL der Aktion in ASP.NET MVC abrufen

Ich bin auf der Suche nach etwas wie GetFullUrl("Action", "Controller"), die etwas wie http://www.fred.com/Controller/Action zurückgeben würde.

Der Grund, den ich suche, ist, harte URLs in automatisierten E-Mails zu vermeiden, die erzeugt werden, damit die URLs immer relativ zum gegenwärtigen Standort der Site erzeugt werden können.

+0

Siehe auch: http://StackOverflow.com/q/434604 – Andrew

Antwort

503

Es gibt eine Überladung von Url.Action, die das gewünschte Protokoll (z. B. http, https) als Argument verwendet. Wenn Sie dies angeben, erhalten Sie eine vollständig qualifizierte URL.

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

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

Htmlhelper (@Html) hat auch eine Überlastung der Action Methode, die Sie in Rasierer verwenden können, einen Anker zu schaffen Element, aber es erfordert auch die Parameter HostName und Fragment. Also würde ich nur entscheiden @ Url.Action wieder zu benutzen:

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

Keine Sorge - Sie sollten denken, dass es noch eine bessere Möglichkeit geben sollte, dies zu tun, aber hey ... – Paddy

+0

Beim lokalen Testen mit Azure-Emulator dies gibt Port 82 anstelle des korrekten Ports 81 zurück. Nicht sicher, ob dies gut funktioniert, wenn es veröffentlicht wird oder nicht. Die Antwort von Marius Schulz funktioniert perfekt. – angularsen

+1

Die richtige URL ist 'https: // 127.0.0.1/Home/Index', erzeugt aber' https: //127.0.0.1: 444/Home/Index'. Es muss keinen Port haben. Ich verwende den Azure-Emulator. Bitte helfen Sie. – fiberOptics

123

Als Paddy erwähnt: , wenn Sie eine Überlastung von UrlHelper.Action() verwenden, das das Protokoll explizit angibt, zu verwenden, wird die generierte URL absolut sein und voll qualifiziert anstatt relativ zu sein.

Ich schrieb einen Blog-Post genannt How to build absolute action URLs using the UrlHelper class, in dem ich vorschlagen, eine benutzerdefinierte Erweiterung Verfahren aus Gründen der Lesbarkeit zu schreiben:

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

Anschließend können Sie es einfach so in Ihrer Ansicht verwenden:

@Url.AbsoluteAction("Action", "Controller") 
+0

Wünschen Sie mehr upvotes bekam, das ist eigentlich ein Kinderspiel, die IMO im Rahmen – Roger

+7

Das einzige, was sein sollte ich hinzufügen würde (oder modifizieren) ist die wörtliche „http“ mit HttpContext.Current.Request.Url.Scheme zu ersetzen . Dadurch kann https bei Bedarf verwendet werden. – Jay

+0

@Jay, danke für deinen Vorschlag, ich habe mein Codebeispiel aktualisiert. Ich habe das gleiche Feedback zu meinem Blogpost erhalten ;-). –

0

Diese Frage ist spezifisch für ASP.NET aber ich bin sicher, dass einige von Ihnen System-agnostic Javascript profitieren, die in vielen Situationen vorteilhaft ist.

UPDATE: Die Möglichkeit, URL außerhalb der Seite selbst gebildet wird in den Antworten oben beschrieben.

Oder Sie könnten einen oneliner tun wie folgt vor:

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

aus dem Filter oder:

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

jedoch ziemlich oft muss man die URL der aktuellen Seite bekommen, für die Fälle mit Html.Action und Den Namen und den Controller der Seite, in der du dich befindest, zu setzen, fühlt sich peinlich an. In solchen Fällen bevorzuge ich stattdessen JavaScript. Dies ist besonders gut in Systemen, die halb umgeschrieben werden MVT halb Web-Formulare halb vb-Skript halb Gott weiß was - und um URL der aktuellen Seite zu erhalten, muss man jedes Mal eine andere Methode verwenden.

Eine Möglichkeit ist, JavaScript zu verwenden URL zu erhalten, ist eine andere window.location.href - einmal document.URL

+1

Dies würde nur funktionieren, um die URL der aktuellen Seite darzustellen. Das OP möchte die Namen eines .Net-Controllers und Views weitergeben, um die URL zu generieren, um auf diese Seite zu gelangen. – Matthew

0

Das bin ich wirklich sein nur sein kann, wirklich pingelig, aber Ich mag nur Konstanten definieren. Wenn Sie einen der oben definierten Ansätze verwenden, wird Ihre Aktionskonstante mehrfach 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 Ihre Controller erstellen, sagen wir zum Beispiel das 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 ist es genau wie verwenden:

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

und von Ihrem .cshtml (oder beliebigen Code)

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

Dies ist auf jeden Fall sehr viel mehr Arbeit, aber ich ruhig schlafen Validierung zu wissen, kompiliert Zeit ist auf meiner Seite.

1

Dies ist, was Sie tun müssen.

+2

Dies ist das gleiche wie die angenommene Antwort. Antworten werden am besten veröffentlicht, wenn etwas Neues eingeführt wird. – Doomsknight

0

Ich hatte ein Problem mit diesem, mein Server lief hinter einem Load Balancer. Der Load Balancer hat die SSL/TLS-Verbindung beendet. Anschließend übermittelte es die Anfrage über http an die Webserver.

Mithilfe der Url.Action() -Methode mit Request.Url.Schema, erstellt es eine HTTP-URL, in meinem Fall, um einen Link in einer automatisierten E-Mail zu erstellen (was mein PenTester nicht mochte).

ich ein wenig betrogen haben, aber es ist genau das, was ich brauchte eine HTTPS-URL zu erzwingen:

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

ich eigentlich eine web.config verwenden appSetting so kann ich http verwenden, wenn sie lokal Debuggen, aber alle Test- und Produktumgebungen verwenden eine Umwandlung, um den https-Wert festzulegen.