The biggest architectural difference that exists between ASP.NET MVC and ASP.NET Web Forms is the neat separation between the two key phases of processing the request and generating the response. In general, rendering an ASP.NET Web Forms page means looping through the page’s server controls and iteratively have each control add its own markup to a buffer so as to ensure that the results form a HTML-compliant string. In ASP.NET Web Forms, the rendering process is rooted on the page as a resource and server controls play a central role. For each request, server controls are used to read the input and render the output. Server controls are live instances that have the same lifecycle as the request.

The internal architecture of ASP.NET MVC is quite different in the way requests are processed. Not only  is each request mapped to a controller object, but The controller does anything necessary to produce the raw data that will be served back to the requesting browser. Any controller method ends with a call to an internal method that just packages the raw data into the preferred format, be it HTML, JSON, binary, or plain text. Architecturally speaking, this final step implies the presence of a separate layer-the generator of the ActionResult type. When it comes to generating HTML, the action result generator gets the more familiar name of the view engine.

The view engine works by mixing together a view template and raw data to be displayed in the final HTML. The template is expressed in an engine-specific markup language; the data is passed in by the invoking controller method packaged in dictionaries or in strongly-typed objects. An ASP.NET MVC application can have one or more view engines, which means that different views of an application can be expressed using different markup languages. The default ASP.NET MVC project supports two view engines;  Razor and WebForms. More likely, though, you have each application using just one view engine and one markup language. Of the two, Razor is by far the most concise, elegant and effective markup language.

Razor View Engine

In Razor, a view template is essentially a HTML page with a few placeholders, often referred to as code nuggets. Each placeholder contains an executable expression-much like a code snippet. The code in the snippets, which can be  C# or VB,   is evaluated when the view gets rendered and resulting markup is integrated in the HTML template. The Razor engine reads view templates from a physical location on disk. The path is retrieved using the ASP.NET virtual path provider.

The location of view templates is rooted in the Views folder. The Views folder has a number of subfolders-each named after an existing controller. Each controller-specific directory contains physical files whose name is expected to match the name of a view invoked from the controller. The extension has to be .cshtml for the Razor view engine. If you’re writing your ASP.NET MVC application in Visual Basic, then the extension must be .vbhtml. ASP.NET MVC also requires that you place each view template under the directory of the controller that uses it. In case multiple controllers are expected to invoke the same view, then you move the view template file under the Shared directory.

It is important to note that the same hierarchy of directories that exists at the project level under the Views folder must be replicated on the production server when you deploy the site. The Razor view engine defines a few properties through which you can control how view templates are located. For the internal working of the Razor view engine, it is necessary to provide a default location for master, regular and partial views both in a default project configuration and when areas are used.

Table 1 shows the location properties supported by the Razor view engine with the predefined value.

Property

Default location format

AreaMasterLocationFormats

~/Areas/{2}/Views/{1}/{0}.cshtml

~/Areas/{2}/Views/Shared/{0}.cshtml

~/Areas/{2}/Views/{1}/{0}.vbhtml

~/Areas/{2}/Views/Shared/{0}.vbhtml

AreaPartialViewLocationFormats

~/Areas/{2}/Views/{1}/{0}.cshtml

~/Areas/{2}/Views/{1}/{0}.vbhtml

~/Areas/{2}/Views/Shared/{0}.cshtml

~/Areas/{2}/Views/Shared/{0}.vbhtml

AreaViewLocationFormats

~/Areas/{2}/Views/{1}/{0}.cshtml

~/Areas/{2}/Views/{1}/{0}.vbhtml

~/Areas/{2}/Views/Shared/{0}.cshtml

~/Areas/{2}/Views/Shared/{0}.vbhtml

MasterLocationFormats

~/Views/{1}/{0}.cshtml

~/Views/Shared/{0}.cshtml

~/Views/{1}/{0}.vbhtml

~/Views/Shared/{0}.vbhtml

PartialViewLocationFormats

~/Views/{1}/{0}.cshtml

~/Views/{1}/{0}.vbhtml

~/Views/Shared/{0}.cshtml

~/Views/Shared/{0}.vbhtml

ViewLocationFormats

~/Views/{1}/{0}.cshtml

~/Views/{1}/{0}.vbhtml

~/Views/Shared/{0}.cshtml

~/Views/Shared/{0}.vbhtml

FileExtensions

.cshtml, .vbhtml

Table 1.  The default location formats of the Razor view engine.

As you can see, locations are not fully qualified paths but contain up to three placeholders. The placeholder {0} refers to the name of the view, as it is being invoked from the controller method. The placeholder {1} refers to the controller name as it is used in the URL. Finally, the controller {2}, if specified, refers to the area name.

I’ve already mentioned that an ASP.NET MVC application has two view engines registered by default. This means that you can have views expressed in either format.  As long as each view can be resolved unambiguously, everything works just fine. For every view or partial view that is necessary to render, registered view engines are given a chance to process the request in the order in which they are registered. Note that the ASPX engine always takes precedence over the Razor engine. This means that if you happen to have two view files such as default.aspx and default.cshtml the former will be picked up. At any rate, you can modify the order (and number) of registered view engines in global.asax just when the application starts up. Here’s a sample implementation of Application_Start that removes the ASPX engine that only supports the Razor engine.

 
protected void Application_Start()
{
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new RazorViewEngine());
}

View engines are referenced via the ViewEngines.Engines collection. In the sample code, you first clear out the collection and then add just the engine instance that you’re going to use. Using a single view engine is preferable for consistency reasons, but nothing really prevents you from mixing view engines and view files in your project.

Razor Nuggets

I’ve already described  code nuggets as being similar to ASP.NET code blocks but with a simpler and terser syntax. You denote the start of a Razor code block with a @ character. More importantly, you don’t need to close those blocks explicitly. The Razor parser uses the C# parsing logic to figure out where a line of code finishes. Here’s a first basic example of a code nugget.

 
<h2>@ViewBag.Header</h2>

Nuggets can be used in loops to generate for example the rows of a HTML table, as below:

 
<table>    
@foreach (var person in Model.People) {
    <tr>
       <td><%: person.Name %></td>
       <td><%: person.Country %></td>
    </tr>
}
</table>

Nuggets can contain any executable line of code as long as it is prefixed with @. Here’s an example of how you import a namespace:

 
@using System.Net;

And here’s how you create a HTML form:

 
@using (Html.BeginForm()) {
   <fieldset>
       :
   </fieldset>
}

Special Expressions

Usually, a nugget consists of a single line of code. However, you can expand it to multiple lines by using an @{ code } block:

 
@{
   var city = "London";
}
:
<p>@city</p>

Any variable you create can be retrieved and used later as if the code belonged to a single all-encompassing block. The content of an @{...} block can mix code and markup. It is essential, however, that the parser can figure out exactly where code ends and markup begins and vice versa. Look at the following nugget:

 
@{
    var theString = GetSomeString();
    if(theString.Length > 10)
      <p>Text too long</p>
    else
      <text>Text ok</text>
}

If the markup content you’re emitting is wrapped up by HTML tags, then the parser will properly recognize it as markup. If it’s plain text (i.e., just a text string) then you must wrap it in a Razor-specific <text> for the parser to handle it correctly.

If you  wish to emit  a value that  results from an expression,  then you can wrap it  in round brackets:

 
<span> @("I love " + city) </span>

Note that any content emitted by Razor is automatically encoded. If your code returns HTML markup that you want to insert in the page as-is,  without encoding, then you can resort to using the Html.Raw helper method:

 
@Html.Raw(Strings.HtmlMessage)

Most of the time, the Razor parser is smart enough to figure out from the context the reason why you’re using the @ symbol, whether it’s to denote a code nugget or perhaps a literal email address. If you hit an edge case that the parser can’t successfully solve, using @@ makes it clear that you want the symbol @ to be taken literally and not as the start of a code nugget.

Finally, when inside multiline code nuggets @{ … }, you use the C# syntax to place comments. You can comment out an entire block of Razor code using the @* … *@ syntax instead:

 
@*
<div> Razor markup here </div>
*@

The Visual Studio toolbar buttons for commenting blocks in and out support the Razor syntax nicely.

Conditional Nuggets in ASP.NET MVC 5

Razor now supports conditional attributes that are emitted only if the Razor expression evaluates to a non-null string. Let’s consider the following markup:

 
<div class="@cssClassName">
   ...
</div>

If the variable cssClassName is empty or null you may not want the class attribute to be emitted. In ASP.NET MVC 5, some conditional logic built into the Razor engine makes it happen automagically.

This is a useful feature as it may save a lot of boring code in many views. Less code in the view also gives a significant contribution to keeping markup cleaner and more readable. It should also be noted that conditional nuggets are not limited to strings but applies also to Boolean expressions.

URL Auto-completion

For quite some time in Razor you had to explicitly complete the URL for images and script files using the Url.Content method, as shown below:

 
<script src="@Url.Content("~/content/scripts/somefile.js")"></script>

It is now possible to avoid that as Razor automatically expands the tilde character in HTML elements.

 
<script src="~/content/scripts/somefile.js"></script>

It is interesting to notice that this will work only within HTML elements.  In other words, if your page contains C# or script code that defines a relative URL with a tilde  then it  won’t be automatically expanded and so the only alternative is to  resort to Url.Content.

Properties of the Razor View Object

When the Razor view engine is used, the resulting view object is an instance of the WebViewPage class defined in the System.Web.Mvc assembly. This class incorporates the logic to parse markup and render HTML. Public properties on this class are available to any code nuggets you might write in actual templates. The properties of the Razor view object are summarized in the table below:

Property

Description

Ajax

Gets an instance of the AjaxHelper class used to reference Ajax HTML helpers around the template.

Culture

Gets and sets the ID of the culture associated with the current request.

Href

Converts any path you create in code (which can include the ~ operator) to a path that the browser can understand.

Html

Gets an instance of the HtmlHelper class used to reference HTML helpers in the template.

Context

Gets the central repository to gain access to various ASP.NET intrinsic objects: Request, Response, Server, User, and so forth.

IsAjax

Returns true if the current request was initiated by the browser’s Ajax object.

IsPost

Returns true if the current request was placed through an HTTP POST verb.

Layout

Gets and sets the path to the file containing the master view template.

Model

Gets a reference to the view model object (if any) containing data for the view. This property is of type dynamic.

UICulture

Gets and sets the ID of the user-interface culture associated with the current request.

ViewBag

Gets a reference to the ViewBag dictionary that might contain data the controller needs to pass to the view object.

ViewData

Gets a reference to the ViewData dictionary that might contain data the controller needs to pass to the view object.

Table 2.  The properties of the Razor view object.

As a side note, it may helpful to recall the difference between Culture and UICulture. The Culture property in the table refers to a setting that influences culture-dependent aspects of a page, such as date, number, and currency formatting. The UICulture property instead determines which resources are loaded in multilingual applications. The culture is expressed in xx-yy format, where xx indicates the language and yy the culture. For example, en-us.

Summary

The Razor syntax is now quickly becoming the only one being used in ASP.NET MVC solutions. It is terse and clean and produces more readable markup than the ASPX syntax. All the other markup languages that appeared around the time of the first release of ASP.NET MVC have disappeared. So today Razor is the recommended choice for creating views in ASP.NET MVC. This article summarized the key aspects of the Razor syntax that you more commonly require when you write HTML views.

A Look at the Razor View Engine in ASP.NET MVC的更多相关文章

  1. Introducing “Razor” – a new view engine for ASP.NET

    原文发布时间为:2011-03-24 -- 来源于本人的百度文章 [由搬家工具导入] Razor :  cshtml扩展名,用@代替了那些复杂的“耳朵” <% %>  ne of the ...

  2. 使用Razor Generator构建模块化ASP.NET MVC应用程序

    在构建Web应用程序的时候,我们很难做到模块化的开发,这是因为Web应用程序不仅仅包含编译的C#代码,还包含了js.css和aspx等资源. 在ASP.NET MVC中,我们发布应用程序的时候,还会包 ...

  3. ASP.NET MVC学习笔记-----使用自定义的View Engine

    我们都知道在ASP.NET MVC中自带了Razor View Engine,Razor十分的强大,可以满足我们绝大部分的需要.但是ASP.NET MVC的高度可扩展性,使我们可以使用自定义的View ...

  4. ASP.NET没有魔法——ASP.NET MVC Razor与View渲染

    对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的界面呈现工作是由浏览器完成的,Web应用的原理是通过Http协议从服务器上获取到 ...

  5. ASP.NET没有魔法——ASP.NET MVC Razor与View渲染 ASP.NET没有魔法——ASP.NET MVC界面美化及使用Bundle完成静态资源管理

    ASP.NET没有魔法——ASP.NET MVC Razor与View渲染   对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的 ...

  6. Asp.net MVC razor语法参考

    Razor语法的快捷参考http://haacked.com/archive/2011/01/06/razor-syntax-quick-reference.aspx/ 只是copy下来便于查阅! I ...

  7. Use Razor for Email Template outside ASP.NET MVC

    原文发布时间为:2011-09-15 -- 来源于本人的百度文章 [由搬家工具导入] http://kazimanzurrashid.com/posts/use-razor-for-email-tem ...

  8. Razor 视图引擎 – ASP.NET MVC 4 系列

           Razor 视图引擎是 ASP.NET MVC 3 开始扩展的内容,并且也是默认视图引擎.        Razor 通过理解标记的结构来实现代码和标记之间尽可能顺畅的转换.下面的例子演 ...

  9. ASP.NET MVC 学习笔记-2.Razor语法

    1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“:”结尾.代码块中定义的变量可能会被同一个域中的其他块使用. ...

随机推荐

  1. Android中自动跳转

    先看效果图吧    -------->        -------->   Activity类 package com.xm; import java.io.File; import j ...

  2. [置顶] Android RadioButton与TextView浪漫约会?

    情景一 今天主要实现一个国家与地区切换,就是当我们选中RadioButton时然后将值设置到TextView中,听着这需求应该不难对吧?那么我们就开始约会吧? 看下原型图 准备条件: 首先需要一个ra ...

  3. apply 无循环拼接数组

    apply()第二个参数只能是数组,这个数组将作为参数传给原函数的参数列表arguments. 其实在实际开发中,JS 继承的方法并不止这一种,使用原型链继承是更加常用的方式,此外还有构造函数继承,这 ...

  4. php果然是世界上最好的语言

    这两天参加Hackathon,作为一个什么都半吊子的家伙,两人小队伍被逼上岗,于是我不得不着手写代码.由此,我体验到了php的魔力-- 首先,我深刻地意识到了更新版本的重要性. 偷懒不想搭Apache ...

  5. linux ls-al 指令详解

    ls -al 具体说明请自行找男人(man 中了鸟哥的毒 =.=).

  6. Bellman-Ford算法——解决负权边

    Dijkstra算法虽然好,但是它不能解决带有负权边(边的权值为负数)的图. 接下来学习一种无论在思想上还是在代码实现上都可以称为完美的最短路径算法:Bellman-Ford算法. Bellman-F ...

  7. docker 命令记录

    从 Docker 镜像仓库获取镜像的命令是 docker pull.其命令格式为: docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] 具体的选项 ...

  8. git身份验证失败清除密码缓存

    git config --system --unset credential.helper

  9. 有返回值的多线程demo

    package com.jimmy.demo.util; import java.util.HashMap;import java.util.concurrent.*;import java.util ...

  10. 双击 cui

    //改变属性块的双击事件 //将菜单文件中的双击改一下,退出时还原文件 acad.bak.cui 改这个名字 每次用这个更新为新的 acad.cui进行修改 //退出时再用 acad.bak.cui还 ...