Tuesday, February 09, 2010 5:06 AM Kazi Manzur Rashid

ASP.NET MVC Complex Object ModelMetaData Issue

One of the exciting feature of ASP.NET MVC is(?) auto generating the view of the model with DisplayForModel/EditorForModel statement, it gives a nice extension point for the application developers to customize the view. But in the latest release (MVC2 RC2), it looks like the feature is no longer available. No, those methods are still available, but they are not working the same way as they were doing in the earlier versions. In rc2, if your model has any complex object, it will not render it . I know some of you like myself thought, one of the major changes in rc2 is the Input Validation vs. Model Validation in ASP.NET MVC and rest of it is bug fixing and some improvements. I did check the release note doc, where it is mentioned as

Templated helpers such as Html.EditorFor and Html.DisplayFor show only simple properties by default. If you need to show complex properties, you can create a custom template to show any set of properties.

Check the last line, it says to show the complex properties we have to create a custom template. But interestingly enough it does not work. Let me show you a very simple example, lets say that we have product and category class like the following:

public class Category
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set; }

    [UIHint("CategoryTemplate")]
    public Category Category { get; set; }
}

Check that we are using a custom template (CategoryTemplate) to show the category property.

And in the Controller:

public ActionResult Index()
{
    return View(new Product
                 {
                     Id = 1,
                     Name = "Product 1",
                     Price = 10.0m,
                     Category = new Category { Id = 2, Name = "Category 2" }
                 });
}

And in the View we want to render the product:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ComplexObject.Models.Product>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <p>
        <%= Html.DisplayForModel() %>
    </p>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
    </p>
</asp:Content>

But when the view is rendered, there is no category:

CO1

I posted this issue in the Gu’s RC2 announcement post as well as in the CodePlex, but the answer that I got is somewhat confusing. I do not think this is a right decision to hide the complex object in the default implementation, I never hard anybody is having some issues with this features and I do not think it is the right time for this change as the MVC2 is in in RC, anyway feature is broken and needs to be resolved in the first place.

So, till there is a fix, what is the workaround? Lets write some Haacky code. First, lets see where the ASP.NET MVC take the decision to show/hide the model property. If you open the DefaultDisplayTemplates.cs and DefaultEditorTemplates.cs under the Html folder of the ASP.NET MVC Source code, you will find both of it has a method called ShouldShow.

private static bool ShouldShow(ModelMetadata metadata, TemplateInfo templateInfo)
{
    return
        metadata.ShowForEdit
        && metadata.ModelType != typeof (EntityState)
        && !metadata.IsComplexType
        && !templateInfo.Visited(metadata);
}

The only problematic checking is the IsComplexType which in turns check whether the type can be converted from the string type :

public virtual bool IsComplexType
{
    get { return !(TypeDescriptor.GetConverter(ModelType).CanConvertFrom(typeof (string))); }
}

So the workaround is either we override the ModelMetadata which is somewhat an overkill or we can create a TypeConverter for the complex object for which we have custom template to fool the ASP.NET MVC Framework. In this case it is the Category. So lets write a converter.

public class CategoryConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        return sourceType == typeof(string) ? true : base.CanConvertFrom(context, sourceType);
    }
}

Now, decorate the Category with this converter:

[TypeConverter(typeof(CategoryConverter))]
public class Category
{
    public int Id { get; set; }

    public string Name { get; set; }
}

when you run the project you will find the category is shown like the following:

CO2

And that’s it. You can download the complete code from the following link.

Source Code: ComplexObject.zip

Shout it
Filed under: , , ,

Comments

# Twitter Trackbacks for ASP.NET MVC Complex Object ModelMetaData Issue - Kazi Manzur Rashid's Blog [asp.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 ASP.NET MVC Complex Object ModelMetaData Issue - Kazi Manzur Rashid's Blog         [asp.net]        on Topsy.com

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Monday, February 08, 2010 7:59 PM by Martin Aatmaa

Hi Kazi,

Thank you for posting the details on this.

Are there any negative consequences of attributing your Category class with the custom TypeConverter (CategoryConverter)?

# ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 09, 2010 12:03 AM by DotNetShoutout

Thank you for submitting this cool story - Trackback from DotNetShoutout

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 09, 2010 1:26 AM by msony

Yeah, i got this as well, thats why i needed to use my own template instead of EditorForModel

# ASP.NET MVC Complex Object ModelMetaData Issue - Kazi Manzur &#8230;

Pingback from  ASP.NET MVC Complex Object ModelMetaData Issue - Kazi Manzur &#8230;

# ASP.NET MVC Complex Object ModelMetaData Issue - Kazi Manzur &#8230; &laquo; Internet Cafe Solution

Pingback from  ASP.NET MVC Complex Object ModelMetaData Issue - Kazi Manzur &#8230; &laquo;  Internet Cafe Solution

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 09, 2010 11:11 AM by bradwils

The documentation is correct. You made the custom template for the wrong object. :) You need to make a custom template for Product, because it's Product that has the thing inside of it that normally wouldn't be shown.

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 09, 2010 12:20 PM by Eric

Can you give an example of where this would be used?

I can't see how dumping a raw C# business object to a page would ever be useful in a web application outside of maybe debugging?

# Best Running Tips Newsletter, Issue #019 &#8212; About Safety and the &#8230; | Running Leisure Knowledge

Pingback from  Best Running Tips Newsletter, Issue #019 &#8212; About Safety and the &#8230; | Running Leisure Knowledge

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 09, 2010 2:23 PM by Arnis L.

Isn't it easier to flatten your viewmodel?

# Distracted Driving on the Rise in West Virginia | Shapiro, Cooper &#8230; | Educational West Virginia

Pingback from  Distracted Driving on the Rise in West Virginia | Shapiro, Cooper &#8230; | Educational West Virginia

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 09, 2010 7:30 PM by Kazi Manzur Rashid

@Arnis L: Flattern does not help in complex view, for ex try to create an order entry form of Northwind database.

If you have hierarchical object model you can have to create template for the root object and as per the mvc team the child cannot have its own template which is some what unacceptable.

# Social comments and analytics for this post

Wednesday, February 10, 2010 5:30 AM by uberVU - social comments

This post was mentioned on Twitter by jrguay: #ASPNET #Weblog: ASP.NET MVC Complex Object ModelMetaData Issue: One of the exciting feature of ASP.NET MVC is(?) ... http://bit.ly/c5gBOv

# ASP.NET MVC Complex Object ModelMetaData Issue &#8211; Kazi Manzur &#8230; | Drakz Free Online Service

Pingback from  ASP.NET MVC Complex Object ModelMetaData Issue &#8211; Kazi Manzur &#8230; | Drakz Free Online Service

# STIRA Technologies requires SharePoint, C#, ASP.Net, SQL Server &#8230; | ASP WebDev Insider

Pingback from  STIRA Technologies requires SharePoint, C#, ASP.Net, SQL Server &#8230; | ASP WebDev Insider

# ASP.NET MVC Complex Object ModelMetaData Issue | 007Nova Articles

Pingback from  ASP.NET MVC Complex Object ModelMetaData Issue | 007Nova Articles

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Tuesday, February 16, 2010 10:41 AM by felipe_csl

Thanks for sharing. I agree that it is an error to ignore complex objects in the default EditorForModel implementation.

Felipe

# re: ASP.NET MVC Complex Object ModelMetaData Issue

Monday, February 22, 2010 5:36 AM by ahsanm.m

thanks for sharing, Would you please give me a guide line to understand it clearly.

I am newbie in MVC architecture.

Thanks

# MVC 2 EditorForModel and DropDownList

Monday, June 28, 2010 3:44 PM by Lazy Bones

MVC 2 EditorForModel and DropDownList