Создание URL-адреса в HTML-помощнике

Обычно в представлении ASP.NET можно использовать следующую функцию для получения URL-адреса (а не <a>):

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

Однако я не могу найти, как это сделать из пользовательского помощника HTML. У меня

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

Вспомогательная переменная имеет методы Action и GenerateLink, но они генерируют <a> s. Я сделал некоторые копания в исходном коде ASP.NET MVC, но я не мог найти простой способ.

Проблема в том, что Url above является членом класса view и для его создания ему нужны некоторые контексты и карты маршрутов (с которыми я не хочу иметь дело, и Im не должен в любом случае). В качестве альтернативы, экземпляр класса HtmlHelper имеет также некоторый контекст, который, как я полагаю, представляет собой либо ужин подмножества контекстной информации экземпляра Url (но опять же я не хочу иметь с ним дело).

В целом, я думаю, что это возможно, но поскольку все способы, которые я мог видеть, включают некоторые манипуляции с некоторыми более или менее внутренними компонентами ASP.NET, мне интересно, есть ли лучший способ.

Изменить: Например, одна из возможностей, которую я вижу, будет:

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

Но это не кажется правильным. Я не хочу иметь дело с экземплярами UrlHelper. Должен быть более простой способ.

Ответ 1

Вы можете создать помощник URL, как это, внутри метода расширения html-помощника:

var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
var url = urlHelper.Action("Home", "Index")

Ответ 2

Вы также можете получить ссылки, используя UrlHelper общедоступный и статический класс:

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

В этом примере вам не нужно создавать новый класс UrlHelper, что может быть небольшим преимуществом.

Ответ 3

Вот мой крошечный метод extenstion для получения UrlHelper экземпляра HtmlHelper:

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

Используйте его как:

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

(Я отправляю эту ссылку только для справки)