My problem is similar to this question but instead of applying Data Annotations to the property Name via reflection (handled by ModelMetadata.DisplayName) I am applying them to the value (not handled by ModelMetadata).
In the context of an ASP.NET MVC program.
Suppose I have a Model class
public class Model
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string NickName { get; set; }
public string Address { get; set; }
public int Phone { get; set; }
[Display(Name = "Start Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime StartDate { get; set }
[Display(Name = "End Date")]
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime EndDate { get; set }
}
Then suppose this Model is used in at least 5 different views where the value of every property must be displayed in full. (Sometimes for every instance, other times for a handful, other times for one).
I can manually list each Property access within it's own<td>@Html.DisplayFor(item.<Property>)</td>
for every view.
But that won't help me if later on the definition for Model expands to include new Properties (like Description and Relation and Reliability). Then I'd need to manually update every occurrence of the complete Model listing.
I can use reflection to iterate over a list of PropertyInfo's and save having to manually list each property by using<td>@property.GetValue(item)</td>
But DisplayFor(x)
does not support an expression as complex as x=>property.GetValue(item)
, and this means I lose the Data Annotations that format my DateTime as01/01/1990
instead of01-Jan-90 12:00:00 AM
and would likely also result in the loss of all types of annotation including validation.
So far I have considered (and in some cases attempted) the following solutions:
@property.GetValue(item)
DisplayFor(x => property.GetGetMethod())
as well as .Invoke
ing it on x.This last solution would turn the broken@Html.DisplayFor(m=>property.GetValue(item)
into a theoretically working@Html.DisplayFor(m=>item.Properties[i].Value)
Which aside from the slightly unintuitive need for getting a property called Name (Properties["Name"]) by (.Value), seems the most workable solution, at the cost of Model clarity.
[Edit]
Most recently I have created a Utility method which retrieves the DisplayFormatAttribute from the PropertyInfo and returns either the DisplayFormatString or the default of "{0}" if a format string was not annotated. I have then used it to create a collection of preformatted property values within a ViewModel.
This seems for now, to be the most elegant way I know of to decouple the View from the Model as much as possible while still retrieving the necessary data from it.
[/Edit]
This is at the moment, purely a learning exercise, but I would like to know...
Is it possible to succeed where I have failed and both have my Reflection cake and eat the Data Annotations too? Or must I seek an alternative solution?
If I must seek an alternative solution, are there routes I have missed, or am I at least on the right track?
Maybe something similar to:
@foreach (var property in Model.GetType().GetProperties())
{
<li>@property.GetValue(Model, null)</li>
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With