Exercise 5: Creating a View Model

So far you made your Views display hardcoded HTML, but in order to create dynamic web applications, the View template should receive information from the Controller. One common technique to be used for that purpose is the ViewModel pattern, which allows a Controller to package up all the information needed to generate the appropriate HTML response.

In this exercise, you will learn how to create a ViewModel class and add the needed properties: in this case the number of genres in the store and a list of those genres. Also, you will update the StoreController to use the created ViewModel and finally you will create a new View template that will display the mentioned properties in the page.

Task 1 – Creating a ViewModel Class

In this task, you will create a ViewModel class that will implement the Store genre listing scenario.

  1. If not already open, start Microsoft Visual Web Developer 2010 Express from Start | All Programs | Microsoft Visual Studio 2010 Express | Microsoft Visual Web Developer 2010 Express.
  2. In the File menu, choose Open Project. In the Open Project dialog, browse to Source\Ex05-CreatingAViewModel\Begin, select MvcMusicStore.sln and click Open. Alternatively, you may continue with the solution that you obtained after completing the previous exercise.
  3. Create a ViewModels folder to hold the ViewModel. To do this, right-click the top-level MvcMusicStore project, select Add and then New Folder.

    Figure 34

    Adding a new folder

  4. Name the folder ViewModels.

    Figure 35

    ViewModels folder in Solution Explorer

  5. Create a ViewModel class. To do this, right-click on the ViewModels folder recently created, select Add and then Class.

    Figure 36

    Adding a new Class

  6. Name the class StoreIndexViewModel and click Add.

    Figure 37

    Creating StoreIndexViewModel class – C#

    Figure 38

    Creating StoreIndexViewModel class - VB

Task 2 – Adding Properties to the ViewModel class

There are two pieces of information to be passed from the StoreController to the View template in order to generate the HTML response wanted: the number of genres in the store and a list of those genres.

In this task, you will add those 2 properties to the StoreIndexViewModel class: NumberOfGenres (an integer) and Genres (a list of strings).

  1. Add NumberOfGenres and Genres properties to the StoreIndexViewModel class. To do this, add the following 2 lines to the class definition:

    (Code Snippet – ASP.NET MVC 3.0 Fundamentals – Ex5 StoreIndexViewModel properties – CSharp)

    C#

    public class StoreIndexViewModel
    FakePre-01067339f3004fd7a65aded103cb5870-b959baf6ef3341a9bd4f2036c469c6fe public int NumberOfGenres { get; set; } public List<string> Genres { get; set; }FakePre-ccbfd1f402a34699aef39cbc176d2de3-ba274a7798b746e0b93148071a9b79a8

    (Code Snippet – ASP.NET MVC 3.0 Fundamentals – Ex5 StoreIndexViewModel properties – VB)

    Visual Basic

    Public Class StoreIndexViewModel Public Property NumberOfGenres As Integer Public Property Genres As List(Of String) End Class

    Note:
    Note: The { get; set; } notation makes use of C#’s auto-implemented properties feature. It provides the benefits of a property without requiring us to declare a backing field.

Task 3 – Updating StoreController to use the StoreIndexViewModel

The StoreIndexViewModel class encapsulates the information needed to pass from StoreController’s Index method to a View template in order to generate a response.

In this task, you will update the StoreController to use the StoreIndexViewModel.

  1. Open StoreController class.

    Figure 39

    Opening StoreController class

  2. In order to use the StoreIndexViewModel class from the StoreController, add the following namespace to the top of the StoreController code:

    (Code Snippet – ASP.NET MVC 3.0 Fundamentals – Ex5 StoreIndexViewModel using ViewModels – CSharp)

    C#

    using MvcMusicStore.ViewModels;

    (Code Snippet – ASP.NET MVC 3.0 Fundamentals – Ex5 StoreIndexViewModel using ViewModels – VB)

    Visual Basic

    VB no need to add namespace

  3. Change the StoreController’s Index action method so that it creates and populates a StoreIndexViewModel object and then passes it off to a View template to generate an HTML response with it.

    Note:
    In Lab “ASP.NET MVC Models and Data Access” you will write code that retrieves the list of store genres from a database. In the following code, you will create a List of dummy data genres that will populate the StoreIndexViewModel.

    After creating and setting up the StoreIndexViewModel object, it will be passed as an argument to the View method. This indicates that the View template will use that object to generate an HTML response with it.

  4. Replace the Index method with the following code:

    (Code Snippet – ASP.NET MVC 3.0 Fundamentals – Ex5 StoreController Index method – CSharp)

    C#

    public ActionResult Index() { // Create a list of genres var genres = new List<string> {"Rock", "Jazz", "Country", "Pop", "Disco"}; // Create our view model var viewModel = new StoreIndexViewModel { NumberOfGenres = genres.Count(), Genres = genres }; return View(viewModel); }
    FakePre-8e1dfb4884e94dc4a9d8ce2505dbe3d7-561c230945934602811e5f81ce73ab34
    

    (Code Snippet – ASP.NET MVC 3.0 Fundamentals – Ex5 StoreController Index method – VB)

    Visual Basic

    Public Function Index() As ActionResult 'Create list of genres Dim genres = New List(Of String) From {"Rock", "Jazz", "Country", "Pop", "Disco"} 'Create your view model Dim viewModel = New StoreIndexViewModel With {.NumberOfGenres = genres.Count, .Genres = genres} Return View(viewModel) End Function
    FakePre-42d8cf78609242ffa37c4bee97a61a7e-bc2b31457c0c4a249c8b6f270bab5f84
    

    Note:
    If you’re unfamiliar with C#, you may assume that using var means that the viewModel variable is late-bound. That’s not correct – the C# compiler is using type-inference based on what you assign to the variable to determine that viewModel is of type StoreIndexViewModel. Also, by compiling the local viewModel variable as a StoreIndexViewModel type you get compile-time checking and Visual Studio code-editor support.

Task 4 – Creating a View Template that Uses StoreIndexViewModel

In this task, you will create a View template that will use a StoreIndexViewModel object passed from the Controller to display a list of genres.

  1. Before creating the new View template, let’s build the project so that the Add View Dialog knows about the StoreIndexViewModel class. Build the project by selecting the Debug menu item and then Build MvcMusicStore.

    Figure 40

    Building the project

  2. Create a new View template. To do that, right-click inside the Index method and select Add View.

    Figure 41

    Adding a View – C#

    Figure 42

    Adding a View - VB

  3. Because the Add View Dialog was invoked from the StoreController, it will add the View template by default in a \Views\Store\Index.aspx file. The view will be based on the Site.Master MasterPage template. Check the Create a strongly-typed-view checkbox and then select the StoreIndexViewModel as the Model class. Also, make sure that the View engine selected is ASPX (C#|VB). Click Add.

    Figure 43

    Add View Dialog – C#

    Figure 44

    Add View Dialog - VB

    The \Views\Store\Index.aspx View template file is created and opened. Based on the information provided to the Add View dialog in the last step, the View template will expect a StoreIndexViewModel instance as the data to use to generate an HTML response. You will notice that by seeing that the template inherits a ViewPage<MusicStore.ViewModels.StoreIndexViewModel> in C# and a ViewPage(Of MusicStore. StoreIndexViewModel) in Visual Basic.

Task 5 – Updating the View Template

In this task, you will update the View template created in the last task to output the number of genres and their names within the page.

Note:
You will use <%: %> syntax (often referred to as “code nuggets”) to execute code within the View template. There are two main ways you will see this used:

1. Code enclosed within <% %> will be executed

2. Code enclosed within <%: %> will be executed, and the result will be output to the page

  1. In the Index.aspx file, replace the code inside the Content2 ASP.NET Content control with the following:

    HTML

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    FakePre-1d2e455d0ef64164b271e6c656796697-d3db5278f59c4252a381a21783cb4664 <h3> Browse Genres</h3> <p> Select from <%: Model.NumberOfGenres %> genres</p>FakePre-739e73819abd47eea2619a5b85911004-f0f06eaded8049a79e36c93cc1f0aeb6FakePre-3c0b849038bc41ceb21dbdb2c328c6b0-ab3be49394c34fb48ff8fd9712af98c8FakePre-1624fd2891dd4f669096619101615067-2aacd6373cfe42729e722bdd5a1ac6ce

    Note:
    As soon as you finish typing the period after the word Model, Visual Studio’s Intellisense feature supplies you with a list of possible properties and methods to choose from.

    Figure 45

    Getting Model properties and methods with Visual Studio’s IntelliSense

    The Model property references the StoreIndexViewModel object that the Controller passed to the View template. This means that you can access all of the data passed the Controller to the View template via the Model property, and format it into an appropriate HTML response within the View template.

    You can just select the NumberOfGenres property from the Intellisense list rather than typing it in and then it will auto-complete it by pressing the tab key.

  2. Loop over the genre list in the StoreIndexViewModel and create an HTML <ul> list using a foreach loop. Also change the code inside Content1 ASP.NET Content control with a simple text: Store Genres.

    HTML(C#)

    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreIndexViewModel>" %>
    FakePre-ad8b6b2688f24bf5ba3db0a0991d5739-dfc5535a224741f8898647e5ed2795b4FakePre-dd6bd483132845f5a527d2b477b7730d-a1843dbe9bf74709986ec2021616fe2fStore Genres <ul> <% foreach (string genreName in Model.Genres) { %> <li> <%: genreName %> </li> <% } %> </ul>FakePre-f38e9a14be0a439498d9e051b8b887d9-52d5aa08d90b45c2b1bb9f086d485877FakePre-2725982145944e12b02cd48497511515-e04d9236138c4d16b5fc1f0ae7e1a861FakePre-73d886d7f7f34b048296f4e18879c15d-1560173e9eab4be8a8069a6c24f85c40FakePre-bb27a86b899f4316a6e09b9779e5d0da-7eb331523dfb4be18cfc65a971a78e69FakePre-5da05846c3fe42dc936ce0310c2f729b-e1e964e923744ce98bb55b4af5784b7fFakePre-5d00bcf92f434ffe9acebd270113ee4c-911b0e2f3a254459ae2b3a6724a0d03fFakePre-28c4368605dd499689cccc2c5069e1de-f133a6d6cd0e46cebdefaab98bbe2d7eFakePre-5620d90b5ebf4a3a84bc2d5440b9fa8c-f7d0780ed59e4e9193402576cacf94e8Store Genres <ul> <% foreach (string genreName in Model.Genres) { %> <li> <%: genreName %> </li> <% } %> </ul>FakePre-d61076085e53402291cce1f66dcc05a5-e19015c7f8084e84891c5b664995fec2FakePre-77f2a8cf6c0f4d48b19d7a9453abf505-b9ac587e46f54a9b8566cf566433779c

    HTML(Visual Basic)

    <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of MvcMusicStore.StoreIndexViewModel)" %>
    FakePre-29850ff76f12498d8105a0c36efc6995-7531d7fdbc634ed4be473cd62090686bFakePre-e74afaa488af4b048d4ea1303dd27e8d-4205ed46bddd4e3d952429434dac5175Store Genres <ul> <% For Each string genreName in Model.Genres %> <li> <%: genreName %> </li> <% Next genreName %> </ul>FakePre-945268fa811a462f80bf42e2d8816d2f-b9590e35d70b41adbe0425715b11d6f4FakePre-bde11300248d4e3497749e056f92100b-5256d40846d149a0bdbdaca4af0069ecFakePre-8940d074d8b142afb0f4d7313a9d3468-ecb533b981194c8c83212babbe249afcFakePre-708a99be119a408c84b940f33141887f-273b58aea0df4782b0fd9d0c3e2bfe04FakePre-36d530689ebf41b9a0d4ac9f3c66f927-5b5595f69bcb4a5aa0afb53ac6282898FakePre-233f8ee3c4b343d3a6da923af02e862d-560c3a9de7484c4a9fd86bbf758b5d0eFakePre-a7c7e48bbadf4df380bffad269b28280-9eba7544e8d74ce5aaa6f115315a7772FakePre-8abf1896a1844726981f39cc4f941946-a57257f1911d4c4eb0dc430dc2234520Store Genres <ul> <% For Each string genreName in Model.Genres %> <li> <%: genreName %> </li> <% Next genreName %> </ul>FakePre-6406422ef0d549579988200a381a0ff7-b39229994e3f4c9d8f3f97fb64c6d526FakePre-a1fe331d5574467da6550dd00115c100-a3ee411ad5b54bad92bb38d421a912c3

  3. Press F5 to run the Application and browse /Store. You will see the list of genres passed in the StoreIndexViewModel object from the StoreController to the View template.

    Figure 46

    View displaying a list of genres

  4. Close the browser.

Next Step

Exercise 6: Using Parameters in View