Strongly Typed Views

Suppose you need to write a view that displays a list of Album instances. One possible approach is to simply add the albums to the view data dictionary (via the ViewBag property) and iterate over them from within the view.

For example, the code in your Controller action might look like this:

public ActionResult List() {
 var albums = new List<Album>();
 for(int i = 0; i < 10; i++) {
   albums.Add(new Album {Title = "Product " + i});
 }
 ViewBag.Albums = albums;
 return View();
}

In your view, you can then iterate and display the products, as follows:

<ul>
@foreach (Album a in (ViewBag.Albums as IEnumerable<Album>)) {
 <li>@a.Title</li>
}
</ul>

Notice that we needed to cast ViewBag.Albums (which is dynamic) to an IEnumerable<Album> before enumerating it. We could have also used the dynamic keyword here to clean the view code up, but we would have lost the benefit of IntelliSense when accessing the properties of each Album object.

<ul>
@foreach (dynamic p in ViewBag.Albums) {
 <li>@p.Title</li>
}
</ul>

It would be nice to have the clean syntax afforded by the dynamic example without losing the benefits of strong typing and compile-time checking of things such as correctly typed property and method names. This is where strongly typed views come in.

Remember that ViewData is a ViewDataDictionary, not just a generic Dictionary. One reason for this is that it has an additional Model property to allow for a specific model object to be available to the view. Since there can be only one model object in ViewData, it's convenient to use this to pass a specific class to the view. This allows your view to specify the class it is expecting the model object to be, which allows you take advantage of strong typing.

In the Controller method, you can specify the model via an overload of the View method whereby you pass in the model instance:

public ActionResult List() {
 var albums = new List<Album>();
 for (int i = 0; i < 10; i++) {
   albums.Add(new Album {Title = "Album " + i});
 }
 return View(albums);
}

Behind the scenes, this sets the value of the ViewData.Model property to the value passed into the View method. The next step is to indicate to the view what type of model is using the @model declaration. Note that you may need to supply the fully qualified type name (namespace plus type name) of the model type.

@model IEnumerable<MvcApplication1.Models.Album>
<ul>
@foreach (Album p in Model) {
 <li>@p.Title</li>
}
</ul>

To avoid needing to specify a fully qualified type name for the model, you can make use of the @using declaration.

@using MvcApplication1.Models
@model IEnumerable<Album>
<ul>
@foreach (Album p in Model) {
 <li>@p.Title</li>
}
</ul>

An even better approach for namespaces that you end up using often within views is to declare the namespace in the web.config file within the Views directory.

@using MvcApplication1.Models
<system.web.webPages.razor>
 …
 <pages pageBaseType="System.Web.Mvc.WebViewPage">
   <namespaces>
     <add namespace="System.Web.Mvc" />
     <add namespace="System.Web.Mvc.Ajax" />
     <add namespace="System.Web.Mvc.Html" />
     <add namespace="System.Web.Routing" />
     <add namespace="MvcApplication1.Models" />
   </namespaces>
 </pages>
</system.web.webPages.razor>

To see the previous two examples in action, use NuGet to install the Wrox.ProMvc4.Views.AlbumList package into a default ASP.NET MVC 4 project, as follows:

Install-Package Wrox.ProMvc4.Views.AlbumList

This places the two view examples in the ViewsAlbums folder and the controller code within the SamplesAlbumList folder. Hit Ctrl+F5 to run the project and visit /albums/listweaklytyped and /albums/liststronglytyped to see the result of the code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset