EditorHelper是否使用ViewBag将数据传递到相应的模板?

And*_*i V 6 c# asp.net-mvc templates razor

我在覆盖Object.cshtm模板时发现了一种奇怪的行为.该Object.cshtm迭代的Model特性和"发送"他们合适的模板进行渲染.

foreach (var prop in ViewData.ModelMetadata.Properties)        
{
    @Html.Editor(prop.PropertyName, 
          "MyCustomTemplateCollection" + prop.TemplateHint) 
    //TemplateHint set by custom attributes
}
Run Code Online (Sandbox Code Playgroud)

一切运作良好:模板切换到适当的类型模板,在我可以访问Metadata属性的内部:

string name = ViewData.ModelMetadata.PropertyName;
string controllerName = ViewData.ModelMetadata.ContainerType.Name;

//render property accordingly (using the property information)
Run Code Online (Sandbox Code Playgroud)

但是,如果由于某种原因ViewBag包含与其中一个属性同名的(动态)Model属性,ModelMetadata则不会完全生成; 至少上述ModelMetadata属性设置为null.例如,如果在我设置的控制器中ViewBag.ProductName = myModel.ProductName;,当ProductName属性进入其相应的模板时,元数据不包含"预期"值.

解决方案很简单:如果,不管出于什么原因,物业需要保存的ViewBag,它必须以不同的名称保存.

我的问题是:如何EditorHelper将数据传递给模板?我不希望这样,ViewDataViewBag"分享"这些信息.与检查快速监视我可以看到在Non-Public members中的ViewBag一个ViewData这似乎是一样的性质,可以说,一般可用ViewData对象.为什么不完全独立?

Ant*_*t P 1

你的问题有一个非常简单的答案:

ViewBag是 的动态包装器ViewData。它们实际上是同一件事。你放入的任何东西ViewData也会放入ViewBag,反之亦然。

您可以在此处查看 的实现DynamicViewDataDictionary(这是其ViewBag实例)。正如您所看到的,它只是保存对其包装的内部引用并将属性访问委托给字典元素。ViewDataDictionary

因此,当框架传递ViewData到具有特定键的模板并且您分配ViewBag具有匹配名称的属性时,只有一个可以获胜。

硬币的另一面 - 我认为实际上更相关 - 是负责ModelMetadata提供元数据检查的静态方法ViewData 首先检查 - 在检查模型对象的元数据之前。

因此,如果您将属性分配给ViewBag(并且 - 通过关联 - ViewData),这些属性将与您传递给模板的表达式相匹配,并且这些属性不会具有某些元数据,例如模型类上的数据注释提供的元数据。