I observed a somewhat peculiar behavior when overwriting the Object.cshtm template. The Object.cshtm iterates the Model properties and "sends" them to the appropriate template for rendering.
foreach (var prop in ViewData.ModelMetadata.Properties)
{
@Html.Editor(prop.PropertyName,
"MyCustomTemplateCollection" + prop.TemplateHint)
//TemplateHint set by custom attributes
}
Everything works well: the template switches to the appropriate type template and inside those I can access Metadata properties:
string name = ViewData.ModelMetadata.PropertyName;
string controllerName = ViewData.ModelMetadata.ContainerType.Name;
//render property accordingly (using the property information)
However, if for some reason the ViewBag contains a (dynamic) property with the same name as one of the Model properties, the ModelMetadata is not completely generated; at least the ModelMetadata properties described above are set to null. For example, if in my controller I set ViewBag.ProductName = myModel.ProductName;, when the ProductName property gets in its corresponding template, the metadata does not contain the "expected" values.
The solution is quite simple: if, for whatever reason, the property needs to be saved in the ViewBag, it must be saved under a different name.
My question is: how does the EditorHelper pass the data to the templates? I wouldn't expect that ViewData and ViewBag "share" such information. Inspecting with QuickWatch I can see in the Non-Public membersof the ViewBag a ViewData property which appears to be the same as the, lets say, generally available ViewData object. Why aren't the completely independent?