Now that we have looked at how to pass data around in your view using the ViewData
dictionary, we can take a look at how to pass data around without the ViewData
dictionary. Specifically, we want to take a look at how to do this using a strongly typed view.
This recipe will use the Product
class that we created in the last recipe. It will also use NBuilder to generate Product
data in the same way that we did earlier. You can copy the last project over for this recipe and build from where you left off in the last recipe (or start a new project and grab what you need from the previous recipe as we go).
Views/Home
folder and then open the Product.aspx
file. Inherits
page attribute. We need to change our view so that it inherits from System.Web.Mvc.ViewPage<Product>
. By doing this we are telling the view that it will be working with an instance of Product
. In order for us to gain access to this Product
instance, the MVC framework will provide us with a Model
property that exposes the Product
instance, which is passed down to the view by the controller.Views/Home/Product.aspx:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Product>" %> <%@ Import Namespace="{project name}.Models" %>
Also notice that the previous listing has an Import
statement to reference our Product
class.
HomeController
. In the Product
action we will change from passing a Product
instance into ViewData
and the ViewData
out to the view. Instead, we will just pass that Product
instance directly to the view. Do this by creating a Product
variable (p
) and remove the property reference to ProductName
.Controllers/HomeController.cs:
public ActionResult Product()
{
Product p = Builder<Product>
.CreateNew()
.Build();
//remove the reference to the ProductName here!
return View(p);
}
Product.aspx
view. We now need to change the way we refer to the data that is passed to the view by the controller. Instead of using the built-in ViewData
dictionary directly, we will now reference the Model
property that is exposed by a strongly typed view.Views/Home/Product.aspx:
<h2>Product</h2> <%= Model.ProductName %>
When typing this you should now have full blown IntelliSense to the specified Model
of your strongly typed view.
What we did here was to remove our dependence on magic strings. We told the view to expect a Product
to be passed in by inheriting from generic ViewPage
of type Product
. This doesn't mean that the ViewData
will stop working. It can still be used. However, not only do you have IntelliSense, you now also have strongly typed code that can be refactored without worry.
Now, while this is better than the first recipe where we used the ViewData
dictionary to pass data around, this method still has some issues. In this case, we have a strongly typed reference to our domain model. This means that when our domain model changes by way of a good refactoring, our view will also need to change. This sounds like a good thing at first pass. However, this should scream to you: "Houston, we have a problem!". Our View should not know so much about our domain model that a small change in our object structure somehow forces our presentation layer to also undergo a code refactor.
There is another reason that using our domain directly from the model isn't that great. The view's Model can only be one object referenced by the generic type passed into the view base class from which the view is inheriting. If you want to expand your current view from showing just one product to showing the product, the category that the product is in, and the user that is currently logged in, you can't (or shouldn't) pass that data through your Product
class. For these reasons, we will take a look at yet another way to pass data down to our view that will allow us to be strongly typed, easily refactorable, and allow our presentation layer (the view) to be fairly decoupled from our application layer. And the view model method will also allow us to move more than one type of data out to our view.