Aide en ligne ASP.NET MVC pour les champs

asp.net-mvc c# expression-trees html-helper razor

Question

J'ai besoin d'un assistant en ligne générique pour afficher les champs.

Voici ce que j'ai actuellement:

@helper DisplayField(Func<MyModel, string> field)
{
    if (string.IsNullOrWhiteSpace(field(Model)) == false)
    {
        <div class="row"> @field(Model) </div>     
    }
}

Usage:

@DisplayField(m => m.Name)
@DisplayField(m => m.PhoneNumber)

Je ne sais pas comment afficher Label (DisplayAttribute) à l'intérieur d'un assistant. S'il vous plaît aider.

Réponse acceptée

En haut de votre page, ajoutez un using pour System.Linq.Expressions, par exemple.

@using System.Linq.Expressions

(ou ajoutez cet espace de noms dans web.config).

Ensuite, pour créer l’assistant, cela ressemblerait à quelque chose comme:

@helper DisplayField(Expression<Func<MyModel, string>> field)
{
    @Html.LabelFor(field)
    @Html.DisplayFor(field)
}

Vous pouvez ajouter une logique supplémentaire pour vérifier la valeur vide, etc. Il serait peut-être préférable de créer un HtmlHelper, de cette manière, vous pourrez utiliser des arguments de type générique plutôt que "MyModel" et "string" comme ci-dessus. Lors de ma dernière tentative, il n'était pas possible d'ajouter des arguments de type générique à un utilitaire intégré, par exemple. Ce qui suit n'est pas possible, sauf si cette fonctionnalité a été ajoutée depuis:

@helper DisplayField<TModel, TValue>(Expression<Func<TModel, TValue>> field)
{
    @Html.LabelFor(field)
    @Html.DisplayFor(field)
}

Donc, pour obtenir la méthode générique, vous utiliseriez un HtmlHelper personnalisé. Pour faire ça:

  1. Créez un fichier comme suit:

    using System;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Mvc.Html;
    
    namespace MvcApplication1.HtmlHelpers
    {
        public static class HtmlHelpers
        {
            public static MvcHtmlString DisplayFieldFor<TModel, TValue>(
                this HtmlHelper<TModel> helper, 
                Expression<Func<TModel, TValue>> field)
            {
                var labelString = helper.LabelFor(field);
                var displayString = helper.DisplayFor(field);
    
                return MvcHtmlString.Create(
                    labelString.ToString() + 
                    displayString.ToString());
            }
        }
    }
    
  2. Dans votre page, l'utilisation d'une telle chose serait:

    @Html.DisplayFieldFor(m => m.Name)
    @Html.DisplayFieldFor(m => m.PhoneNumber)
    

etc. Vous devrez peut-être vérifier vos utilisations sur votre page ou ajouter l'espace de noms du HtmlHelper dans web.config.


Réponse populaire

@ David_001 a fourni une solution MVC très élégante pour cela; Je laisse ma réponse ici car il décrit le mécanisme interne et pourrait être utile si vous devez résoudre un problème qui n'est pas couvert par les aides MVC prêts à l'emploi.

Changez le type de paramètre de Func<MyModel, string> à Expression<Func<MyModel, string>> . De cette façon, vous recevez une expression dynamique dans la méthode que vous pouvez analyser au lieu du délégué statique que vous recevez dans le formulaire actuel.
Vous pouvez récupérer la valeur du champ comme ceci:

var compExpr = field.Compile();
var value = compExpr.DynamicInvoke(Model);

Vous pouvez accéder au membre et à ses attributs qui sont renvoyés par l'expression dynamique comme suit:

var memberAccExpr = (System.Linq.Expressions.MemberAccessExpression)field.Body;
var attr = (DisplayAttribute)memberAccExpr.Member.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault();

Je l'ai testé à peu près dans un projet C # (pas MVC), donc je ne peux pas dire si cela fonctionne dans Razor; mais je suis sûr que vous pouvez également déplacer votre code dans une classe normale.
Veuillez noter que vous perdez un type de sécurité avec cette approche puisqu'un appelant peut fournir une variété d'expressions dynamiques à la méthode. Vous devez donc en tenir compte si vous analysez l'expression afin de trouver l'attribut.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi