I have a project written in C#
on the top on ASP.NET MVC 5 framework. I am trying to decouple my views from my view model so I can make my views reusable. With the heavy use of EditorTemplates
I am able to create all of my standard views (i.e create, edit and details) by evaluating the ModelMetadata
and the data-annotation-attributes for each property on the model, then render the page. The only thing that I am puzzled with is how to render the Index
view.
My index view typically accepts an IEnumerable<object>
or IPagedList<object>
collection. In my view, I want to be able to evaluate the ModelMetadata of a each object
/record in the collection to determine if a property on the object
should be displayed or not.
In another words my view-model will look something like this
public class DisplayPersonViewModel
{
public int Id{ get; set; }
[ShowOnIndexView]
public string FirstName { get; set; }
[ShowOnIndexView]
public string LastName { get; set; }
[ShowOnIndexView]
public int? Age { get; set; }
public string Gender { get; set; }
}
Then my Index.cshtml
view will accepts IPagedList<DisplayPersonViewModel>
for each record in the collection, I want to display the value of the property that is decorated with ShowOnIndexView
attribute.
Typically I would be able to do that my evaluating the ModelMetadata in my view with something like this
@model IPagedList<object>
@{
var elements = ViewData.ModelMetadata.Properties.Where(metadata => !metadata.IsComplexType && !ViewData.TemplateInfo.Visited(metadata))
.OrderBy(x => x.Order)
.ToList();
}
<tr>
@foreach(var element in elements)
{
var onIndex = element.ContainerType.GetProperty(element.PropertyName)
.GetCustomAttributes(typeof(ShowOnIndexView), true)
.Select(x => x as ShowOnIndexView)
.FirstOrDefault(x => x != null);
if(onIndex == null)
{
continue;
}
@Html.Editor(element.PropertyName, "ReadOnly")
}
</tr>
Then my controller will look something like this
public class PersonController : Controller
{
public ActionResult Index()
{
// This would be a call to a service to give me a collection with items. but I am but showing the I would pass a collection to my view
var viewModel = new List<DisplayPersonViewModel>();
return View(viewModel);
}
}
However the problem with evaluating ModelMetadata
for the IPagedList<DisplayPersonViewModel>
is that it gives me information about the collection itself not about the generic type or the single model in the collection. In another words, I get info like, total-pages, items-per-page, total-records....
Question
How can I access the ModelMetadata
info for each row in the collection to be able to know which property to display and which not to?