In "Beta Version of ASP.NET MVC 3 Is Out!" the product was still in the "almost released" category of software. But now it is out in the wild in final form, and it's time to dive into more details of the Razor syntax. If you haven't already fired up Microsoft's Web Platform Installer and installed MVC 3, go get it! It is a great upgrade to the software. For more information on Razor, see "Sharper Applications with the ASP.NET MVC 3 Razor View Engine" and "Working with the ASP.NET MVC 3 Razor View Engine."

I'm going to explore some of the syntax differences between views created with the ASP.NET Web Forms engine and the Razor view engine, along with some Razor-specific features. The ones I'll cover here are those that Web Forms developers will see most often, along with some that are just plain interesting.

Syntax Differences
Probably the first thing you'll notice is that a Web Forms view is defined in a file with an .aspx extension long used for Web Forms, such as LogOn.aspx. The Razor view is defined in LogOn.cshtml or LogOn.vbhtml, with a custom Razor file extension that indicates the language used in the view.

A Web Form page has a Page directive at the top that identifies the language used in the page, the master page file, and the type of model object used in the view:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<DogApp.Models.LogOnModel>" %>

Or, for VB:

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage(Of DogApp.LogOnModel)" %>

The Razor page has only a @model (C#) or @ModelType (VB) directive to identify the type of model object, as shown below. It figures out the language from the file extension and the master page is defined elsewhere, using a new feature, layout pages.

C#:

@model MVC3Dogs.Models.LogOnModel

VB:

@ModelType MVC3Dogs.LogOnModel

If you prefer the full syntax of specifying that the WebViewPage object is of a specific type, like in the Web Forms engine, you can use the @inherits statement at the top of the view instead of @model or @ModelType. There really is no reason to use @inherits, particularly since it is a syntax that Microsoft introduced with a preview version of MVC 3. This puts it in the awkward position of providing backward compatibility with a feature introduced in a pre-beta release.



All code nuggets in the Web Forms view use <%  %> delimiters, whereas Razor uses @. Notice how much cleaner and simpler the Razor view is as a result. By default, Visual Studio highlights both types of code nugget markers in yellow, making them stand out on the page.

The using/Using block code is much cleaner in Razor. The Web Forms code can only be described as busy:

C#:

<% using (Html.BeginForm()) \\{ %>
    ...
<% \\} %>

VB:

<% Using Html.BeginForm() %>
    ...
<% End Using %>

But the Razor code is much cleaner and better reflects how the block is defined in a regular language code file, including the opening and closing curly brackets or final End Using statement:

C#:

@using (Html.BeginForm()) \\{
    ...
\\}

VB:

@Using Html.BeginForm()
    ...
End Using

Razor Features
Those are some of the most noticeable differences between Web Forms and Razor syntax. There are also a few Razor features that make it even more effective to use. For example, you can delimit a regular code block using the @\\{  \\} syntax in C# or @Code  End Code syntax in VB, like the following code that sets the view's Title property. This code doesn't insert a string into the HTML; it just executes a line of code. You can include as much code as you want in the code block, but in the spirit of MVC views you should keep it simple and completely focused on building the view rather than inserting code that really should be in the controller. Variable values stay in scope in all of the code blocks and nuggets on the page.

C#:

@\\{
    ViewBag.Title = "Log On";
\\}

VB:

@Code
    ViewData("Title") = "Log On"
End Code



The following code uses a foreach/For Each loop to run through all of the items in the Model. The code block has the @ marker to start the code, but from there on you're just writing regular code interspersed with HTML markup. It knows that <tr> is part of the markup and not part of the code, for example. You only need to include another @ for each code additional code statement. Again, this is much cleaner than the syntax for the Web Forms engine, and much quicker to type.

C#:

@foreach (var item in Model) \\{
    <tr>
        <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>
        <td>@item.Name</td>
        <td>@item.Gender</td>
        <td>@item.Age</td>
    </tr>
\\}

VB:

@For Each item In Model
    @<tr>
        <td>@Html.ActionLink("Edit", "Edit", New With \\{.id = item.ID\\}) |
            @Html.ActionLink("Details", "Details", New With \\{.id = item.ID\\}) |
            @Html.ActionLink("Delete", "Delete", New With \\{.id = item.ID\\})
        </td>
        <td>@item.Name </td>
        <td>@item.Gender </td>
        <td>@item.Age </td>
    </tr>
Next

If you ever have a situation where you nest HTML content within an if code block or loop, or any other code block, you can wrap the inner content of the code block in an HTML element, such as a span, to help Razor identify the beginning of a content block. If you don't want to include any kind of wrapping tag, you can use the <text> block, as in the following code. Without the <text> tags, the dog names run together without any whitespace.

C#:

@foreach (var item in Model) \\{
    <text>@Ajax.ActionLink(item.Key, "GetDogDetails", new \\{ id = item.Value \\},
        new AjaxOptions \\{ UpdateTargetId = "divResults" \\})
    </text>
\\}

VB:

@For Each item In Model
    @<text>
    @Ajax.ActionLink(item.Key, "GetDogDetails",  New With \\{.id = item.Value\\},
        New AjaxOptions() With \\{.UpdateTargetId = "divResults"\\})
    </text>
Next

One other nice feature in Razor is server-side comments. This lets you comment out code or HTML so that the content of the comment is not part of the web page delivered to the browser. HTML has client-side comments delimited with <!--  --> as shown in the following code snippet, but even though the content won't appear in the browser, a user who views the page source will see the content. ASP.NET Web Forms, and that view engine, have server-side comments using the <%-- --%> syntax that doesn't include the content as part of the web page sent to the browser.

<!-- This will appear in the web page source. -->

The Razor syntax for server-side comments is the following, in both C# and VB. You can use this to comment out a single line or many, and you can use the Visual Studio Comment and Uncomment buttons  to select a block of HTML and code and either comment it out or remove the comment block and leave the content in the page.

@*
    This won't appear in the web page source.
*@

If you have an embedded @ within static content in the page, such as in an email address, Razor is smart enough to see that the @ doesn't start off a code statement. But if you ever have a situation where what follows @ could be a code statement, but you want Razor to consider it content, just double up the @ marker and use @@ instead.

Hopefully I've whet your appetite with these "best of" features of Razor. It seems to the be emerging view engine of choice for choosy MVC developers, with good reason!

This article is derived from MVC courseware that I've developing for AppDev.

Don Kiely (donkiely@computer.org), MVP, MCSD, is a senior technology consultant, building custom applications and providing business and technology consulting services. His development work involves SQL Server, Visual Basic, C#, ASP.NET, and Microsoft Office.