How to render ModelMetadata object using Html.Displar in Razor-engine in ASP.NET MVC app?

468 Views Asked by At

I am trying to utilize the DisplayTemplates feature in razor-engine to automate rendering my display views.

I scan my Model to find the correct ModelMetadata for each property that I want to display. But I am not able to render the properties using Html.DisplayFor correctly.

I tried to display my property like so

// First I find the ModelMetadata for the property
// I call this statement in a loop and each iteration I pass a different PropertyName to get the correct model
ModelMetadata columnMetadata = elementsMetadata.First(x => x.PropertyName == column.PropertyName);

// I attempted to render the columnMetadata object like so
Html.DisplayFor(x => columnMetadata.Model)

The above code works "in term of displaying the correct value" However it does not use the correct DisplayTemplate which is causing the incorrect format.

For example I have an editor template called Currency.cshtml which simply display Model.ToString("C"). I also have another display template called Status.cshtml which accepts boolean value and return "Active" or "Inactive". Both display-template are located in ~/Views/Shared/DisplayTemplates.

But for some reason Html.DisplayFor() isn't looking for the proper template. Here is an example of one of my view-models

public class ViewModel
{
    public string Name { get; set; }

    [DataType(DataType.Currency)]
    public decimal Rate { get; set; }

    [DataType("Status"), DisplayName("Status")]
    public bool Active { get; set; }
}

Currently my view shows a disabled checkbox for the Active property and a non-formatted number for my Rate property.

How can I correctly display ModelMetadata object where the correct display-template is used based on the property data-type?

1

There are 1 best solutions below

0
On BEST ANSWER

ModelMetadata contains a DataTypeName property, which contains the value generated by the DataTypeAttribute, which will be "Currency" for your Rate property and "Status" for you Status property. You can use this value in the 2nd argument of DisplayFor()

ModelMetadata columnMetadata = elementsMetadata.First(x => x.PropertyName == column.PropertyName);
string template = columnMetadata.DataTypeName;
Html.DisplayFor(x => columnMetadata.Model, template)

Note also that you can use the UIHintAttribute which also sets the value of DataTypeName, for example

[Display(Name = "Status")] // use this rather that [DisplayName]
[UIHint("Status")]
public bool Active { get; set; }