Usando extensões MVC HtmlHelper de visualizações declarativas do Razor

Eu estava tentando criar um auxiliar declarativo Razor na minha pasta App_Code para um projeto MVC 3 RTM.

O problema que eu encontrei foi que as extensões MVC HtmlHelper, como ActionLink, não estão disponíveis. Isso ocorre porque os auxiliares compilados derivam de System.Web.WebPages.HelperPage e, embora exponha uma propriedade Html , é do tipo System.Web.WebPages.HtmlHelper vez de System.Web.Mvc.HtmlHelper .

Um exemplo do tipo de erro que eu estava recebendo é:

‘System.Web.Mvc.HtmlHelper’ não contém uma definição para ‘ActionLink’ e nenhum método de extensão ‘ActionLink’ aceitando um primeiro argumento do tipo ‘System.Web.Mvc.HtmlHelper’ pode ser encontrado (você está perdendo uma diretiva usando ou uma referência de assembly?)

Minha única solução foi criar meu próprio HelperPage e replace a propriedade Html:

 using System.Web.WebPages; public class HelperPage : System.Web.WebPages.HelperPage { // Workaround - exposes the MVC HtmlHelper instead of the normal helper public static new HtmlHelper Html { get { return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html; } } } 

Eu então tenho que escrever o seguinte no topo de cada ajudante:

 @inherits FunnelWeb.Web.App_Code.HelperPage @using System.Web.Mvc @using System.Web.Mvc.Html @helper DoSomething() { @Html.ActionLink("Index", "Home") } 

É para ser tão difícil em MVC 3, ou estou fazendo algo errado?

Dê uma olhada na resposta de Marcind para esta questão. O que você está enfrentando é uma limitação de colocar exibições declarativas na pasta App_Code .

Colocar seus helpers no App_Code funciona, mas tem certas limitações que afetam determinados cenários do MVC (por exemplo: nenhum access a MVC Html. Helpers padrão)

Eu criei um método de extensão para o auxiliar do WebPages para que eu possa obter access ao auxiliar de página.

 public static HtmlHelper GetPageHelper(this System.Web.WebPages.Html.HtmlHelper html) { return ((System.Web.Mvc.WebViewPage) WebPageContext.Current.Page).Html; } 

Omar tem a resposta certa aqui, mas eu queria acrescentar algo (fique à vontade para marcar a resposta de Omar como resposta).

Nós estávamos cientes disso na v1 e não fomos capazes de obter uma grande correção no produto, mas David Ebbo (um arquiteto da equipe da ASP.Net) postou uma amostra de um gerador de código do Visual Studio que é basicamente uma primeira exploração de o tipo de ideias que estamos procurando para fazer isso funcionar corretamente: http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries .aspx

Experimente e veja o que você pensa! Deixe David saber se você tem comentários postando em seu blog.

Semelhante ao @Jakes resposta:

 public static class MvcIntrinsics { public static System.Web.Mvc.HtmlHelper Html { get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html; } } public static System.Web.Mvc.AjaxHelper Ajax { get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Ajax; } } public static System.Web.Mvc.UrlHelper Url { get { return ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Url; } } } 

Uso:

 @MvcIntrinsics.Html.Raw("test") 

Fonte: Dino Esposito – Programação Microsoft ASP.NET MVC

Uma solução alternativa

Adicione isto em cima do seu arquivo de razor-ajudante:

 @functions { public static System.Web.Mvc.HtmlHelper HHtml = ((System.Web.Mvc.WebViewPage)WebPageContext.Current.Page).Html; } 

então ligue assim:

 @HHtml.ActionLink("actionname") 

Para o benefício dos pesquisadores, recebi o mesmo erro ao criar exibições do MVC como parte de uma biblioteca de classs (para reutilização de componentes). A solução, parcialmente mencionada acima, foi adicionar as seguintes instruções usando a parte superior do arquivo .cshtml:

 @using System.Web.Mvc @using System.Web.Mvc.Html 

Nenhum trabalho adicional é necessário.

Minha abordagem para isso é simplesmente passar a página como um parâmetro para o método auxiliar. Então, no seu exemplo, seria:

 @helper DoSomething(WebViewPage page) { @page.Html.ActionLink("Index", "Home") } 

Então, na sua visão Razor, onde você precisa, ligue assim:

 @YourHelperFilename.DoSomething(this) 

Fazendo isso, você tem access imediato às propriedades da página, como Html ou Url que você normalmente possui (e através das extensões HtmlHelper ).

Como benefício adicional (se você precisar disso), você também terá access a propriedades de instância, como o ViewData da página.

Eu sei que existem alguns problemas intellisense com o MVC 3. Acho que os ajudantes ainda funcionarão se você tiver o namespace definido no web.config.

MVC 3 RTM acaba de ser liberado você está usando este ou um beta?

Parece que a ASP.NET MVC corrigiu esse problema no VS 2013. Consulte este post http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3670180-support-helper-extensionmethod-this- htmlhelper-ht