Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does EditorHelper use ViewBag to pass data to corresponding template?

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?

like image 438
Andrei V Avatar asked Dec 11 '13 08:12

Andrei V


People also ask

What is the use of ViewBag in MVC?

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).

Can we use ViewBag to pass data from view to controller?

Yes you cannot pass a Viewbag from view to controller. But you can pass them using TempData.

How do you pass data using ViewBag?

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.

What is the difference between ViewBag and ViewData in MVC?

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.


1 Answers

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.

like image 94
Ant P Avatar answered Nov 07 '22 01:11

Ant P