Views

.

Views

"A view is a (visual) representation of its model. It would ordinarily highlight certain attributes
of the model and suppress others. It is thus acting as a presentation filter"Trygve Reenskaug, Dec. 1979



In ASP.NET MVC, a view is typically responsible for laying out a screen and populating the screen with formatted data. The view then passes the screen (HTML) and any client-scripts (JavaScript) to the browser. The browser renders the HTML and executes the JavaScript to create the display screen. MVC views may appear similar to Web Forms pages, but there are many differences in their construction. Unlike Web Forms pages, MVC views do NOT use a code-behind file (i.e. just one file for the view) and views do NOT subscribe to any of the page events. Early versions of MVC used the same ".aspx" view engine as Web Forms. But then the Razor view engine was released in MVC 3. The Razor View Engine article provides the syntax for Razor and describes differences between Web Forms pages and MVC views:

MVC does not contain the Server Web Controls which were used in Web Forms. Nor does MVC contain the visual GUI development environment of Web Forms, which provided a graphical editor to layout the screen with the ability to drag and drop controls onto the screen. MVC has all the HTML created on the client-side, instead of having server controls create portions of the HTML the server-side. Having the client perform more of the processed is called a Rich Client Environment, which in MVC, makes use of HTML helpers (to render HTML), Ajax helpers (to render HTML which performs requests asynchronously), and interface libraries such as jQuery UI (for widgets, themes, animation, interatctions). However, all the helpers and interface libraries end up creating JavaScript for the browser to process, without using the server to create any HTML.

The implementation of MVC views also differ from that of Web Form pages. In Web Forms a request URL would map to a physical .aspx file stored on the computer. In MVC a request URL gets routed to an Action Method inside a controller. Then the action method contains the logic to direct the process of obtaining the data and passing it to a view for display. Further information about the MVC Routing Engine is in the Routing article.


MVC View Conventions and Terminology

The name and location of views in MVC must follow a convention. If an action method named Login in the Account controller returns a view, then the associated view must be named Login and reside in a folder named Account within the Views folder. Note, this is unlike the controllers and models which can be located anywhere, even in a separate assembly.

MVC also contains Partial Views which renders only a portion of the screen. Partial Views allow for code reuse (similar to the Web Forms User Controls), and are used with Ajax to perform partial page updates. Partial Views are stored in the Shared subfolder in the Views folder which allows them to be used by any other views in the project.


Passing Data to Views

Data can be passed to views as models, in which case the view data is strongly typed. Data can also be passed using the ViewData and ViewBag objects. The data in the ViewData object is in the form of name-value pairs (e.g. ViewData["theData"]). With ViewData the data is not strongly typed, so you get no assistance from Intellisense and errors will occur at run time instead of compile time. MVC 3 introduced the ViewBag object which is just a wrapper around ViewData, but the data is stored as properties on the ViewData object. This allows the data to be accessed with the dot operator (e.g. ViewBag.theData). It also creates strongly typed data so the ViewBag properties will show up in Intellisense. Also errors will be found at compile time instead of run time.

  1. ViewData - ViewData is a dictionary object which is used to pass data between a controller and views. Controllers add items to the dictionary and the view reads the items from the dictionary. ViewData is derived from the ViewDataDictionary class and contains "key/value" syntax for storing items. ViewData requires typecasting (unboxing) for complex data type and check for null values to avoid error.


  2. ViewBag - ViewBag is a wrapper around the ViewData object. ViewBag uses the dynamic feature of C# 4.0 which allows for the creation of dynamic properties. The ViewBag syntax uses properties (e.g. ViewBag.Foo), while ViewData uses the string syntax (e.g. ViewBag["foo"]). ViewBag doesn’t require typecasting for complex data type.


  3. Strongly Typed Views - In stead of using ViewData or ViewBag, a Strongly Typed View associates a view with a model. This allows for strong compiler-time type checking (instead of getting run time errors on type mismatches). Strongly Typed Views also provides the information which allows intellisense to prompt for all the properties in the model.
  4. ViewModels - ViewModels define the data required for a particular view. The controller creates the ViewModel object based on one or more Model objects. It is best practices for every view have its own ViewModel.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System.Web.Mvc;
using MVC1.Models;
using MVC1.ViewModels;

namespace MVC1.Controllers
{
    public class TestController : Controller
    {
        private Customer theCustomer { get; set; }
        public Salesman theSalesman { get; set; }

        public TestController()
        {
            Customer cust = new Customer();
            cust.FirstName = "Kevin";
            cust.LastName = "Harris";
            cust.PurchaseAmount = 12.95;
            theCustomer = cust;

            Salesman sman = new Salesman();
            sman.FirstName = "Fred";
            sman.LastName = "Smith";
            theSalesman = sman;
        }

        //View Data
        public ActionResult GetView1()
        {
            ViewData["Customer"] = theCustomer;
            return View("View1");
        }

        // View Bag
        public ActionResult GetView2()
        {
            ViewBag.Customer = theCustomer;
            return View("View2");
        }

        // Strongly Typed View
        public ActionResult GetView3()
        {
            return View("View3", theCustomer);
        }

        // View Model
        public ActionResult GetView4()
        {
            PurchaseViewModel vmPurchase = new PurchaseViewModel();
            vmPurchase.CustomerName = theCustomer.FirstName + " " +  theCustomer.LastName;
            vmPurchase.PurchaseAmount = theCustomer.PurchaseAmount;
            vmPurchase.SalesmanName = theSalesman.FirstName + " " + theSalesman.LastName;
            return View("View4", vmPurchase);
        }

    }
}


Test Controller

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@*This View gets data through ViewData*@

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>View 1</title>
</head>
<body>
    <div>
        @{
            MVC1.Models.Customer cust = (MVC1.Models.Customer)ViewData["Customer"];
        }
        <b>This View gets data through ViewData</b> <br /><br />

        <u>Customer Details</u><br />
        Customer Name : @cust.FirstName @cust.LastName<br />
        Purchase Amount: @cust.PurchaseAmount.ToString("C")
    </div>
</body>
</html>


View 1 (ViewData)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@*This View gets data through ViewBag*@

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>View 2</title>
</head>
<body>
    <div>
        @{
            MVC1.Models.Customer cust = (MVC1.Models.Customer)ViewBag.Customer;
        }
        <b>This View gets data through ViewBag</b> <br /><br />

        <u>Customer Details</u><br />
        Customer Name : @cust.FirstName @cust.LastName<br />
        Purchase Amount: @cust.PurchaseAmount.ToString("C")
    </div>
</body>
</html>


View 2 (View Bag)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@*This is a Strongly Typed View*@

@model MVC1.Models.Customer

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>View 3</title>
</head>
<body>
    <div>
        <b>This is a Strongly Typed View</b> <br /><br />

        <u>Customer Details</u><br />
        Customer Name : @Model.FirstName @Model.LastName<br />
        @if (Model.PurchaseAmount > 10.00)
        {
            @:Purchase Amount:
            <span style="color:red">
                 @Model.PurchaseAmount.ToString("C")
            </span>

        }
        else
        {
            <span style="color:blue">
                Purchase Amount: @Model.PurchaseAmount.ToString("C")
            </span>
        }
    </div>
</body>
</html>


View 3 (Strongly Typed View)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@*This is a View Model*@

@model MVC1.ViewModels.PurchaseViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>View 4</title>
</head>
<body>
    <div>
        <b>This is a View Model</b> <br /><br />

        <u>Customer Details</u><br />
        Customer Name : @Model.CustomerName<br />
        Purchase Amount: @Model.PurchaseAmount.ToString("C")<br />
        Saleman Name: @Model.SalesmanName
    </div>
</body>
</html>


View 4 (View Model)


Rendering Views

Inside an action method, the helper method View creates an ViewResult object which renders a view to the response stream. See the Controllers article for more information about action methods, action results, and their helper methods. When the View() helper method is used with no parameters, then the ViewResult object looks for the a view which has the same name as the action method. It looks for the view inside a subdirectory of Views folder. The subdirectory must have the same name as the controller. For example, if the View() helper method is used inside an action method named "Login", which is inside the "Account" controller, then the view must be called "Login" and be located in the "View/Account" subdirectory.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    public class AccountController : Controller
    {
        //
        // GET: /Account/Login
        // Get Login data to display.
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }


View Named Login Must be in Views/Account/ Subdirectory

You can direct the ViewResult object to look for a different view by passing in the name of the different view to the View helper method. For example View("AnotherView") will cause the ViewResult object to look for a view called "AnotherView"). Note that the View helper method also accepts another model through the first parameter also, such as View(AnotherModel). So be sure if you want a different view, the parameter in the View() method must be of type string.

1
2
3
protected internal ViewResult View(
	string viewName
)


Pass a Different View with the View() Method

1
2
3
protected internal ViewResult View(
	object model
)


Pass a Different Model with the View() Method


Rendering Partial Views

Partial views are typically stored in the Shared folder so they can be reused by all other views. A convention is to start the partial view name with an underscore (e.g. _MyView). A partial view can be called from a view by using HTML Helpers, such as:

Html.RenderPartial("~/Views/Shared/_Product.cshtml", product);

or

@Html.Partial("~/Views/Shared/_Product.cshtml", product);

The difference between the four HTML helper methods are described below.

  1. Html.RenderPartial - results will be written directly to the HTTP response stream. The method returns void. Useful when displaying data which is already in the corresponding view model.

  2. Html.RenderAction - results will be written directly to the HTTP response stream. The method returns void. Useful when the data for the partial view is independent from the corresponding view model.

  3. Html.Partial - The method returns the partial view as an HTML-encoded string. Useful when displaying data which is already in the corresponding view model.

  4. Html.Action - The method returns the partial view as an HTML-encoded string. Useful when displaying data which is already in the corresponding view model. The is the best choice if you want to cache a partial view.

Html.Action() and HTML.RenderAction() will call an action method, While Html.Partial() and HTML.RenderPartial() will not. Html.Partial() and Html.Action() returns the rendered partial as a string, so their results can be assigned to a variable. HTML.RenderAction() and HTML.RenderPartial write the rendered partial directly to the HTTP response stream.

Use Html.Partial() when you are rendering static content or, it the data for the partial view corresponds to the view model. Use Html.Action() when you actually need to retrieve additional data from the server to populate the partial view.