A Look at the Razor View Engine in ASP.NET MVC

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.

时间: 2024-10-27 02:49:06

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

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

对于Web应用来说,它的界面是由浏览器根据HTML代码及其引用的相关资源进行渲染后展示给用户的结果,换句话说Web应用的界面呈现工作是由浏览器完成的,Web应用的原理是通过Http协议从服务器上获取到对应的Html代码以及相关资源,使得浏览器能够完成正确的呈现工作. ASP.NET MVC作为一个Web应用构建框架View承担了UI显示的功能,在开发过程中View以Action的名称命名,当用户的请求被路由到某一Action方法时,ASP.NET MVC将会根据Action的名称来获取到对应的V

Razor in ASP.NET MVC 3.0

ASP.NET MVC 3.0中,提供了新的View Engine:Razor,使用的方式和以往没有差别很大,不过写法却显得的更简单俐落:以往费事的,被简化成短短的@,如果需要声明多行,则只需要利用@{}包起来就可以了!对我来说,最棒的是排版的时候漂亮超多XD 下图是基本的Razor View: @model 声明该页的Model类型 @Layout 声明想要套用的MasterPage名称(如果不需要套用就是null) @View.Title 页面标题 除了在页面声明之外,你还可以用一个更简单的

Razor 视图引擎 &ndash; ASP.NET MVC 4 系列

       Razor 视图引擎是 ASP.NET MVC 3 开始扩展的内容,并且也是默认视图引擎.        Razor 通过理解标记的结构来实现代码和标记之间尽可能顺畅的转换.下面的例子演示了一个包含少量视图逻辑的简单 Razor 视图: @{ // this is a block of code. For demonstration purposes, // we'll create a "model" inline. var items = new string[] {

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

1.         表达式 表达式必须跟在“@”符号之后, 2.         代码块 代码块必须位于“@{}”中,并且每行代码必须以“:”结尾.代码块中定义的变量可能会被同一个域中的其他块使用.比如,定义在视图顶部的变量可以被同一视图中的代码块和代码段访问. 3.         布局 Razor通过layouts保持网页外观布局的一致性.布局模板包含基本的标签,并可以指定渲染视图内容的位置.比如 基本布局文件(_Layout.cshtml) <!DOCTYPE Html> <ht

ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中

ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NET MVC搭建项目后台UI框架—4.tab多页签支持 ASP.NET MVC搭建项目后台UI框架—5.Demo演示Controller和View的交互 ASP.NET MVC搭建项目后台UI框架—6.客户管理(添加.修改.查询.分页) ASP.NET MVC搭建项目后台UI框架—7.统计报表 ASP.NE

ASP.NET MVC 3: Razor的@:和语法

来自森大科技官方博客,排版更好! http://www.cnsendblog.com/index.php/?p=115 这是我正在写的博文系列中的另一篇,涵盖ASP.NET MVC 3的一些新功能: http://weblogs.asp.net/scottgu/archive/2010/10/19/asp-net-mvc-3-new-model-directive-support-in-razor.aspx Razor中的布局10月22日) 用Razor实现服务器端注释(11月12日) Razo

Express (Routing、Middleware、托管静态文件、view engine 等等)

1. Express 简介 Express 是基于 Node.js 平台,快速.开放.极简的 web 开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用. Express 不对 Node.js 已有的特性进行二次抽象,我们只是在它之上扩展了 Web 应用所需的基本功能. Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件. API 方面:丰富的 HTTP 快捷方法和任意排列组合的

ASP.NET MVC 出现错误 “The view &#39;XXX&#39; or its master was not found or no view engine support”

来自:http://www.dengyukeji.com/archiver/tid-151.html 错误如下:The view 'XXX' or its master was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/XXX/XXX.aspx ~/Views/XXX/XXX.ascx ~/Views/Shared/XXX.

The view or its master was not found or no view engine supports the searched locations

Error like:The view 'LoginRegister' or its master was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/MyAccount/LoginRegister.aspx ~/Views/MyAccount/LoginRegister.ascx ~/Views/Shared/LoginRe