Getting Data to a View Using ViewData

You use a tool like ASP.NET MVC because you want to build data-driven websites. Otherwise plain ol' Html is just fine. If that is the case, then you need to get data to your view. There are a few ways. The first and most basic is the use of ViewData.

The base page for ASP.NET Webforms is System.Web.UI.Page. The base page for an ASP.NET MVC page is System.Web.Mvc.ViewPage. One of the properties on this new base page is ViewData, which is a dictionary that can be used to store data that the view can reference. Let us look at an example:

This is the time that the page you are looking at was last rendered: 7/30/2010 12:56:51 AM.

The time in bold in the previous paragraph was generated in the controller. You can view source on the page to see how it was rendered. The pre-rendered source of that block of the page looks like this:

    
    
    

This is the time that the page you are looking at was last rendered: <%= ViewData["TheCurrentTime"]%>.

The <%= ViewData["TheCurrentTime"] %> bit takes the value put into that dictionary during the execution of the controller action and inlines it into the page. The controller action for for this view looks like the following:

public ActionResult GettingDataToAViewUsingViewData()
{
    ViewData["TheCurrentTime"] = DateTime.Now.ToString();

    return View();
}
    

You can put anything into the ViewData dictionary - strings, integers, custom objects, etc. It makes for a very convenient way to get data from controller to view.

But there is another way that is also convenient but is a better option in most cases, and that is to use a strongly-typed view.

Another Way to Do It That Is Not Awesome

Another way to do it would be to inline the call to DateTime directly into the page, like this:

Here is the time again: 7/30/2010 12:56:51 AM

    
    
    

Here is the time again: <%= DateTime.Now.ToString() %>

Does it work? Yes. Is it the best way to generally do things? Probably not for at least two reasons.

First, as a general rule, it is best to separate display from the logic of the form. This preference comes from the principle of separation of concerns. Views are concerned with Html, controllers with being the glue between Html and model, and models for your business logic. DateTime.Now.ToString() is not concerned with Html generation, so should be done elsewhere.

Second, inlining code in this manner makes that chunk of code harder to test. If it is the result of a controller, it can be tested easily. Of course you would not generally want to automate the testing of DateTime.Now.ToString() so as a contrived example it is not very convincing, but this would not be the case for the custom classes you create that you want to test.

How to Do This the Wrong Way, Part 2

Instead of either of the two patterns above, someone might want to do the following in the controller:

public ActionResult GettingDataToAViewUsingViewData()
{
    ViewData["TheCurrentTime"] = "<p>This is the current time: " + DateTime.Now.ToString() + ".</p>"

    return View();
}
    

If you are generating Html in your controller, chances are, you are going to commit a major fail. Controllers are not intended to create your Html for you. That is the job of the View and the HtmlHelper. So, as a general rule, don't do that!

Where to Go from Here

The ViewData dictionary is cool and all but you really need to learn about strongly-typed views.

Speak Your Mind!

Have something to say? Find a grammatical mistake? Think I said something incorrect? Don't like my perspective? Hate my color scheme? Whatever it is, you can let me know. I would appreciate it if you did.