Wygeneruj adres URL w pomocniku HTML

168

Zwykle w widoku ASP.NET można użyć następującej funkcji, aby uzyskać adres URL (nie <a>):

Url.Action("Action", "Controller");

Jednak nie mogę znaleźć, jak to zrobić z niestandardowego pomocnika HTML. mam

public class MyCustomHelper
{
   public static string ExtensionMethod(this HtmlHelper helper)
   {
   }
}

Zmienna pomocnicza ma metody Action i GenerateLink, ale generują one <a>. Poszperałem trochę w kodzie źródłowym ASP.NET MVC, ale nie mogłem znaleźć prostego sposobu.

Problem polega na tym, że powyższy adres URL jest członkiem klasy widoku i do swojej instancji potrzebuje pewnych kontekstów i map tras (z którymi nie chcę się zajmować i nie powinienem). Alternatywnie, instancja klasy HtmlHelper ma również pewien kontekst, który, jak sądzę, jest albo kolacją podzbioru informacji kontekstowych instancji Url (ale znowu nie chcę się tym zajmować).

Podsumowując, myślę, że jest to możliwe, ale ponieważ wszystkie sposoby, które widziałem, obejmują manipulację mniej lub bardziej wewnętrznymi elementami ASP.NET, zastanawiam się, czy jest lepszy sposób.

Edycja: Na przykład widzę jedną możliwość:

public class MyCustomHelper
{
    public static string ExtensionMethod(this HtmlHelper helper)
    {
        UrlHelper urlHelper = new UrlHelper(helper.ViewContext.RequestContext);
        urlHelper.Action("Action", "Controller");
    }
}

Ale to nie wydaje się właściwe. Nie chcę sam mieć do czynienia z wystąpieniami UrlHelper. Musi być łatwiejszy sposób.

Jan Zich
źródło
3
Zdaję sobie sprawę, że jest to uproszczony przykład, ale w pokazanym przykładzie rozszerzyłbym UrlHelper zamiast HtmlHelper. Twój prawdziwy kod może jednak wymagać obu.
Craig Stuntz
Przepraszam, powinienem był być bardziej jasny: chciałem wykonać renderowanie HTML w metodzie rozszerzenia i musiałem wygenerować dla niego adresy URL.
Jan Zich

Odpowiedzi:

217

Możesz utworzyć pomocnika adresu URL w ten sposób wewnątrz metody rozszerzenia pomocnika html:

var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
var url = urlHelper.Action("Home", "Index")
Darin Dimitrov
źródło
2
Myślę, że byłoby lepiej, gdyby konstruktor również zainicjował RouteCollectionnew UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection)
kpull1
22

Możesz również uzyskać linki za pomocą UrlHelperklasy publicznej i statycznej:

UrlHelper.GenerateUrl(null, actionName, controllerName, null, null, null, routeValues, htmlHelper.RouteCollection, htmlHelper.ViewContext.RequestContext, true)

W tym przykładzie nie musisz tworzyć nowej klasy UrlHelper, co może być małą zaletą.

cryss
źródło
Bardziej podoba mi się ta odpowiedź, ponieważ ustawia RouteCollection.
kpull1
10

Oto mój malutki metoda extenstion uzyskania UrlHelperz HtmlHelperinstancji:

  public static partial class UrlHelperExtensions
    {
        /// <summary>
        /// Gets UrlHelper for the HtmlHelper.
        /// </summary>
        /// <param name="htmlHelper">The HTML helper.</param>
        /// <returns></returns>
        public static UrlHelper UrlHelper(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewContext.Controller is Controller)
                return ((Controller)htmlHelper.ViewContext.Controller).Url;

            const string itemKey = "HtmlHelper_UrlHelper";

            if (htmlHelper.ViewContext.HttpContext.Items[itemKey] == null)
                htmlHelper.ViewContext.HttpContext.Items[itemKey] = new UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection);

            return (UrlHelper)htmlHelper.ViewContext.HttpContext.Items[itemKey];
        }
    }

Użyj go jako:

public static MvcHtmlString RenderManagePrintLink(this HtmlHelper helper, )
{    
    var url = htmlHelper.UrlHelper().RouteUrl('routeName');
    //...
}

(Publikuję to i tylko w celach informacyjnych)

Kibria
źródło
Doskonałe podejście, ponieważ ponownie wykorzystuje istniejący obiekt, zamiast tworzyć nowy.
Mike
Używamy ASP.NET 4.5 i wystąpiły problemy z ponownym włączeniem. Uważamy, że UrlHelper nie nadaje się do ponownego wykorzystania w żądaniach HTTP. Proszę zwrócić uwagę.
Carl in 't Veld