2010-01-09 8 views
148

Potrzebuję wygenerować niektóre adresy URL w modelu w ASP.NET MVC. Chciałbym nazywać coś w rodzaju UrlHelper.Action(), który używa tras do generowania adresu URL. Nie mam nic przeciwko wypełnianiu zwykłych spacji, takich jak nazwa hosta, schemat i tak dalej.Call UrlHelper w modelach w ASP.NET MVC

Czy jest jakaś metoda, którą mogę wzywać do tego? Czy istnieje sposób na zbudowanie UrlHelper?

+1

Myślałam o tym sam, ale należy pamiętać, że Url.Action wygeneruje względny adres URL. Upewnij się, że tego właśnie chcesz. –

Odpowiedz

62

Podoba mi się odpowiedź Omara, ale to nie działa dla mnie. Tylko dla przypomnienia jest to rozwiązanie używam teraz:

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

Co to jest Config.Url? – joshcomley

+0

Zawiera adres URL mojej witryny. Tam usunąłem to. – Pablo

+2

Biorąc pod uwagę, że klasa UrlHelper opiera się na kontekście żądania (i kontekście HTTP), ręczne skonstruowanie tych obiektów kontekstu może dać nieoczekiwane wyniki. Jeśli HttpContext.Current ma wartość null i używasz tego podejścia, postępowałbym ostrożnie. – Sean

-27

myślę co szukasz to:

Url.Action("ActionName", "ControllerName"); 
41

UrlHelper mogą być zbudowane od wewnątrz działania kontrolera z następującymi:

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

poza z kontrolera, a UrlHelper można skonstruować, tworząc RequestContext z RouteTable.Routes RouteData.

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

(Na podstawie odpowiedzi Briana, z niewielką korektą kodu dodany.)

+1

Ale nie mam kontrolera w modelu. – Pablo

+0

OK, przepraszam, nie byłem pewien, gdzie dokładnie kod został wykonany. Pozwól mi spojrzeć ... –

+2

Nie trzeba tworzyć nowego kontekstu żądania: 'var urlHelper = new UrlHelper (HttpContext.Current.Request.RequestContext);' – bradlis7

8

Tak, można go instancję. Można zrobić coś takiego:

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

RouteTable.Routes jest właściwość statyczna, więc nie powinno być OK; Aby uzyskać odniesienie do HttpContextBase, HttpContextWrapper pobiera odniesienie do HttpContext i HttpContext.

+0

To nie zadziała, chociaż jest bardzo blisko. Zobacz moją odpowiedź poniżej. –

261

pomocna wskazówka, w dowolnej aplikacji ASP.NET, można uzyskać odwołanie obecnego HTTPContext

HttpContext.Current 

który pochodzi z system.Web. Dlatego dodaje się będzie pracować w dowolnym miejscu w aplikacji ASP.NET MVC:

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

Przykład:

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

Wywołanie właściwości Link na utworzonego obiektu MyModel zwróci prawidłowy adres URL, aby wyświetlić model oparty na routingu w Global.asax

+0

Czy na pewno istnieje HttpContext.Current.Request.RequestContext? HttpContext.Current.Request wydaje się nie mieć RequestContext. – Pablo

+1

To dziwne. Właśnie wypróbowałem to rozwiązanie i działa ono idealnie. Używam programu ASP.NET MVC 2 Preview 2, ale myślę, że działa to we wszystkich wersjach. Nie wiem, dlaczego to nie działa. Czy tworzysz klasę poza projektem MVC? Upewnij się też, że są "używane" zarówno dla "System.Web", jak i "System.Web.Mvc" – Omar

+0

Jestem w projekcie ASP.NET MVC 1, myślałem o braku rzeczy, ale mam je oba. – Pablo

0

Starałem się zrobić coś podobnego z poziomu strony (poza kontrolerem).

UrlHelper nie pozwala mi skonstruować go tak łatwo, jak Pablos odpowiedzi, ale potem przypomniał sobie starą sztuczkę skutecznym zrobić to samo:

string ResolveUrl(string pathWithTilde) 
0

po wypróbowaniu wszystkich innych odpowiedzi, skończyło się

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

Haters znienawidzi ¯ \ _ (ツ) _/¯