web-dev-qa-db-fra.com

Utilisation des extensions MVC HtmlHelper à partir de vues déclaratives Razor

J'essayais de créer un assistant déclaratif Razor dans mon dossier App_Code pour un projet MVC 3 RTM.

Le problème que j'ai rencontré est que les extensions MVC HtmlHelper, comme ActionLink, ne sont pas disponibles. En effet, les aides compilées proviennent de System.Web.WebPages.HelperPage et, bien qu'elle expose une propriété Html, elle est de type System.Web.WebPages.HtmlHelper plutôt que System.Web.Mvc.HtmlHelper.

Voici un exemple du type d'erreur que je recevais:

'System.Web.Mvc.HtmlHelper' ne le fait pas contient une définition pour 'ActionLink' et pas de méthode d'extension 'ActionLink' accepter un premier argument de type 'System.Web.Mvc.HtmlHelper' pourrait être trouvé (il vous manque une directive using ou une référence Assembly?)

Ma seule solution a été de créer ma propre HelperPage et de remplacer la propriété 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; }
    }
}

Je dois ensuite écrire ce qui suit en haut de chaque aide:

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

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

Est-ce censé être aussi difficile dans MVC 3 ou est-ce que je fais quelque chose de mal?

121
Paul Stovell

Jetez un coup d'œil à la réponse de Marcind à cette question. Ce que vous rencontrez est une limitation du placement de vues déclaratives dans le dossier App_Code.

Mettre vos aides dans App_Code fonctionne mais a certaines limites que impact sur certains scénarios MVC (pour exemple: pas d'accès à l'aide standard de MVC Html.)

42
Omar

J'ai créé une méthode d'extension pour l'assistant WebPages afin de pouvoir accéder à l'assistant de page. 

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

Omar a la bonne réponse ici, mais je voulais ajouter quelque chose (ne hésitez pas à marquer la réponse d'Omar comme réponse).

Nous étions au courant de cela dans la v1 et n'avons pas réussi à trouver une solution miracle au produit, mais David Ebbo (un architecte de l'équipe ASP.Net) a publié un exemple de générateur de code Visual Studio, qui constitue essentiellement une première exploration de le genre d'idées que nous recherchons pour que cela fonctionne correctement: http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable -libraries.aspx

Essayez cela et voyez ce que vous en pensez! Si vous avez des commentaires, signalez-le à David en postant sur son blog.

11

Similaire à @Jakes answer:

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")

Source: Dino Esposito - Programmation Microsoft ASP.NET MVC

9
Greg Gum

Une solution alternative:

Ajoutez ceci au-dessus de votre fichier razor-helper:

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

puis appelez-le comme ceci:

@HHtml.ActionLink("actionname")
7
Alex

Pour le bénéfice des chercheurs, j'ai eu la même erreur lors de la création de vues MVC dans une bibliothèque de classes (pour la réutilisation de composants). La solution, partiellement évoquée ci-dessus, consistait à ajouter les instructions using suivantes en haut du fichier .cshtml:

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

Aucun travail supplémentaire nécessaire.

4
HockeyJ

Mon approche consiste simplement à passer la page en tant que paramètre de la méthode d'assistance. Donc, dans votre exemple, ce serait:

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

Ensuite, dans votre vue Razor où vous en avez besoin, appelez-la comme suit:

@YourHelperFilename.DoSomething(this)

Cela vous donne immédiatement accès aux propriétés de page telles que Html ou Url que vous avez habituellement (et à travers les extensions HtmlHelper).

En tant qu'avantage supplémentaire (si vous en avez besoin), vous avez également accès à des propriétés d'instance telles que la variable ViewData de la page.

3
Dejan
0
Omar

Je sais qu’il existe certains problèmes d’intellisense avec MVC 3. Je pense que les aides continueront à fonctionner si l’espace de nommage est défini dans web.config.

MVC 3 RTM vient de paraître, utilisez-vous ceci ou une version bêta? 

0
Lee Smith