ASP.NET MVC helper in linea per i campi

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

Domanda

Ho bisogno di un helper in linea generico per mostrare i campi.

Ecco cosa ho attualmente:

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

Uso:

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

Non ho idea di come mostrare Label (DisplayAttribute) all'interno di un helper. Per favore aiuto.

Risposta accettata

Nella parte superiore della pagina, aggiungere in un utilizzo per System.Linq.Expressions, ad es.

@using System.Linq.Expressions

(o aggiungi questo spazio dei nomi in web.config).

Quindi per creare l'helper, assomiglierebbe a qualcosa:

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

È possibile aggiungere ulteriore logica per controllare il valore vuoto, ecc. Potrebbe essere meglio creare un HtmlHelper, in questo modo è possibile utilizzare argomenti di tipo generico piuttosto che "MyModel" e "string" come sopra. Quando ho provato l'ultima volta non è stato possibile aggiungere argomenti di tipo generico a un helper in linea, ad es. il seguente non è possibile, a meno che questa funzione non sia stata aggiunta da allora:

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

Quindi, per ottenere il metodo generico, si utilizzerà un HtmlHelper personalizzato. Per fare questo:

  1. Creare un file come il seguente:

    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. Nella tua pagina, l'utilizzo di una cosa del genere sarebbe:

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

ecc. Potrebbe essere necessario controllare gli utilizzi sulla tua pagina o aggiungere lo spazio dei nomi per HtmlHelper in web.config.


Risposta popolare

@ David_001 ha fornito una soluzione MVC molto elegante per questo; Lascio la mia risposta qui in quanto descrive il meccanismo interno e potrebbe essere utile se è necessario risolvere un problema che non è coperto dagli helper MVC out of the box.

Cambiare il tipo di parametro da Func<MyModel, string> a Expression<Func<MyModel, string>> . In questo modo, si riceve un'espressione dinamica nel metodo che è possibile analizzare al posto del delegato statico ricevuto nel modulo corrente.
Puoi recuperare il valore del campo in questo modo:

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

Puoi accedere al membro e ai suoi attributi che vengono restituiti dall'espressione dinamica come questa:

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

L'ho testato all'incirca in un progetto C # (non MVC), quindi non posso dire se funziona su Razor; ma sono sicuro che puoi anche spostare il tuo codice in una classe normale.
Si noti che si perde qualche tipo di sicurezza con questo approccio poiché un chiamante può fornire una varietà di espressioni dinamiche al metodo. Quindi dovresti tenerne conto se analizzi l'espressione per trovare l'attributo.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché