Chiama UrlHelper nei modelli in ASP.NET MVC


159

Devo generare alcuni URL in un modello in ASP.NET MVC. Vorrei chiamare qualcosa come UrlHelper.Action () che utilizza i percorsi per generare l'URL. Non mi dispiace riempire i soliti spazi vuoti, come il nome host, lo schema e così via.

C'è un metodo che posso chiamare per questo? C'è un modo per costruire un UrlHelper?


1
Ci stavo pensando da solo, ma tieni presente che Url.Action genererà un URL relativo. Assicurati che sia quello che vuoi.
Fiume Vivian,

Risposte:


277

Suggerimento utile, in qualsiasi applicazione ASP.NET, è possibile ottenere un riferimento all'attuale HttpContext

HttpContext.Current

che è derivato da System.Web. Pertanto, quanto segue funzionerà ovunque in un'applicazione ASP.NET MVC:

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

Esempio:

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

Chiamare la Linkproprietà su un oggetto MyModel creato restituirà l'URL valido per visualizzare il modello in base al routing in Global.asax


Sei sicuro che esista un HttpContext.Current.Request.RequestContext? HttpContext.Current.Request sembra non avere un RequestContext.
pupeno

1
È strano. Ho appena testato questa soluzione e funziona perfettamente. Sto eseguendo ASP.NET MVC 2 Preview 2, ma penso che funzioni su tutte le versioni. Non sono sicuro del perché non funzioni per te. Stai creando la classe al di fuori di un progetto MVC? Assicurati anche che ci siano usingper entrambi System.WebeSystem.Web.Mvc
Omar,

Sono su un progetto ASP.NET MVC 1, ho pensato di perdere gli utilizzi ma li ho entrambi.
pupeno

Non sono davvero sicuro del motivo per cui non sta mostrando. Se qualcun altro potesse confermare che questo non esiste in ASP.NET MVC 1 sarebbe fantastico. Ho solo una macchina con VS2010 e MVC 2 installati. Se sei interessato, MVC RC 2 haacked.com/archive/2009/12/16/aspnetmvc-2-rc.aspx
Omar

6
Si noti che Request.RequestContex è supportato in .NET4 +
h - n

64

Mi piace la risposta di Omar, ma non funziona per me. Solo per la cronaca questa è la soluzione che sto usando ora:

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

Contiene l'URL del mio sito. Lì l'ho rimosso.
pupeno

4
Considerando che la classe UrlHelper si basa sul contesto della richiesta (e sul contesto HTTP), la costruzione manuale di tali oggetti di contesto potrebbe produrre risultati imprevisti. Se HttpContext.Current è null e si utilizza questo approccio, procederei con cautela.
Sean,

4
Fai attenzione a questa risposta: il RequestContext fittizio si traduce in un UrlHelper che restituisce sempre una stringa vuota.
gknicker,

47

Un UrlHelper può essere costruito all'interno di un'azione del controller con il seguente:

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

Al di fuori di un controller, è possibile creare un UrlHelper creando un RequestContext da RouteTable.Routes RouteData.

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

(Basato sulla risposta di Brian, con l'aggiunta di una correzione minore del codice.)


2
Ma non ho un controller nel modello.
Pupeno

Okay, mi scuso, non ero sicuro di dove fosse eseguito il codice. Fammi dare un'occhiata ...
Nathan Taylor

2
Non è necessario creare un nuovo contesto di richiesta:var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
bradlis7,

Nice @ bradlis7. Quello è MVC 5?
Nathan Taylor,

1
Non funziona, perché this.ControllerContext.RequestContextè un HttpRequestContexte costruttore di si UrlHelperaspetta un RequestContext. Entrambe le classi non sono correlate.
Florian Winter

8

Sì, puoi istanziarlo. Puoi fare qualcosa del tipo:

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

RouteTable.Routesè una proprietà statica, quindi dovresti essere OK lì; per ottenere un HttpContextBaseriferimento, HttpContextWrapperaccetta un riferimento HttpContexte lo HttpContextconsegna.


Questo non funzionerà, anche se è molto vicino. Vedi la mia risposta qui sotto.
Nathan Taylor

3

Dopo aver provato tutte le altre risposte, ho finito con

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

Gli odiatori odieranno ¯ \ _ (ツ) _ / ¯


0

Stavo cercando di fare qualcosa di simile all'interno di una pagina (al di fuori di un controller).

UrlHelper non mi ha permesso di costruirlo con la stessa facilità con cui risponde Pablos, ma poi ho ricordato un vecchio trucco per fare efficacemente la stessa cosa:

string ResolveUrl(string pathWithTilde)

-30

Penso che quello che stai cercando sia questo:

Url.Action("ActionName", "ControllerName");
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.