ASP.NET MVC Inline-Helfer für Felder

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

Frage

Ich brauche einen generischen Inline-Helfer, um Felder anzuzeigen.

Hier ist, was ich gerade habe:

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

Verwendung:

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

Ich habe keine Ahnung, wie man Label (DisplayAttribute) innerhalb eines Helfers anzeigt. Bitte helfen Sie.

Akzeptierte Antwort

Fügen Sie oben auf Ihrer Seite eine Verwendung für System.Linq.Expressions hinzu, z.

@using System.Linq.Expressions

(oder fügen Sie diesen Namespace in web.config hinzu).

Um dann den Helfer zu erstellen, würde er ungefähr so ​​aussehen:

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

Sie können zusätzliche Logik hinzufügen, um nach leeren Werten usw. zu suchen. Sie können jedoch besser einen HtmlHelper erstellen, so dass Sie generische Typargumente anstelle von "MyModel" und "string" wie oben verwenden können. Als ich das letzte Mal probiert habe, war es nicht möglich, einem Inline-Helper generische Argumente hinzuzufügen, z. Folgendes ist nicht möglich, es sei denn, diese Funktion wurde seither hinzugefügt:

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

Um die generische Methode zu erhalten, würden Sie einen benutzerdefinierten HtmlHelper verwenden. Um dies zu tun:

  1. Erstellen Sie eine Datei wie die folgende:

    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. In Ihrer Seite wäre die Verwendung einer solchen Sache:

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

usw. Möglicherweise müssen Sie Ihre Verwendung auf Ihrer Seite überprüfen oder den Namespace für den HtmlHelper in web.config hinzufügen.


Beliebte Antwort

@ David_001 hat dafür eine sehr elegante MVC-Lösung bereitgestellt; Ich lasse meine Antwort hier, da sie den inneren Mechanismus beschreibt und hilfreich sein kann, wenn Sie ein Problem lösen müssen, das nicht von den MVC-Out-of-the-Box-Helfern abgedeckt wird.

Ändern Sie den Parametertyp von Func<MyModel, string> in Expression<Func<MyModel, string>> . Auf diese Weise erhalten Sie einen dynamischen Ausdruck in der Methode, die Sie analysieren können, anstelle des statischen Delegaten, den Sie im aktuellen Formular erhalten.
Sie können den Wert des Feldes wie folgt abrufen:

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

Sie können auf das Element und seine Attribute zugreifen, die vom dynamischen Ausdruck wie folgt zurückgegeben werden:

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

Ich habe es grob in einem C # -Projekt (nicht MVC) getestet, also kann ich nicht sagen, ob es in Razor funktioniert; Aber ich bin sicher, dass Sie Ihren Code auch in eine normale Klasse verschieben können.
Bitte beachten Sie, dass Sie bei diesem Ansatz einige Arten von Sicherheit verlieren, da ein Aufrufer der Methode eine Vielzahl von dynamischen Ausdrücken bereitstellen kann. Sie sollten dies also berücksichtigen, wenn Sie den Ausdruck analysieren, um das Attribut zu finden.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum