{"id":1723,"date":"2013-11-14T00:00:00","date_gmt":"2013-11-14T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/a-look-at-the-razor-view-engine-in-asp-net-mvc\/"},"modified":"2021-05-17T18:34:54","modified_gmt":"2021-05-17T18:34:54","slug":"a-look-at-the-razor-view-engine-in-asp-net-mvc","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/a-look-at-the-razor-view-engine-in-asp-net-mvc\/","title":{"rendered":"A Look at the Razor View Engine in ASP.NET MVC"},"content":{"rendered":"<div id=\"pretty\">\n<p class=\"start\">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&#8217;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. <\/p>\n<p>The internal architecture of ASP.NET MVC is  quite different in the way requests are processed. Not only&#160; 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 <code>ActionResult<\/code> type. When it comes to generating HTML, the  action result generator gets the more familiar name of the view engine.<\/p>\n<p>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; &#160;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.<\/p>\n<h2>Razor View Engine<\/h2>\n<p>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&#160; C# or VB, &#160;&#160;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. <\/p>\n<p>The location of view templates is rooted in the <i>Views<\/i> folder. The <i>Views<\/i> 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 <i>.cshtml<\/i> for the Razor view engine. If you&#8217;re writing your ASP.NET MVC application in Visual Basic, then the  extension must be <i>.vbhtml<\/i>. 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 <i>Shared<\/i> directory.  <\/p>\n<p>It is important to note that the same hierarchy  of directories that exists at the project level under the <i>Views<\/i> 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. <\/p>\n<p>Table 1 shows the location properties supported  by the Razor view engine with the predefined value.&#160; <\/p>\n<table class=\"MsoTableLightList\">\n<tbody>\n<tr>\n<td valign=\"top\">\n<p><b>Property<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b> \t\tDefault location format<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i>AreaMasterLocationFormats<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t~\/Areas\/{2}\/Views\/{1}\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/Shared\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t~\/Areas\/{2}\/Views\/{1}\/{0}.vbhtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/Shared\/{0}.vbhtml<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i> \t\tAreaPartialViewLocationFormats<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/{1}\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/{1}\/{0}.vbhtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/Shared\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/Shared\/{0}.vbhtml<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i> \t\tAreaViewLocationFormats<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/{1}\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/{1}\/{0}.vbhtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/Shared\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Areas\/{2}\/Views\/Shared\/{0}.vbhtml<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i> \t\tMasterLocationFormats<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t \t\t~\/Views\/{1}\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/Shared\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/{1}\/{0}.vbhtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/Shared\/{0}.vbhtml<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i> \t\tPartialViewLocationFormats<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t \t\t~\/Views\/{1}\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/{1}\/{0}.vbhtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/Shared\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/Shared\/{0}.vbhtml<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i> \t\tViewLocationFormats<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t \t\t~\/Views\/{1}\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/{1}\/{0}.vbhtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/Shared\/{0}.cshtml<\/p>\n<p class=\"TableText\"> \t\t \t\t~\/Views\/Shared\/{0}.vbhtml<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"TableText\"><b><i> \t\tFileExtensions<\/i><\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"TableText\"> \t\t.cshtml,  \t\t.vbhtml<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"caption\"><b>Table 1.&#160; The default location formats of the Razor view engine.<\/b><\/p>\n<p>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.<\/p>\n<p>I&#8217;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. &#160;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 <b>global.asax<\/b> just when the application starts up. Here&#8217;s a sample  implementation of <strong>Application_Start <\/strong>that removes the ASPX engine that only supports the Razor engine.  <\/p>\n<pre>protected void Application_Start()\n{\n&#160;&#160;&#160; ViewEngines.Engines.Clear();\n&#160;&#160;&#160; ViewEngines.Engines.Add(new RazorViewEngine());\n}<\/pre>\n<p>View engines are referenced via the <b>ViewEngines.Engines<\/b> collection. In the sample code, you first clear out the  collection and then add just the engine instance that you&#8217;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.<\/p>\n<h2>Razor Nuggets<\/h2>\n<p>I&#8217;ve already described &#160;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&#8217;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&#8217;s  a first basic example of a code nugget.<\/p>\n<pre>&lt;h2&gt;@ViewBag.Header&lt;\/h2&gt;<\/pre>\n<p>Nuggets can be used in loops to generate for  example the rows of a HTML table, as below:<\/p>\n<pre>&lt;table&gt; &#160;&#160;&#160;\n@foreach (var person in Model.People) {\n&#160;&#160;&#160; &lt;tr&gt;\n&#160;&#160;&#160;&#160;&#160;&#160; &lt;td&gt;&lt;%: person.Name %&gt;&lt;\/td&gt;\n&#160;&#160;&#160;&#160;&#160;&#160; &lt;td&gt;&lt;%: person.Country %&gt;&lt;\/td&gt;\n&#160;&#160;&#160; &lt;\/tr&gt;\n}\n&lt;\/table&gt;<\/pre>\n<p>Nuggets can contain any executable line of code  as long as it is prefixed with @. Here&#8217;s an example of how you import a namespace:<\/p>\n<pre>@using System.Net;<\/pre>\n<p>And here&#8217;s how you create a HTML form:<\/p>\n<pre>@using (Html.BeginForm()) {\n&#160;&#160; &lt;fieldset&gt;\n&#160;&#160;&#160;&#160;&#160;&#160; :\n&#160;&#160; &lt;\/fieldset&gt;\n}<\/pre>\n<h2>Special Expressions &#160;<\/h2>\n<p>Usually, a nugget consists of a single line of  code. However, you can expand it to multiple lines by using an <code>@{ code } <\/code>block:<\/p>\n<pre>@{\n&#160;&#160; var city = \"London\";\n}\n:\n&lt;p&gt;@city&lt;\/p&gt;<\/pre>\n<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<code> @{...}<\/code> 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:<\/p>\n<pre>@{\n&#160;&#160;&#160; var theString = GetSomeString();\n&#160;&#160;&#160; if(theString.Length &gt; 10)\n&#160;&#160;&#160;&#160;&#160; &lt;p&gt;Text too long&lt;\/p&gt;\n&#160;&#160;&#160; else\n&#160;&#160;&#160;&#160;&#160; &lt;text&gt;Text ok&lt;\/text&gt;\n}<\/pre>\n<p>If the markup content you&#8217;re emitting is wrapped  up by HTML tags, then the parser will properly recognize it as markup. If it&#8217;s plain text (i.e., just a text string)  then you must wrap it in a Razor-specific <b>&lt;text&gt;<\/b> for the parser to handle it  correctly.<\/p>\n<p>If you &#160;wish  to emit &#160;a value that &#160;results from an  expression, &#160;then you can wrap it &#160;in round  brackets:<\/p>\n<pre>&lt;span&gt; @(\"I love \" + city) &lt;\/span&gt;<\/pre>\n<p>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, &#160;without encoding, then you can resort to using the Html.Raw helper method:<\/p>\n<pre>@Html.Raw(Strings.HtmlMessage)<\/pre>\n<p>Most of the time, the Razor parser is smart  enough to figure out from the context the reason why you&#8217;re using the @ symbol, whether it&#8217;s to denote a code nugget or  perhaps a literal email address. If you hit an edge case that the parser can&#8217;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. <\/p>\n<p>Finally, when inside multiline code nuggets @{  &#8230; }, you use the C# syntax to place comments. You can comment out an entire block of Razor code using the @* &#8230; *@  syntax instead:<\/p>\n<pre>@*\n&lt;div&gt; Razor markup here &lt;\/div&gt;\n*@<\/pre>\n<p>The Visual Studio toolbar buttons for commenting  blocks in and out support the Razor syntax nicely.<\/p>\n<h2>Conditional Nuggets in ASP.NET MVC 5<\/h2>\n<p>Razor now supports conditional attributes that  are emitted only if the Razor expression evaluates to a non-null string. Let&#8217;s consider the following markup:<\/p>\n<pre>&lt;div class=\"@cssClassName\"&gt;\n&#160;&#160; ...\n&lt;\/div&gt;<\/pre>\n<p>If the variable <i><strong>cssClassName<\/strong><\/i> is empty or null you may not want the <i>class<\/i> attribute to be emitted. In ASP.NET MVC 5, some conditional logic built  into the Razor engine makes it happen automagically. <\/p>\n<p>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. <\/p>\n<h2>URL Auto-completion<\/h2>\n<p>&#160;For quite some time in Razor you had to explicitly  complete the URL for images and script files using the <b>Url.Content<\/b> method, as  shown below:<\/p>\n<pre>&lt;script src=\"@Url.Content(\"~\/content\/scripts\/somefile.js\")\"&gt;&lt;\/script&gt;<\/pre>\n<p>It is now possible to avoid that as Razor automatically expands the tilde character in HTML  elements. <\/p>\n<pre>&lt;script src=\"~\/content\/scripts\/somefile.js\"&gt;&lt;\/script&gt;<\/pre>\n<p>It is interesting to notice that this will work only within HTML elements.&#160; In other words, if your page contains C# or script code that defines a relative URL with a tilde &#160;then it &#160;won&#8217;t be automatically expanded  and so the only alternative is to &#160;resort to <b>Url.Content<\/b>.<\/p>\n<h2>Properties of the Razor View Object<\/h2>\n<p>When the Razor view engine is used, the  resulting view object is an instance of the <b>WebViewPage<\/b> class defined in the <b>System.Web.Mvc<\/b> 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:<\/p>\n<table class=\"MsoTableLightList\">\n<tbody>\n<tr>\n<td valign=\"top\">\n<p><b> \t\tProperty <\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p><b> \t\tDescription<\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Ajax<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets an instance of the AjaxHelper class  \t\tused to reference Ajax HTML helpers around the template.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Culture<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets and sets the ID of the culture associated with the  \t\tcurrent request. <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Href<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Converts any path you create in code  \t\t(which can include the ~ operator) to a path that the browser can understand.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Html<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets an instance of the HtmlHelper class used to reference  \t\tHTML helpers in the template.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Context<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets the central repository to gain access  \t\tto various ASP.NET intrinsic objects: Request, Response, Server, User, and so forth.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>IsAjax<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Returns true if the current request was initiated by the  \t\tbrowser&#8217;s Ajax object.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>IsPost<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Returns true if the current request was  \t\tplaced through an HTTP POST verb. <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Layout<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets and sets the path to the file containing the master  \t\tview template.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>Model<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets a reference to the view model object  \t\t(if any) containing data for the view. This property is of type <i>dynamic<\/i>.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>UICulture<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets and sets the ID of the user-interface culture  \t\tassociated with the current request. <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>ViewBag<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets a reference to the ViewBag dictionary  \t\tthat might contain data the controller needs to pass to the view object.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p><b>ViewData<\/b><\/p>\n<\/td>\n<td valign=\"top\">\n<p>Gets a reference to the ViewData dictionary that might  \t\tcontain data the controller needs to pass to the view object.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"caption\"><b>Table 2.&#160; The properties of the Razor view object.<\/b><\/p>\n<p>As a side note, it may helpful to recall the  difference between <b>Culture<\/b> and <b>UICulture<\/b>. The <b> Culture<\/b> property in the table refers to a setting that influences culture-dependent aspects of a page, such as date,  number, and currency formatting. The <b>UICulture<\/b> property instead determines which resources are loaded in multilingual applications. The culture  is expressed in xx-yy format, where <strong>xx<\/strong> indicates the language and<strong> yy<\/strong> the culture. For example, en-us.<\/p>\n<h2>Summary<\/h2>\n<p>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.<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Razor is now the dominant markup language for ASP.NET MVC applications, since it is terse and produces more readable markup than the ASPX syntax.  Now with conditional nuggets and URL auto-completion, it is the obvious choice, as Dino explains.&hellip;<\/p>\n","protected":false},"author":221911,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[4143,4156,4157,5166],"coauthors":[],"class_list":["post-1723","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","tag-net","tag-asp","tag-asp-net","tag-mvc"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1723","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221911"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1723"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1723\/revisions"}],"predecessor-version":[{"id":40967,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1723\/revisions\/40967"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1723"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}