Razor View Engine

.

Razor View Engine

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.

In MVC 3 a new view engine called Razor was released for coding the display screens (views). Razor is a typical view engines in that it employs a combination of HTML and a server-side programming language. The older view engine used in Web Forms, and MVC 1 and MVC2, (System.Web.Mvc.WebFormViewEngine) can still be used in later versions MVC. However, MVC 3+ defaults to using the Razor view engine (System.Web.Razor). Razor can contain either C# or VB.NET code mixed with the HTML. Razor files containing C# code have a .cshtml extenstion while Razor files containing VB code have a .vbhtml extension. There are several other third party view engines which can be used with MVC: Bellevue, Brail, Hasic, NDjango, NHaml, NVelocityViewEngine, SharpTiles, Spark View Engine, Wing Beats, and XsltViewEngine.

A Razor view typically contains literal text, HTML, and server code. The server code can be either an expression which returns data to be placed in a view, or processing logic such as loops for iterating through the data. The @ is used to transition between literal text and code expressions. For example the expression @item.value returns the item name from the server and inserts it into the view. To specific a @ as a literal, use two @@ symbols. The @expression is similar to Response.Write, except the @expression automatically HTML encodes the data. HTML which is not encoded can be passed to the response stream by usingthe HTML helper @HTML.Raw(). If literal text is needed as part of an expression, an explicit expression can be created by surrounding the text with (). For example the statement @(item.value / 5) would prevent the division operation of occurring.

Server code for logic processing can be put into blocks. Code blocks are delimited by @{ } for C# and @Code ... End Code for VB. Inside the code block, if Razor does not transition between code and literals as desired, the literal text can be put inside a <text></text> tag, or after the characters @: will also explicitly denote literal text.

Reference Examples

Below is a list of sites with information about Razor syntax:

  1. HTML Helpers Cheat Sheet
  2. Razor Cheat Sheet
  3. C# Razor Syntax Quick Reference

Below is a snippet of Razor code showing the comment and block syntax:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
   @* This is a Razor Comment *@
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Payee)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Amount)
            </td>
            <td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
                @Html.ActionLink("Details", "Details", new { id=item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.ID })
            </td>
        </tr>
    }


Example Razor Code


Complete Razor Views

Below are complete examples of a login and a list razor 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
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 CathySite.Web.Models;
@model LoginViewModel

<hgroup class="title">
    <h1 class="centerText">Website Administration</h1>
</hgroup>

<section id="loginForm">
    <h5>Please Log In</h5>
    @using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)
        <div style="padding-top: 15px;">
            <table cellpadding= "10">
                <tr>
                    <td>
                        @Html.LabelFor(m => m.UserName)
                    </td>
                    <td>
                        @Html.TextBoxFor(m => m.UserName)
                    </td>
                    <td>
                        @Html.ValidationMessageFor(m => m.UserName)
                    </td>
                </tr>
                <tr>
                    <td>
                        @Html.LabelFor(m => m.Password)
                    </td>
                    <td>
                        @Html.PasswordFor(m => m.Password)
                    </td>
                    <td>
                        @Html.ValidationMessageFor(m => m.Password)
                    </td>
                </tr>
                <tr>
                    <td></td>
                    <td>
                        <input type="submit" value="Log in" />
                    </td>
                    <td></td>
                </tr>
            </table>
        </div>
    }
</section>
<section>
    <div style="width:90%;">
        <h3>Administration Area</h3>
        <h5>
            This is a restricted area for maintaining the contents of this website. The restricted area includes a home-grown content management system for changing the contents of some
            of the web pages without the need to modify any programs.
        </h5>
    </div>
</section>


Razor Code for a Login 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
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@model CathySite.Web.ViewModels.BillIndexViewModel

@{
    //Layout = null;
    ViewBag.Title = "Bills";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <style>
        table, th, td {
            border: 1px solid black;
        }

        table {
            border-spacing: 5px;
        }
        /* cellspacing */

        th, td {
            padding: 5px;
        }
        /* cellpadding */
    </style>
</head>
<body>
    <div>
        <br />
        @Html.ActionLink("Add Bill", "Create")
        <br /><br />
        <table cellpadding="10">
            <tr>
                <th>
                    @Html.DisplayNameFor(m => m.Bills.FirstOrDefault().Payee)
                </th>
                <th>
                    @Html.DisplayNameFor(m => m.Bills.FirstOrDefault().Amount)
                </th>
                <th>
                    @Html.DisplayNameFor(m => m.Bills.FirstOrDefault().PeriodID)
                </th>
                <th>
                    @Html.DisplayNameFor(m => m.Bills.FirstOrDefault().Date)
                </th>
                <th>
                    @Html.DisplayNameFor(m => m.Bills.FirstOrDefault().Balance)
                </th>
                <th>
                    Options
                </th>

            </tr>
            @foreach (var item in Model.Bills)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(m => item.Payee)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Amount)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.PeriodID)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Date)
                    </td>
                    <td>
                        @Html.DisplayFor(m => item.Balance)
                    </td>
                    <td>
                        @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
                        @Html.ActionLink("Details", "Details", new { id = item.ID }) |
                        @Html.ActionLink("Delete", "Delete", new { id = item.ID })
                    </td>
                </tr>
            }
        </table>
        <br />
    </div>
</body>
</html>


Razor Code for List View


Layout Views

Layout Views in Razor are similar to "master pages" in the Web Forms view engine. They create a template containing common view elements and data shared by content views. Layout views are typically stored in the Shared folder (e.g._Layout.cshtml. Inside the layout view is where you put your DOCTYPE, head, and body tags. Also inside the layout view are two content elements:

  1. @RenderBody() - the contents of the content view are placed.

  2. @RenderSection() - allows content view another location to plug in content, in addition to the body). For example to make a required section called "Footer", use @RenderSection("Footer", true); in the layout view, and then use @section Footer{...} in the content view.

These content elements allow the content views to insert their portions into the layout view as part of the final rendered view. The layout view is specified in the _ViewStart.cshtml file which is located at the root level. _ViewStart files can be placed in subdirectories which will override the global _ViewStart file. Layout views can also be specified within the individual content view files. So the order of precedence is the layout specified in the content view, the subdirectory _ViewStart file, then the global _ViewStart file.

 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
58
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Cathy Harris Website</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Cathy Harris Website", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Pictures <span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            <li>@Html.ActionLink("Cathy", "Pictures/Cathy", "Content", null, new { target = "_blank" })</li>
                            <li>@Html.ActionLink("Pets", "Pictures/Pets", "Content", null, new { target = "_blank" })</li>
                            <li role="separator" class="divider"></li>
                            <li>@Html.ActionLink("Old Pictures", "Pictures/Old", "Content", null, new { target = "_blank" })</li>
                            <li role="separator" class="divider"></li>
                            <li>@Html.ActionLink("Homer", "Pictures/Homer", "Content", null, new { target = "_blank" })</li>
                        </ul>
<li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>             
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()       
        <hr />
        <footer>
            <div style="margin-top: -10px">
                Kevin Harris &copy; @DateTime.Now.Year
            </div>
        </footer>
    </div>

    <script src="~/Scripts/ckeditor/ckeditor.js"></script>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @Scripts.Render("~/bundles/ckeditor")
    @RenderSection("scripts", required: false)
</body>
</html>


_Layout.cshtml File

HTML Helpers

You can code HTML directly into a Razor view, or you can use HTML Helpers. Typically HTML helpers are just extension methods which return strings. HTML helpers make it easy to create small blocks of HTML. You can use the standard predefined HTML helpers, or you can create your own HTML helpers as extension methods.

A couple of the common HTML helpers are:

  1. BeginForm() - emits a form tag.

  2. LabelFor() - emits a label.

  3. EditorFor() - create an appropriate element for the data type (e.g. textbox for a string, checkbox for a boolean).

  4. ValidationMessageFor() - create a mesage.

  5. HiddenFor() - emits a hidden input tag.

Custom HTML Helpers

Below is an example of a custom HTML helper created as an extension method:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace CathySite.Web.Infrastructure
{
    public static class MyHelpers
    {
        public static MvcHtmlString Img(this HtmlHelper helper, 
                                        string src, string altText)
        {
            var builder = new TagBuilder("img");
            builder.MergeAttribute("src", src);
            builder.MergeAttribute("alt", altText);
            return MvcHtmlString.Create(builder.ToString(TagRenderMode.SelfClosing));
        }
    }
}


Custom HTML Helper Extension Method

1
2
   <div style="padding-top: 15px;">
            @Html.Img("/Images/mvc7.png", "The Alternate Text")


Using Custom HTML Helper


Error | ASP.NET Developer

Error

Error message

  • Warning: Cannot modify header information - headers already sent by (output started at /srv/disk9/1218369/www/kcshadow.net/aspnet/includes/common.inc:2748) in drupal_send_headers() (line 1232 of /srv/disk9/1218369/www/kcshadow.net/aspnet/includes/bootstrap.inc).
  • PDOException: SQLSTATE[42000]: Syntax error or access violation: 1142 INSERT command denied to user '1218369_b2cf'@'185.176.40.58' for table 'watchdog': INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => 0 [:db_insert_placeholder_1] => cron [:db_insert_placeholder_2] => Attempting to re-run cron while it is already running. [:db_insert_placeholder_3] => a:0:{} [:db_insert_placeholder_4] => 4 [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => http://www.kcshadow.net/aspnet/?q=razor [:db_insert_placeholder_7] => [:db_insert_placeholder_8] => 54.198.41.76 [:db_insert_placeholder_9] => 1534839453 ) in dblog_watchdog() (line 160 of /srv/disk9/1218369/www/kcshadow.net/aspnet/modules/dblog/dblog.module).
The website encountered an unexpected error. Please try again later.