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 members
of 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?
In general, ViewBag is a way to pass data from the controller to the view. It is a type object and is a dynamic property under the controller base class. Compared to ViewData, it works similarly but is known to be a bit slower and was introduced in ASP.NET MVC 3.0 (ViewData was introduced in MVC 1.0).
Yes you cannot pass a Viewbag from view to controller. But you can pass them using TempData.
To pass the strongly typed data from Controller to View using ViewBag, we have to make a model class then populate its properties with some data and then pass that data to ViewBag with the help of a property. And then in the View, we can access the data of model class by using ViewBag with the pre-defined property.
ViewData is a dictionary of objects that is derived from ViewDataDictionary class and accessible using strings as keys. ViewBag is a dynamic property that takes advantage of the new dynamic features in C# 4.0. ViewData requires typecasting for complex data type and check for null values to avoid error.
There is a very simple answer to your question:
ViewBag
is a dynamic wrapper for ViewData
. They are effectively the same thing. Anything you put into ViewData
is also in ViewBag
and vice versa.
You can see the implementation of DynamicViewDataDictionary
(which is what ViewBag
is an instance of) here. As you can see, it simply holds an internal reference to the ViewDataDictionary
that it wraps and delegates property access to dictionary elements.
So, when the framework passes ViewData
into a template with a specific key and you assign a ViewBag
property with a matching name, only one can win.
The other side of the coin - which I think is actually more relevant - is the fact that the static ModelMetadata
methods responsible for providing metadata check ViewData
first - before examining the metadata of the model object.
So, if you assign properties to ViewBag
(and - by association - ViewData
), these are the properties that will be matched to the expression you passed to the template and these won't have certain metadata such as that provided by data annotations on the model class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With