我在覆盖 Object.cshtm
模板时观察到一些奇怪的行为。 Object.cshtm
迭代 Model
属性并将它们“发送”到适当的模板进行呈现。
foreach (var prop in ViewData.ModelMetadata.Properties)
{
@Html.Editor(prop.PropertyName,
"MyCustomTemplateCollection" + prop.TemplateHint)
//TemplateHint set by custom attributes
}
一切正常:模板切换到适当的类型模板,在我可以访问的模板中 Metadata
属性:
string name = ViewData.ModelMetadata.PropertyName;
string controllerName = ViewData.ModelMetadata.ContainerType.Name;
//render property accordingly (using the property information)
但是,如果由于某种原因 ViewBag
包含一个与 Model
属性之一同名的(动态)属性,则 ModelMetadata
未完全生成;至少上述 ModelMetadata
属性设置为 null
。例如,如果在我的 Controller 中我设置了 ViewBag.ProductName = myModel.ProductName;
,当 ProductName
属性进入其对应的模板时,元数据不包含“预期的” "值(value)观。
解决方案非常简单:如果出于某种原因,属性需要保存在ViewBag
中,则必须以不同的名称保存。
我的问题是:EditorHelper
如何将数据传递给模板?我不希望 ViewData
和 ViewBag
“共享”此类信息。使用 QuickWatch 检查我可以在 ViewBag
的 Non-Public members
中看到一个 ViewData
属性,它似乎是与一般可用的 ViewData
对象相同。为什么不完全独立?
最佳答案
您的问题有一个非常简单的答案:
ViewBag
是 ViewData
的动态包装器。它们实际上是同一件事。您放入 ViewData
中的所有内容也会放入 ViewBag
中,反之亦然。
您可以看到DynamicViewDataDictionary
的实现(ViewBag
是它的一个实例)here .如您所见,它只是持有对其包装的 ViewDataDictionary
的内部引用,并将属性访问委托(delegate)给字典元素。
因此,当框架将 ViewData
传递到具有特定键的模板中并且您分配具有匹配名称的 ViewBag
属性时,只有一个可以获胜。
硬币的另一面 - 我认为实际上更相关 - 是负责提供元数据检查的静态 ModelMetadata
方法首先检查 ViewData
- 在检查模型对象的元数据之前。
因此,如果您将属性分配给 ViewBag
(以及 - 通过关联 - ViewData
),这些属性将与您传递给模板的表达式相匹配并且这些不会有某些元数据,例如模型类上的数据注释提供的元数据。
关于c# - EditorHelper 是否使用 ViewBag 将数据传递给相应的模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20514573/