Html.DisplayNameFor() using dynamically calculated properties

Viewed 187

I have a class object with more than 30 properties

public class Person
{
    [Display(Name = "A")]
    public string PropertyA { get; set; }
    
    [Display(Name = "B")]
    public string PropertyB { get; set; }

    [Display(Name = "C")]
    public string PropertyC { get; set; }
    ... 
    ...
    [Display(Name = "Z")]
    public string PropertyZ { get; set; }
}

In my view file, I am iterating through the properties dynamically:

@model Person

<div>
   @foreach(var prop in Model.GetType().GetProperties())
   {
      // logic to decide if the property should be
       // included in the output or not
      <div>@prop.Name</div>
   }
</div>

This will list all of the properties, with each property in its own div. What I need to do is output the Display of each property. Something like javascript way of addressing an object's properties by []. I.E:

      <div>@Html.DisplayNameFor(m => m[prop.Name])</div>     //does not work

This is what I tried:

   @foreach(var prop in Model.GetType().GetProperties())
   {

      <div>@Html.DisplayNameFor(prop.Name)</div>             //does not work

   }

My goal is to later filter out properties that are not required in the view, without having to manually edit the view when I decide to alter the class (by adding or removing properties).

1 Answers

Use LINQ to identify an object that contains the Display attribute and select the Name argument value:

@foreach (var prop in Model.GetType().GetProperties())
{
    // TODO: logic to decide if the property should be included in the output or not

    foreach (var ca in prop.CustomAttributes)
    {               
        var name = ca.NamedArguments.Where(t => t.MemberName.Equals("Name")).Select(x => x.TypedValue.Value).FirstOrDefault().ToString();
        <div>@Html.DisplayName(name)</div>
    }
}
Related