Reputation: 1
I have a really strange situation. I have a single Model, and two templates that are both strong-typed on the type of this model. The templates are nested, or in other words, I use DisplayFor on the second Template from within the first template. If I use the model associated with the first template, in the DisplayFor call for the second template, the second template does not render. If I use another instance of the same model type, everything works fine. It seems like there is some sort of cycle checking on the models associated with nested templates.
Model:
public class MyModel
{
public string Value { get; set; }
public MyModel Copy
{
get { return (MyModel) this.MemberwiseClone(); }
}
public MyModel MySelf
{
get { return this; }
}
}
DisplayTemplate1:
@model TestNestedTemplateSameReference.Models.MyModel
<div>Model1</div>
<div>@Model.Value</div>
<div>@Html.DisplayFor(x=>x, "ModelTemplate2")</div>
DisplayTemplate2:
@model TestNestedTemplateSameReference.Models.MyModel
<div>Model2</div>
<div>@Model.Value</div>
Interestingly if instead of calling
@Html.DisplayFor(x=>x, "ModelTemplate2")
I call it with the Copy property
<div>@Html.DisplayFor(x=>x.Copy, "ModelTemplate2")</div>
everything works fine as the actual instance of the MyModel class is different.
Does anyone know why this is done. Is there a viable workaround. It seems like this is a perfectly legitimate usage which shouldnot cause a stack overflow, or any similar issues. I could see how this could be used to protect against cycles for DisplayFor call without template name, but if I specify the template name seems like it should work fine.
It seems like it would be dangerous to bind the same model to multiple EditFor templates, but DisplayFor seems safe.
I can of course create a separate model for nesting level, but that is creating redundand class.
Any help is appreciated.
Upvotes: 0
Views: 463
Reputation: 93424
If what you were trying to do worked, it would result in a stack overflow as object after object was created via the Copy method. Each object would in turn create a new copy of itself, and you would quickly either run out of memory or run out of stack.
The default template executes this method before showing a property
bool ShouldShow(ModelMetadata metadata) {
return metadata.ShowForEdit
&& metadata.ModelType != typeof(System.Data.EntityState)
&& !metadata.IsComplexType
&& !ViewData.TemplateInfo.Visited(metadata);
}
My guess is that it's tripping either IsComplexType or TemplateInfo.Visited.
There's more info on this here:
http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-3-default-templates.html
Upvotes: 1