Strong-typed ViewData
In the previous example, we used the ViewData dictionary to pass data from the controller to the view. When developing the view, each dictionary item we want to display should be cast to the correct class, resulting in a less maintainable situation. It might also lead to code spaghetti in the view. It would be useful if the ViewData dictionary already knew which class type each of its items represented. This is where the model comes in handy! We are serving employee information to the view, so why not use the Employee class that we'd previously created as a "the" model for our view? Note that we'd already placed the Employee class inside the Model folder, which is the appropriate location for model classes.
Views can be made strong-typed by updating the view and replacing the base class of the page (System.Web.Mvc.ViewPage) with a generic version: System.Web.Mvc.ViewPage<Employee>. Make sure you compile your project after updating the first few lines of code in the Show.aspx file:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Employee>" %>
By applying the above code, the page's ViewData object will be made generic. This means that the ViewData object will not only be a dictionary, but will also contain a property named Model, which is of the type that has just been passed in: MvcApplication1.Models.Employee.
This ViewData.Model property is also available as a Model property in the view. We will have to update the view to be able to use this new property. Simply change from ViewData[key] to a property Model (which contains the Employee instance). For example, Model.FirstName is in fact the FirstName property of the Employee instance that you want to render. Note that you can still use dictionary entries combined with this strong-typed model.
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Employee>" %><asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"><% if (ViewData["ErrorMessage"] != null) { %><h1><%=ViewData["ErrorMessage"]%></h1><% } else { %><h1><%=Model.FirstName%> <%=ViewData.Model.LastName%></h1><p>E-mail: <%=Model.Email%></p><% } %></asp:Content>
Before being able to run the application, the controller needs some updates as well. The main difference is that employee properties are no longer copied into the ViewData dictionary. Instead, the Employee instance is passed directly to the view.
using System.Web.Mvc;using MvcApplication1.Models;namespace MvcApplication1.Controllers{ public class EmployeeController : Controller { public ActionResult Show(string firstname) { Employee employee = null; if (string.IsNullOrEmpty(firstname)) { ViewData["ErrorMessage"] = "No firstname provided!"; } else { employee = new Employee { FirstName = firstname, LastName = "Example", Email = firstname + "@example.com" }; } return View(employee); } }}
Note that we are passing the model data to the View() method. Alternatively, this can be done by stating Model = employee prior to returning the view. If you run the application, the result should be exactly the same as before.