ASP.Net MVC: Html.Display() for object in a Collection

16,078

Have a look at the template code in this excellent post from Phil Haack. It seems to come close to what you are looking for: http://haacked.com/archive/2010/05/05/asp-net-mvc-tabular-display-template.aspx

Share:
16,078
Chris Moschini
Author by

Chris Moschini

I'm a Web Consultant, and I build Web Applications. My technology expertise revolves around: jQuery/Javascript, CSS, ASP.Net MVC/C#, and EF Code First/LINQ. I'm competent in other languages like SQL, Java, and VB. You can email me at my first name at my company website.

Updated on August 15, 2022

Comments

  • Chris Moschini
    Chris Moschini almost 2 years

    The standard MVC example to draw an item with the appropriate View Template is:

    Html.DisplayFor(m => m.Date)

    If the Model object has a property named Date of type DateTime, this returns a string with the HTML from the Display/DateTime.ascx template.

    Suppose you wanted to do the same thing, but couldn't use the strongly-typed version - you didn't know the Model's type for this View at compile time. You use the older:

    Html.Display("Date");

    So here's the hard part.

    Suppose the Model is IEnumerable. You don't know what those objects are at compile-time, but at run-time they happen to be objects with a Date of type DateTime again, like:

    public class ModelClass
    {
        public DateTime Date { get; set; }
    }
    

    Now suppose you want your View to iterate over those objects and render each out. If all you cared about was the value you could do this:

    <%
    StringBuilder sb = new StringBuilder();
    foreach(object obj in (IEnumerable<object>)Model)
    {
        Type type = obj.GetType();
    
        foreach(PropertyInfo prop in type.GetProperties())
        {
            // TODO: Draw the appropriate Display PartialView/Template instead
            sb.AppendLine(prop.GetValue(obj, null).ToString());
        }
    }
    %>
    <%= sb.ToString() %>
    

    I'm obviously taking some shortcuts to keep this example focused.

    Here's the point - how do I fulfill that TODO I've written for myself? I don't just want to get the value - I want to get it nicely formatted like Html.Display("Date"). But if I just call Html.Display("Date"), it inspects the Model, which is an IEnumerable, for a property named Date, which it of course does not have. Html.Display doesn't take an object as an argument to use as the Model (like Html.Display(obj, "Date"), and all the classes and methods I can find that lie underneath appear to be internal so I can't tweak and call into them directly.

    There must be some simple way to accomplish what I'm trying to do, but I can't seem to find it.

    Just to make sure I'm being clear - here's an example of the code of DateTime.ascx:

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime>" %>
    <%= Model.ToString("MM/dd/yyyy") %>
    

    And so, ideally, the output from this View that can take any Model, but in this case a list of 3 of these ModelClass objects above, would be:

    11/10/2001 11/10/2002 11/10/2003

    Because the code would find the Display PartialView for DateTime and render it appropriately for each.

    So - how do I fulfill the TODO?