2011-01-17 2 views
121

Stavo cercando di creare un helper dichiarativo Razor nella mia cartella App_Code per un progetto RTM MVC 3.Utilizzo delle estensioni MVC HtmlHelper dalle viste dichiarative di Razor

Il problema che ho riscontrato è che le estensioni MVC HtmlHelper, come ActionLink, non sono disponibili. Questo perché gli helper compilati derivano da System.Web.WebPages.HelperPage e sebbene esponga una proprietà Html, di tipo System.Web.WebPages.HtmlHelper anziché System.Web.Mvc.HtmlHelper.

Un esempio del tipo di errore mi è stato sempre è:

'System.Web.Mvc.HtmlHelper' non significa contiene una definizione per 'ActionLink' e nessun metodo di estensione 'ActionLink' accettando un primo argomento di tipo 'System.Web.Mvc.HtmlHelper' potrebbe essere trovato (che le manca una direttiva using o un riferimento all'assembly?)

la mia unica soluzione è essere it per creare il mio HelperPage e sostituisce la proprietà 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; } 
    } 
} 

Poi ho dovuto scrivere il seguente nella parte superiore di ogni aiuto:

@inherits FunnelWeb.Web.App_Code.HelperPage 
@using System.Web.Mvc 
@using System.Web.Mvc.Html 

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

E 'destinata ad essere così difficile in MVC 3 o sto facendo qualcosa di sbagliato?

+3

Se è necessario anche l'helper Url, è possibile aggiungere questa riga di codice a HelperPage: UrlHelper Url statico pubblico { get {return new UrlHelper (Html.ViewContext.RequestContext); } } –

risposta

41

Dai un'occhiata a Marcind's answer per questa domanda. Quello che stai vivendo è una limitazione di mettere le viste dichiarative nella cartella App_Code.

Mettere le aiutanti in App_Code funziona ma ha alcune limitazioni che impatto alcuni scenari MVC (per . Esempio: non ha accesso a MVC Html helper standard)

+1

Nota per altri lettori: questa risposta è assolutamente corretta, ma anche consultare il contributo aggiuntivo di Andrew Nurse di seguito per una potenziale soluzione alternativa. –

0

So che ci sono alcuni problemi di intelligenza con MVC 3. Penso che gli helper funzioneranno ancora se lo spazio dei nomi è impostato in web.config.

MVC 3 RTM è appena stato rilasciato se si sta utilizzando questa o una beta?

+0

Utilizzo della versione RTM –

11

Omar ha ottenuto la risposta giusta qui , ma volevo aggiungere qualcosa (sentiti libero di contrassegnare la risposta di Omar come risposta).

Siamo stati a conoscenza di questo in v1 e non siamo riusciti a ottenere una grande correzione nel prodotto, ma David Ebbo (un architetto del team ASP.Net) ha pubblicato un esempio di un generatore di codice di Visual Studio che è fondamentalmente una prima esplorazione del tipo di idee che stiamo osservando per farlo funzionare correttamente: http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries.aspx

Provalo e guarda cosa ne pensi! Fai sapere a David se hai commenti postando sul suo blog.

+2

Ci sono piani per risolvere questo problema nella prossima versione di Razor? Ho notato che questo è ancora un problema in VS 11 Beta. – Omar

38

Ho creato un metodo di estensione per l'helper WebPages in modo che sia possibile accedere all'helper di pagina.

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

Uso: '@ Html.GetPageHelper(). ActionLink (" actioname ")' – deerchao

+0

Questo funziona per me, ma ho dovuto aggiungere '@using System.Web.Mvc' e' @using System.Web.Mvc.Html' nel file helpers cshtml all'interno di App_Code – Tomino

+1

Perché esiste una classe HtmlHelper separata? Dovrebbe essere lo stesso sia che si trovi in ​​App_Code o Views. Fallimento della progettazione mezzo mezzo epica. – Triynko

4

A vantaggio dei ricercatori, ho ottenuto lo stesso errore durante la creazione di una vista MVC come parte di una libreria di classi (per il componente riutilizzo). La soluzione, in parte accennato in precedenza, è stato quello di aggiungere le seguenti istruzioni using nella parte superiore del file .cshtml:

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

Nessun ulteriore lavoro necessario.

+0

I miei aiutanti nella mia.cshtml in App_Code non è stato riconosciuto in Intellisense. Aggiunta di @using System.Web.Mvc.Html nella parte superiore del mio .cshtml sotto App_code lavorato. –

+0

Quando eseguo questa operazione, viene visualizzato il messaggio "Impossibile caricare il tipo" System.Web.WebPages.Instrumentation.InstrumentationService "dall'assembly" System.Web.WebPages, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35 "." 'quando si posiziona il cursore' @using System.Web.Mvc'. Qualche idea? – JoeBrockhaus

9

Simile a @Jakes risposta:

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

} 

Usage:

@MvcIntrinsics.Html.Raw("test") 

Fonte: Dino Esposito - Programmazione Microsoft ASP.NET MVC

+1

È ridicolo che ciò sia addirittura necessario e che questi non siano solo parte della classe base per le viste in App_Code. – Triynko

0

sembra che l'ASP.NET MVC ha fissato questo problema in VS 2013. Vedi questo post http://aspnet.uservoice.com/forums/41201-asp-net-mvc/suggestions/3670180-support-helper-extensionmethod-this-htmlhelper-ht

+0

No, per niente. Intellisense non sta raccogliendo i metodi di estensione, e ho l'aggiornamento VS2013 5. Ho '@utilizzando System.Web.Mvc.Html' nella parte superiore del file cshtml in App_Code, ma scrivendo @Html .... non rivela nessuno dei metodi di estensione come 'EditorFor'. È ridicolo che questo non funzioni dopo due importanti rilasci e post sul blog che affermano che è stato implementato. Non è. In effetti, i metodi di estensione non possono funzionare, perché indirizzano la classe System.Web.Mvc.HtmlHelper, non la classe System.Web.WebPages.HtmlHelper, che viene esposta dalla classe System.Web.WebPages.HelperPage . – Triynko

7

Un alternativ e soluzione:

Aggiungere questo in cima al vostro file di rasoio-helper:

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

poi chiamare in questo modo:

@HHtml.ActionLink("actionname") 
+0

Funziona! Hai bisogno di più upvote, signore! – hirikarate

2

Il mio approccio a questo è di passare semplicemente la pagina come parametro al metodo helper. Quindi nel tuo esempio sarebbe:

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

Poi nella vista del rasoio dove serve chiamare in questo modo:

@YourHelperFilename.DoSomething(this) 

Facendo questo dà subito accedere a proprietà di pagina come Html o Url che di solito hai (e attraverso quello le estensioni HtmlHelper).

Come ulteriore vantaggio (se richiesto), è possibile accedere anche alle proprietà di istanza, ad esempio ViewData della pagina.

+0

Bello e semplice! –