Collections and ASP.NET MVC Templated Helpers – Part 4

This is part of a mini-series:

  • Part 1 – Define the problem & give a workaround
  • Part 2 – Show an alternative workaround
  • Part 3 – Show a reusable, simple solution
  • Part 4 – Replacing Object.ascx

My last post showed how to implement a custom model metadata provider that fibs to ASP.NET MVC that a complex property on a model is a simple property based if it has an attribute that provides a rendering for it. This all started because ASP.NET MVC’s Templated Helpers don’t render properties that are complex types – an issue that I’ve bumped into a few times recently. I’ve presented a number of options for tackling this limitation in this set of posts, but one option that I hadn’t covered was providing a replacement Object.ascx. Fortunately ulu pulled me up on this in the comments on the last post :-).

For a given model type, ASP.NET MVC will try to locate a number of different views until it finds one to use. Brad Wilson has a great post on this which is worth reading if you aren’t already familiar with the process as I will be referring to it in this post.

In the scenario that I’ve been using we have a class Foo that has a property List<Bar> Bars. We are using the templated helpers to render an instance of Foo to display. In the second post I showed that we can create a Foo.ascx that will override the default behaviour because a view that matches the type name will be used before the default behaviour. Up until this point we haven’t really looked at where the default implementation comes from. Looking at the list in Brad’s post, you can see that the default behaviour comes from the object template. The implementation of this is in the ASP.NET MVC code rather than in a file, but the good news is that ASP.NET MVC will look for Object.ascx and use that in preference to the code based template. Brad’s post contains example implementations for Object.ascx – scroll down to DisplayTemplates/Object.ascx and EditorTemplates/Object.ascx.

You can think of providing an updated Object.ascx as a generalised version of the approach in my second post. If you go down this route then watch out for circular references on your model objects as this will cause a stack overflow if you remove the TemplateDepth check! In general I’d advise against circular references on your model, but a recent customer scenario had them so I thought it was worth pointing out!

By the way, if you take a look at the code for the object template (in the ObjectTemplate method on System.Web.Mvc.Html.DefaultEditorTemplates if you’re interested) you will see that it contains a check on the TemplateDepth property and limits the output based on this. You can download the source code on the ASP.NET MVC download page.

I’m aware that there may be other ways to tackle this problem (so feel free to comment). I guess this highlights on of the things I like about ASP.NET MVC: the range of extensibility points mean that you generally have several options for tackling a problem.