30

I have an editor template and within that editor template i want to call another editor template with the same model (i.e. nested), but it does not seem to display.
ie. \EditorTemplates\Template1.cshtml

@model foo

// insert code here to edit the default fields.

// display extra fields via another editor template.
@Html.EditorForModel("Template2")   // or @Html.EditorFor(m => m, "Template2")

and \EditorTemplates\Template2.cshtml

@model foo

@Html.TextBoxFor(m => m.Name)

I am sure someone will question why? Well, the nested template will only be displayed if a condition is met (ie. @if (@Model.IsConditionMet) { .... } ), but I have left that out of my prototype for simplicity.

Simon Halsey
  • 5,459
  • 1
  • 21
  • 32
tkerwood
  • 1,875
  • 16
  • 26
  • I'm trying to do something similar, but to no avail. Any luck since you wrote this? – kdawg Nov 08 '11 at 22:03
  • Actually, follow-up info: I'm trying to do this in conjunction with Telerik's MVC grid control. This may have something to do with it too. – kdawg Nov 08 '11 at 22:10
  • @kdawg - No, no luck sorry. I have moved onto JQuery templates and Knockoutjs. – tkerwood Nov 09 '11 at 01:27
  • Hah! I'm using knockout.js in the wizard control that has said Telerik grid control. Love that library. Thanks for the response. – kdawg Nov 09 '11 at 19:47
  • related/duplicate: http://stackoverflow.com/questions/12192225/asp-net-mvc-editor-template-for-property/12231656#12231656 – Goran Obradovic Sep 06 '12 at 05:56

1 Answers1

59

Short answer:

Use Html.Partial instead.

So, in your Template1.cshtml file:

@model foo

// insert code here to edit the default fields.

// display extra fields via another editor template.
@Html.Partial("EditorTemplates/Template2", Model)

Long answer:

This sadly appears to be by-design. MVC tracks the models that have been rendered, and if your model has already been rendered by a template, it won't do it twice, even if the template is different. Hence why the second @Html.EditorForModel("Template2") just does nothing.

Specifically, it's tracked in ViewData.TemplateInfo.VisitedObjects, which is an internal field, so there's no hope in you modifying it after the fact. The intention of this field is to prevent infinite recursion. Noble, but annoying in that it doesn't take the template used into account.

I found this out by looking at the source code, which is great for finding these weird idiosyncrasies of MVC.

Ber'Zophus
  • 7,497
  • 3
  • 22
  • 22