Gere URL no auxiliar HTML

168

Normalmente, em uma exibição do ASP.NET, pode-se usar a seguinte função para obter um URL (não um <a>):

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

No entanto, não consigo encontrar como fazê-lo em um auxiliar de HTML personalizado. eu tenho

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

A variável auxiliar possui os métodos Action e GenerateLink, mas eles geram <a>'s. Eu pesquisei no código-fonte do ASP.NET MVC, mas não consegui encontrar uma maneira direta.

O problema é que o URL acima é um membro da classe view e, por sua instanciação, precisa de alguns contextos e mapas de rotas (com os quais não quero lidar e que não devo). Como alternativa, a instância da classe HtmlHelper também possui algum contexto que, suponho, é a ceia do subconjunto das informações de contexto da instância Url (mas, novamente, não quero lidar com isso).

Em resumo, acho que é possível, mas como todas as formas que pude ver envolvem alguma manipulação com algumas coisas mais ou menos internas do ASP.NET, pergunto-me se existe uma maneira melhor.

Edit: Por exemplo, uma possibilidade que vejo seria:

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

Mas isso não parece certo. Não quero lidar com instâncias do UrlHelper. Deve haver uma maneira mais fácil.

Jan Zich
fonte
3
Sei que este é um exemplo simplificado, mas, para o exemplo mostrado, eu estenderia o UrlHelper em vez do HtmlHelper. Seu código real pode precisar de ambos, no entanto.
22710 Craig Stuntz
Desculpe, eu deveria ter sido mais claro: queria fazer uma renderização HTML no método de extensão e precisava gerar URLs para ele.
Jan Zich

Respostas:

217

Você pode criar um auxiliar de URL como este dentro do método de extensão de auxiliar html:

var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
var url = urlHelper.Action("Home", "Index")
Darin Dimitrov
fonte
2
Eu acho que seria melhor se o construtor também inicializa RouteCollectionnew UrlHelper(htmlHelper.ViewContext.RequestContext, htmlHelper.RouteCollection)
kpull1
22

Você também pode obter links usando UrlHelpera classe pública e estática:

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

Neste exemplo, você não precisa criar uma nova classe UrlHelper, o que poderia ser uma pequena vantagem.

Cryss
fonte
Eu gosto mais desta resposta porque define o RouteCollection.
precisa saber é o seguinte
10

Aqui está o meu pequeno método de extensão para obter UrlHelperuma HtmlHelperinstância:

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

Use-o como:

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

(Estou postando este ans apenas para referência)

Kibria
fonte
Abordagem excelente porque reutiliza um objeto existente em vez de criar um novo.
1178 Mike
Estamos usando o ASP.NET 4.5 e tivemos problemas de reentrada. Não acreditamos que o UrlHelper seja reutilizável em solicitações HTTP. Por favor, tome nota.
Carl in 't Veld