Rufen Sie UrlHelper in Modellen in ASP.NET MVC auf

159

Ich muss einige URLs in einem Modell in ASP.NET MVC generieren. Ich möchte so etwas wie UrlHelper.Action () aufrufen, das die Routen zum Generieren der URL verwendet. Es macht mir nichts aus, die üblichen Lücken wie den Hostnamen, das Schema usw. zu füllen.

Gibt es eine Methode, die ich dafür aufrufen kann? Gibt es eine Möglichkeit, einen UrlHelper zu erstellen?

pupeno
quelle
1
Ich habe selbst darüber nachgedacht, aber beachten Sie, dass Url.Action eine relative URL generiert. Stellen Sie sicher, dass Sie das wollen.
Vivian River

Antworten:

277

Hilfreicher Tipp: In jeder ASP.NET-Anwendung können Sie eine Referenz des aktuellen HttpContext abrufen

HttpContext.Current

welches von System.Web abgeleitet ist. Daher funktioniert Folgendes in einer ASP.NET MVC-Anwendung überall:

UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
url.Action("ContactUs"); // Will output the proper link according to routing info

Beispiel:

public class MyModel
{
    public int ID { get; private set; }
    public string Link
    {
        get
        {
            UrlHelper url = new UrlHelper(HttpContext.Current.Request.RequestContext);
            return url.Action("ViewAction", "MyModelController", new { id = this.ID });
        }
    }

    public MyModel(int id)
    {
        this.ID = id;
    }
}

LinkWenn Sie die Eigenschaft für ein erstelltes MyModel-Objekt aufrufen, wird die gültige URL zurückgegeben, um das Modell basierend auf dem Routing in Global.asax anzuzeigen

Omar
quelle
Sind Sie sicher, dass es einen HttpContext.Current.Request.RequestContext gibt? HttpContext.Current.Request scheint keinen RequestContext zu haben.
Pupeno
1
Das ist seltsam. Ich habe diese Lösung gerade getestet und sie funktioniert perfekt. Ich verwende ASP.NET MVC 2 Preview 2, aber ich denke, dass dies in allen Versionen funktioniert. Ich bin mir nicht sicher, warum es bei Ihnen nicht funktioniert. Erstellen Sie die Klasse außerhalb eines MVC-Projekts? Stellen Sie auch sicher, dass es usingfür beide System.WebundSystem.Web.Mvc
Omar
Ich bin in einem ASP.NET MVC 1-Projekt. Ich habe über fehlende Verwendungen nachgedacht, aber ich habe beide.
Pupeno
Ich bin mir nicht sicher, warum es nicht angezeigt wird. Wenn jemand anderes bestätigen könnte, dass dies in ASP.NET MVC 1 nicht vorhanden ist, wäre das großartig. Ich habe nur eine Maschine mit VS2010 und MVC 2 installiert. Wenn Sie interessiert sind, MVC RC 2 haacked.com/archive/2009/12/16/aspnetmvc-2-rc.aspx
Omar
6
Beachten Sie, dass Request.RequestContex in .NET4 +
h - n
64

Ich mag Omars Antwort, aber das funktioniert bei mir nicht. Nur zur Veranschaulichung: Dies ist die Lösung, die ich jetzt verwende:

var httpContext = HttpContext.Current;

if (httpContext == null) {
  var request = new HttpRequest("/", "http://example.com", "");
  var response = new HttpResponse(new StringWriter());
  httpContext = new HttpContext(request, response);
}

var httpContextBase = new HttpContextWrapper(httpContext);
var routeData = new RouteData();
var requestContext = new RequestContext(httpContextBase, routeData);

return new UrlHelper(requestContext);
pupeno
quelle
Es enthält die URL meiner Website. Dort habe ich es entfernt.
Pupeno
4
Wenn man bedenkt, dass die UrlHelper-Klasse auf dem Anforderungskontext (und dem HTTP-Kontext) basiert, kann das manuelle Erstellen dieser Kontextobjekte zu unerwarteten Ergebnissen führen. Wenn HttpContext.Current null ist und Sie diesen Ansatz verwenden, würde ich mit Vorsicht vorgehen.
Sean
4
Beachten Sie diese Antwort - der duplizierte RequestContext führt zu einem UrlHelper, der immer eine leere Zeichenfolge zurückgibt.
Gknicker
47

Ein UrlHelper kann aus einer Controller-Aktion heraus wie folgt erstellt werden:

 var url = new UrlHelper(this.ControllerContext.RequestContext);
 url.Action(...);

Außerhalb eines Controllers kann ein UrlHelper erstellt werden, indem ein RequestContext aus RouteTable.Routes RouteData erstellt wird.

HttpContextWrapper httpContextWrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContextWrapper, RouteTable.Routes.GetRouteData(httpContextWrapper)));

(Basierend auf Brians Antwort, mit einer geringfügigen Codekorrektur.)

Nathan Taylor
quelle
2
Aber ich habe keinen Controller im Modell.
Pupeno
Okay, ich entschuldige mich, ich war mir nicht sicher, wo genau der Code ausgeführt wurde. Lassen Sie mich einen Blick darauf werfen ...
Nathan Taylor
2
Es ist nicht erforderlich, einen neuen Anforderungskontext zu erstellen:var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
bradlis7
Nice @ bradlis7. Ist das MVC 5?
Nathan Taylor
1
Funktioniert nicht, weil this.ControllerContext.RequestContexta HttpRequestContextund Konstruktor von UrlHelpererwartet a RequestContext. Beide Klassen haben nichts miteinander zu tun.
Florian Winter
8

Ja, Sie können es instanziieren. Sie können so etwas tun wie:

var ctx = new HttpContextWrapper(HttpContext.Current);
UrlHelper helper = new UrlHelper(
   new RequestContext(ctx,
   RouteTable.Routes.GetRouteData(ctx));

RouteTable.Routesist eine statische Eigenschaft, daher sollten Sie dort in Ordnung sein. um eine HttpContextBaseReferenz zu erhalten, HttpContextWrappernimmt eine Referenz auf HttpContextund HttpContextliefert diese.

Brian Mains
quelle
Dies wird nicht funktionieren, obwohl es sehr eng ist. Siehe meine Antwort unten.
Nathan Taylor
3

Nachdem ich alle anderen Antworten ausprobiert hatte, endete ich mit

$"/api/Things/Action/{id}"

Hasser werden ¯ \ _ (ツ) _ / ¯ hassen

Florian Winter
quelle
0

Ich habe versucht, innerhalb einer Seite (außerhalb eines Controllers) etwas Ähnliches zu tun.

UrlHelper erlaubte mir nicht, es so einfach zu konstruieren wie Pablos Antwort, aber dann erinnerte ich mich an einen alten Trick, um das Gleiche effektiv zu tun:

string ResolveUrl(string pathWithTilde)
vGHazard
quelle
-30

Ich denke, was Sie suchen, ist Folgendes:

Url.Action("ActionName", "ControllerName");
user246874
quelle