Using model property of type IEnumerable<T> for table column headers in ASP.NET MVC
I have paged results class that I am using to display paged data to users. I had problem with getting names of returned result properties to table headers in views. It works automatically if model implements IEnumerable<T> but not if your IEnumerable<T> is property of model. Here is the solution I found from Stack Overflow with little improvement.
Problem
Here is my paged result class:
public class PagedResult<T>
{
public IList<T> Results { get; set; }
public int CurrentPage { get; set; }
public int PageCount { get; set; }
public int PageSize { get; set; }
public int RowCount { get; set; }
public T Type { get { return default(T); } }
public PagedResult()
{
Results = new List<T>();
}
}
You can find my paged result class and examples about how to use it from my posting Returning paged results from repositories using PagedResult.
When I try to use results collection this way:
<tr>
<th>
@Html.DisplayFor(model => model.Results.Name)
</th>
<th></th>
</tr>
I get the following error:
CS0411: The type arguments for method ‘System.Web.Mvc.Html.DisplayExtensions.DisplayFor<TModel,TValue>(System.Web.Mvc.HtmlHelper<TModel>, System.Linq.Expressions.Expression<System.Func<TModel,TValue>>, object)’ cannot be inferred from the usage. Try specifying the type arguments explicitly.
Out-of-box DisplayFor<T> is not able to understand what is going on.
Solution
I found solution from Stack Overflow thread @Html.DisplayNameFor for details model. I added fallback from empty display name to original property name and here is the code:
public static MvcHtmlString DisplayColumnNameFor<TModel, TClass, TProperty>(this HtmlHelper<TModel> helper, IEnumerable<TClass> model, Expression<Func<TClass, TProperty>> expression)
{
var name = ExpressionHelper.GetExpressionText(expression);
name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
var metadata = ModelMetadataProviders.Current.GetMetadataForProperty(
() => Activator.CreateInstance<TClass>(), typeof(TClass), name);
var returnName = metadata.DisplayName;
if (string.IsNullOrEmpty(returnName))
returnName = metadata.PropertyName;
return new MvcHtmlString(returnName);
}
Just add this extension method to some static class and call it like I do:
<tr>
<th>
@Html.DisplayColumnNameFor(Model.Results, model => model.Name)
</th>
<th></th>
</tr>
I hope this method finds in future its way to ASP.NET MVC code too.
I solved that problem by using a special setting for JsonSerializerSettings which is called TypeNameHandling.
Can you explain more about how you exactly did it?