33 votes

ASP.NET MVC 3 Custom HTML Helpers - Meilleures pratiques/utilisations

Je découvre MVC et j'ai parcouru les tutoriels sur le site web d'asp.net.

Ils comprennent un exemple d'aide html personnalisée pour tronquer un texte long affiché dans un tableau.

Je me demandais simplement quelles autres solutions les gens ont trouvé en utilisant les HTML helpers et s'il y a des meilleures pratiques ou des choses à éviter lors de la création ou de l'utilisation de ces aides.

Par exemple, j'envisageais d'écrire une aide personnalisée pour formater les dates que je dois afficher à divers endroits, mais je crains maintenant qu'il n'y ait une solution plus élégante (c'est-à-dire des DataAnnotations dans mes modèles).

Qu'en pensez-vous ?

EDIT :

Une autre utilisation potentielle à laquelle je viens de penser... la concaténation de chaînes de caractères. Une aide personnalisée pourrait prendre un ID utilisateur en entrée et retourner le nom complet de l'utilisateur... Le résultat pourrait être une forme de (Titre) (Prénom) (Milieu) (Nom) en fonction des champs disponibles. C'est juste une idée, je n'ai encore rien essayé de tel.

1 votes

Je suis toujours intéressé de voir les autres choses intéressantes que les gens ont faites avec les Custom HTML Helpers. N'hésitez pas à les publier !

101voto

spot Points 2003

J'utilise les HtmlHelpers tout le temps, le plus souvent pour encapsuler la génération de HTML standard, au cas où je changerais d'avis. J'ai eu des aides telles que :

  • Html.BodyId() : génère une balise d'identification de corps conventionnelle à laquelle il est possible de se référer lors de l'ajout de css personnalisés pour une vue.
  • Html.SubmitButton(string) : génère un élément input[type=submit] ou button[type=submit], en fonction de la manière dont je souhaite styliser les boutons.
  • Html.Pager(IPagedList) : Pour générer des contrôles de pagination à partir d'un modèle de liste paginée.
  • etc....

L'une de mes utilisations préférées des HtmlHelpers est de déshydrater le balisage des formulaires courants. En général, j'ai une div conteneur pour une ligne de formulaire, une div pour l'étiquette, et une étiquette pour l'entrée, les messages de validation, le texte d'indication, etc. En fin de compte, cela peut se traduire par un grand nombre de balises html de type "boilerplate". Voici un exemple de la manière dont j'ai géré cette situation :

public static MvcHtmlString FormLineDropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string labelText = null, string customHelpText = null, object htmlAttributes = null)
{
    return FormLine(
        helper.LabelFor(expression, labelText).ToString() +
        helper.HelpTextFor(expression, customHelpText),
        helper.DropDownListFor(expression, selectList, htmlAttributes).ToString() +
        helper.ValidationMessageFor(expression));
}

public static MvcHtmlString FormLineEditorFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string templateName = null, string labelText = null, string customHelpText = null, object htmlAttributes = null)
{
    return FormLine(
        helper.LabelFor(expression, labelText).ToString() +
        helper.HelpTextFor(expression, customHelpText),
        helper.EditorFor(expression, templateName, htmlAttributes).ToString() +
        helper.ValidationMessageFor(expression));
}

private static MvcHtmlString FormLine(string labelContent, string fieldContent, object htmlAttributes = null)
{
    var editorLabel = new TagBuilder("div");
    editorLabel.AddCssClass("editor-label");
    editorLabel.InnerHtml += labelContent;

    var editorField = new TagBuilder("div");
    editorField.AddCssClass("editor-field");
    editorField.InnerHtml += fieldContent;

    var container = new TagBuilder("div");
    if (htmlAttributes != null)
        container.MergeAttributes(new RouteValueDictionary(htmlAttributes));
    container.AddCssClass("form-line");
    container.InnerHtml += editorLabel;
    container.InnerHtml += editorField;

    return MvcHtmlString.Create(container.ToString());
}

public static MvcHtmlString HelpTextFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string customText = null)
{
    // Can do all sorts of things here -- eg: reflect over attributes and add hints, etc...
}    

Une fois que vous avez fait cela, vous pouvez sortir des lignes de formulaire comme ceci :

<%: Html.FormLineEditorFor(model => model.Property1) %>
<%: Html.FormLineEditorFor(model => model.Property2) %>
<%: Html.FormLineEditorFor(model => model.Property3) %>

... et BAM, toutes vos étiquettes, entrées, conseils et messages de validation sont sur votre page. Encore une fois, vous pouvez utiliser des attributs sur vos modèles et réfléchir sur eux pour devenir vraiment intelligent et DRY. Et bien sûr, ce serait une perte de temps si vous ne pouviez pas standardiser la conception de votre formulaire. Cependant, pour les cas simples, où css peut fournir toute la personnalisation dont vous avez besoin, cela fonctionne grrrrrrrrreat !

Morale de l'histoire : les HtmlHelpers peuvent vous protéger des changements de conception globaux qui détruisent les balises élaborées à la main, vue après vue. Je les aime bien. Mais on peut aller trop loin, et parfois des vues partielles sont préférables à des aides codées. Une règle générale que j'utilise pour décider entre l'aide et la vue partielle : Si le morceau de HTML nécessite beaucoup de logique conditionnelle ou d'astuces de codage, j'utilise une aide (mettre le code là où il doit se trouver) ; sinon, si je ne fais qu'afficher un balisage commun sans trop de logique, j'utilise une vue partielle (mettre le balisage là où il doit se trouver).

J'espère que cela vous donnera quelques idées !

3 votes

Excellent article ! Je vais certainement en copier/coller quelques uns si cela ne vous dérange pas ;)

7 votes

Excellente réponse. Il m'a fallu un peu de temps pour comprendre que j'avais besoin d'utiliser System.Web.Mvc.Html ; pour faire apparaître les extensions .EditorFor.

16voto

Darin Dimitrov Points 528142

Dans le cas du formatage de la Format d'affichage pourrait être une solution intéressante :

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}")]
public DateTime Date { get; set; }

et ensuite simplement :

@Html.DisplayFor(x => x.Date)

En ce qui concerne la troncature des chaînes de caractères, une aide HTML personnalisée est une bonne solution.


UPDATE :

En ce qui concerne votre EDIT, une aide HTML personnalisée pourrait fonctionner dans cette situation, mais il y a aussi une approche alternative que j'aime beaucoup : les modèles de vue. Si, dans cette vue particulière, vous voulez toujours afficher la concaténation des noms, vous pouvez définir un modèle de vue :

public class PersonViewModel
{
    public string FullName { get; set; }
}

Le contrôleur va maintenant interroger le référentiel pour récupérer le modèle, puis l'associer à un modèle de vue qui sera transmis à la vue de manière à ce que celle-ci puisse simplement @Html.DisplayFor(x => x.FullName) . La correspondance entre les modèles et les modèles de vue pourrait être simplifiée grâce à des cadres tels que AutoMapper .

4 votes

Très intéressant. Il semble presque qu'une aide html personnalisée soit le dernier recours.

0voto

satya prakash Points 11
public static HtmlString OwnControlName<T, U>(this HtmlHelper<T> helper, Expression<Func<T, U>> expression, string label_Name = "", string label_Title = "", Attr attr = null)
        {
            TemplateBuilder tb = null;
            string template = null;
          if (expression == null) throw new ArgumentException("expression");
 obj = helper.ViewData.Model;
                tb.Build(obj, expression.Body as MemberExpression, typeof(T), new SimpleTemplate(new TextArea()), label_Name, label_Title, attr);
                template = tb.Get();
 return new MvcHtmlString(template);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X