Comparison between ViewBag and ViewData? [duplicate] - asp.net

This question already has answers here:
What's the difference between ViewData and ViewBag?
(17 answers)
Closed 7 years ago.
Which is better to bring data from controller to view in .net MVC amongst ViewBag and ViewData ?

Both the ViewData and ViewBag objects are great for accessing data between the controller and view.
The ViewBag objects lets you add dynamic properties to it which makes it a very verstile tool.So dynamic object, meaning you can add properties to it in the controller.It achieves the same goal as ViewData and should be avoided in favour of using strongly typed view models.

ViewBag is a dynamic wrapper around ViewData.
So with ViewData you can do
ViewData["MyData"] = "Hello World"
You can achieve the same result using
ViewBag.MyData = "Hello World"
Since ViewBag is dynamic, you can access properties that may not actually exist e.g. ViewBag.NothingToSeeHere and the code will still compile. It may hit an exception when you run that line of code, but the property is not resolved until runtime.
More information can be found here
How ViewBag in ASP.NET MVC works

As Jason mentioned, "ViewBag is a dynamic wrapper around ViewData".
For the most part, there isn’t a real technical advantage to choosing one syntax over the other.ViewBag is just syntactic sugar that some people prefer over the dictionary syntax. Although there might not be a technical advantage to choosing one format over the other, there are some critical differences to be aware of between the two syntaxes.
One obvious difference is that ViewBag works only when the key being accessed is a valid C# identifi er. For example, if you place a value in ViewData["Key With Spaces"], you can’t access that value using ViewBag because the code won’t compile.
Another key issue to be aware of is that dynamic values cannot be passed in as parameters to extension methods. The C# compiler must know the real type of every parameter at compile time in order for it to choose the correct extension method.
If any parameter is dynamic, compilation will fail. For example, this code will
always fail: #Html.TextBox("name", ViewBag.Name). To work around this, either use ViewData["Name"] or cast the value to a specifi c type: (string) ViewBag.Name.

Related

Enum naming to avoid name clashes

I'm trying to standardise the way I name things, but as a newbie I always seem to come up with an issue somewhere further down the line.
Case in point - I have a user control and enum that clash. The UC is very specific and contains a form dropdownlist/validation for customer input - the name relates to the type of input so the class is named EmploymentStatus.
However, the dropdownlist is populated via an enum - ideally this would be called EmploymentStatus too as I've adopted the recommended singular form for enums.
No doubt everyone has come across this issue at some point, but what is a good solution?
I think namespaces would be the way to go here. Just put the enum in a separate namespace then refer to fully qualified e.g.
MyCompany.MyApplication.AnotherNamespacePart.EmploymentStatus
If this is a bit verbose then you can use namespace aliases to make things a bit more readable.
using myEnum = MyCompany.MyApplication.AnotherNamespacePart;
... some code
myEnum.EmploymentStatus
Please note I've assumed C# here but the principle will hold for other asp.net languages
In my humble opinion and all that

What are the downsides of "typing" your control state?

I am relatively new to Web Parts and Web Forms (I have only worked a lot with the MVC framework).
I am planning to store some data in the control state. All the examples I can find put an object[] array in the control state and the base control state on the 0 index.
I don't really like putting everything in an object[], so I wanted to create an extra class for my web part with typed properties: e.g. MyWebPartControlState. I will store the base control state in a property BaseControlState of type object.
I was wondering if this could cause any problems or if there are any other reasons why this might not be a good idea. I am wondering because it feels logical to me, but I cannot find any examples of control state where they don't put everything in the control state directly or in a object[].
Thanks in advance.
The control state is persisted in the same field as view state and follows the same rules for serialization. All the samples you found use an object array because that's one of the types the optimized state serializer in ASP.NET understands and for which is able to optimize serialization.
If you use a custom object the serializer won't use the optimizations and instead will serialize your object using the BinaryFormatter which will lead to bloated control state. If you want to have a strongly typed view of your state you should implement IStateManager on your custom class so that it encapsulates the transformation of itself from and to simple objects that the serializer understands.
If I recall correctly the serializer can efficiently serialize the following types:
Primitive types (int, long, etc);
DateTime;
string;
Boxed values of supported value types;
Object arrays containing instances of supported types;
Pair and Triplet objects containing instances of supported types.
I wrote a short blogpost illustrating the differences in size resulting from a simple custom class being serialized with BinaryFormatter versus implementing IStateManager and decomposing to simple types that the serializer can optimize. You can find it at:
ASP.NET ViewState Tips and Tricks #2

How do you decide on the means of passing model data from asp.net mvc controllers to views?

There seem to be multiple means of passing model data from controllers in asp.net mvc to views. Its not clear to me if there's a recommended approach in the mvc v1 and v2 releases or if like most things in life, it depends. I've seen several approaches:
Option 1 - Populate the controller's ViewData dixtionary in either an icky string-based indexing way with casting in the view, or the in a strongly typed way by creating a strongly typed custom model class and passing that via ViewData.
Option 2 - Use ViewData.Model, which I'm not sure I even understand.
Option 3 - Use ViewPage.Model, in which case I'm not sure how you pass the model data from the controller.
I've seen a number of posts poo-pooing options 1 and 2 but I don't understand why. These posts seem to highly recommend 3 in most cases.
How do you approach this? Is there a standard way?
Every view 'should' have a specific model. This is sometimes more work so people use short cuts like ViewData, which works but is just not as clean and type safe in my opinion, so I prefer to have everything in the view's model.
You can then make all your views stongly typed. This is a very clean way to do so. Then in your controller you just call the view like:
YourViewModel model = new YourViewModel()
{
// initialize the data here
};
View(model);
Then in your views you can access all the data via ViewPage Model and it is all type safe and enforced from the controller as well.
EDIT from comments:
You don't need to use ViewData at all if you don't want. You can encapsulate all the data your view needs in a model. Just like the example you quoted with ProductsListViewData. It's just a model that contains all the items that were going to be stored in the ViewData. Both ways work but when you encapsulate it in a class (preferred method where everything is in the model) then all the bits and pieces are strongly typed.
ViewData is a generic container so even though you can just put anything you want into it, it is not type safe and therefore not as 'clean'. It comes down to preference and maintainability. There is only option 1 and 3. Your option 2 is misunderstood and is just option 3 in reality. There is no ViewData.Model just ViewPage.Model.
One approach you may wish to consider as your views become more complex, is to reserve the use of Models for input fields, and use ViewData to support anything else the View needs to render.
There are at least a couple of arguments to support this:
You have a master-page that requires some data to be present (e.g. something like the StackOverflow user information in the header). Applying a site-wide ActionFilter makes it easy to populate this information in ViewData after every action. To put it in model would require that every other Model in the site then inherit from a base Model (this may not seem bad initially, but it can become complicated quickly).
When you are validating a posted form, if there are validation errors you are probably going to want to rebind the model (with the invalid fields) back to the view and display validation messages. This is fine, as data in input fields is posted back and will be bound to the model, but what about any other data your view requires to be re-populated? (e.g. drop-down list values, information messages, etc) These will not be posted back, and it can become messy re-populating these onto the model "around" the posted-back input values. It is often simpler to have a method which populates the ViewData with the..view data.
In my experience I have found this approach works well.
And, in MVC3, the dynamic ViewModels means no more string-indexing!
This might be of some help:
When is it right to use ViewData instead of ViewModels?
(I know the following answer is highly arguable, but it's just the way I like to do it)
I would say use ViewData for simple data-tasks, and use the Model for the main purpose of the View. Check out Rob Conerys ViewData helper-classes here to give them a bit more Strongly typed feel:
http://blog.wekeroad.com/2010/01/20/my-favorite-helpers-for-aspnet-mvc
Using Models for absolubtely everything will bloat your project with hundreds of models just to achieve the smallest thing. I mean if you have a User-setting page, you would normally pass a User-model into the view, but if you decide to show some related data like Customers related to this User. You're stuck with the following solutions
You might have to add a List property to the User-model in order to expose the customers to the view. This leads to the Customer-property always being applied to the User-model everywhere else in the project - or make a new simpler User-model.
Make a new action that returns a partial of customers, which you can use with Html.RenderAction.
OR
you could do ViewData["Customers"] = myRepo.GetCustomersRelatedTo(user); // or something like that.
and (if using Robs helpers) in your view:
<%= Html.RenderPartial("CustomerList", Html.ViewData("Customers")) %>
add a PartialView called CustomerList that takes IEnumerable
In my humble opinion this is a cleaner solution and sure - you end up with a magic string here and there, but I'll stick to this approach until someone shows me a project with not a single magic string.
Use the tools we have in the Framework to get the job done. and Keep it simple s... ;)

ASP MVC multi-view form models

I am pretty new to this stuff but I am running into a concept-wall and I keep going back and forth with the best way to handle the problem.
I have a multi-view process to filling out a "New User Form". Each view has a small part of the entire form. In each view I have a model and the model has properties set to an instance of a LINQ to SQL class (for pre-populating) along with dropdown data (state, country). I also thought I should have a model (value object) that represents the entire form. This value object has properties for each LINQ class as well. So I made the view take the value object as a dependency injection. Then what? Just set a property to ViewData to send in multiple models? Seems like a bad idea since I would have to do that to every view. Should all view models come from a base class with the value object?
I might be way off already. Hopefully someone can help me get back on track. The ultimate goal is to have an object that represents the state/data of a form that spans multiple views and the form fields should populate if data is present.
Thanks for your patience!
Okay, so I am going to try to answer my own question but I am still not sure about things. I am going to use the info I got here: http://www.asp.net/Learn/mvc/tutorial-13-cs.aspx to create an instance of the value object that will be available to every view. Then I am sending the instance (or a property of) into the view model through it's constructor.
I am still working on how to keep the instance of the value object through all pages but I am assuming it will have to be done through a session variable of sorts.

ASP.Net: Is it possible to skip databinding of an element if an error occurs?

I use a lot of repeaters for different elements of our sites, and I've always wondered if there was a way to have the repeater skip an element if an exception occurs instead of having the whole page crash?
In particular, I've inherited a system from another developer that using a similar design, however he didn't include any kind of validation for his business objects, and it a single property is missing, the whole thing goes up in smoke.
Any suggestions?
Thanks in advance!
The simplest suggestion I can offer is the check the validity of the data before it's passed to the repeater. I don't believe there's any way to get the stock repeater to skip a data element on error.
The other approach is to build your own repeater, inheriting from the base Repeater, to add that functionality but I've no sample code to offer. Perhaps someone else may be able to help there.
The way I see it, you have at least three options.
You could create a custom repeater control that inherits System.Web.UI.WebControls.Repeater and override the databinding behaviour to be more try-catchy (probably fail silently on databinding errors). You couldd then easily replace all instances of the standard Repeater with this new one.
You could filter your datasources before databinding to remove items you know are going to cause problems beforehand. This option may be quite laborious and something of an iterative process.
You could try adding default values to the business objects, so that the properties you're binding to return a default instance rather than null (not nice either).
That's my thoughts anyway.
One question - you say "when a property is missing". Do you mean he's using a style of databinding syntax that offers no compile-time checking and is referencing properties that don't exist, or is referecing properties that are null?
Edit
OK, so you're referencing properties that are null. If you have access to the code for the business objects you could modify them so they return a new, non-null instance (this is the third option I gave).
You don't say if you're using .net 3.5, but I'll assume you are. You could add a new property "IsValidForDataBinding" on to each of your business objects. In the getter logic you could check each of the necessary properties and sub-objects to check for validity, non-nullness etc and return a bool. When you come to bind your repeater, write a simple linq statement that filters-out the invalid items (i.e. where IsValidForDataBinding = false). Having said that, I still think that writing a derived repeater control could be your easiest option.
Have you tried using string.isnullorempty("the string") to check for a value before referencing the property?
Here's a reference: MSDN

Resources