📜 ⬆️ ⬇️

Razor - a new presentation engine in ASP.NET


One of the projects that my team was working on was the new presentation engine for ASP.NET.

ASP.NET MVC has always supported the concept of a “view engine”; in fact, it is a replaceable module that implements the choice of different template syntax. Today, the standard presentation engine for ASP.NET MVC uses similar files as ASP.NET Web Forms - .aspx / .ascx / .master. There are other popular ASP.NET MVC view engines - Spark and NHaml .

The new presentation engine we are working on is optimized for generating HTML code, focusing on the template code. The code name for this engine is “Razor”, the first beta version will be available soon.

Development goals


During the way we developed the prototype and evaluated the Razor, we identified several main objectives:
We spent the last few months developing applications using this technology, conducted usability studies with various volunteers, including non-.NET developers groups. Feedback from people was excellent.
')

Choice and Flexibility


The best feature in ASP.NET is to replace literally any part of the code. If a particular mechanism does not meet your needs, you can easily replace it with your own implementation.

With the next version of ASP.NET MVC, a new dialog box “Add-> View” will appear, which will allow you to choose the syntax for the new presentation template file. It allows you to easily select any available view engine installed on a local machine:

AddView9

Razor will be listed, as it will be integrated directly into ASP.NET MVC. All supporting methods and models will be available in both Razor and .ASPX presentation engines.

You will have the opportunity to combine and compare presentation templates written using different engines within one application or site. For example, you can create some views using .aspx, others with .cshtml or .vbhtml (Razor file extensions for C # and VB, respectively), and others with Spark or NHaml. Moreover, you can have a view template on one engine using a partial view written on another engine. You are the captain and choose what you need.

Hello World and Razor


Razor allows you to start with static HTML (or any textual content), further making it dynamic by adding server code. One of the main goals of Razor’s design was to provide a flexible coding process and allow the server code to be quickly integrated into the HTML markup with a minimum of effort.

To see a simple example, let's create a “hello world” example and display the following message:

image

What it looks like when using .ASPX code


If we are going to build the above “hello world” example using ASP.NET and the existing .ASPX syntax markup, we will need to use <% =%> blocks to define code areas inside the HTML markup:

image

I would like to share one observation for this example - each area of ​​the code requires 5 characters (<% =%>) for the beginning and end of the code sequence. Some of these characters (especially the% key, which is located in the upper center section on most keyboards) are not quite easy to type.

What it looks like with razor syntax


Note the beginning of the code area in Razor, where the @ symbol is used. Unlike <%%>, Razor does not require you to explicitly close the code area:

image

The Razor parser can semantically analyze C # / VB in code areas, which is why we don’t need to explicitly close the code block above. Razor can define the above statements as separate areas of the code and implicitly close them for us.

Even in such a trivial “hello world” example, we saved ourselves from 12 extra keystrokes that we would have had to do before. Type the @ symbol on the keyboard is much easier than the% character.

Loops and HTML Inline


Let's consider another case when you need to display a list of products (and the price opposite each):

image

Create an example with .ASPX


If we are going to implement an example using ASP.NET and the existing .ASPX syntax markup, we will need code that will dynamically generate a <ul> list with <li> elements for each product:

image

Create an example with the Razor


Below, I'll show you how to generate an equivalent view using Razor:

image

Notice how we started the foreach loop using the @ symbol, and then placed a line of HTML content with blocks of code inside. Since the Raptor parser understands the semantics of C # in our blocks, it can determine that the content <li> should be inside foreach and treats it as content that should be looped. It also recognizes the closing} and stops foreach.

Razor is also smart enough to recognize the @ p.Name and @ p.Price expressions inside the <li> element as server-side code and execute it for each loop pass. Note that Razor automatically closes the @ p.Name and @ p.Price code areas based on the combined use of HTML and code.

The ability to write code in this way without having to add a lot of opening and closing tags across the entire template makes the whole development process really fast.

If blocks and multiline expressions


Below are a few examples of common situations:

If expressions


As in the foreach example, you can position the content inside if statements (or other C # or VB language structures), without explicitly specifying the beginning / end of code areas. For example:

image

Multi-line expressions


You can designate several lines of code by wrapping them into an @ { code } block as follows:

image

Please note that variables can be broken up into several server blocks of code, the “message” variable is declared in the multiline @ {} block, and also used in the message code block. Just like in the .aspx syntax of the <%%> and <% =%> files.

Complex expressions


The @ () syntax allows you to place complex expressions. For example, we can rewrite the above code to concatenate a string and a number together, inside the @ (code) block:

image

Content and Code Integration



The Razor parser knows many features of the language, allowing you to fully trust it, and not spend time on your own implementation.

Does it conflict with email addresses and other places of use @ in HTML?


The Razor parser is smart enough to determine in most cases whether the @ symbol is used in code or in static content. For example, below I use the @ symbol as part of the email address:

image

While parsing the file, Razor analyzes the content to the right of the @ symbol and tries to determine whether this part is C # code (if it is a CSHTML file) or VB (if it is a VBHTML file), or it is static data. The above code will output the following HTML (where the email address will be displayed as static content, and @ DateTime.Now will be defined as code):

image

In the case where the content is valid, as a code, and you want to display it as static, it is enough to explicitly specify two @@ characters instead of one.

Defining Attached Content


When placing HTML content inside if / else, foreach, or other block expressions, you should wrap the internal contents of the HTML or XML elements to better define the beginning of the content area.

For example, below, I wrapped a multi-line block of content (which includes curly braces) in the <span> tag:

image

This will generate the following code for the client, including the <span> element:

image

Optionally, you can wrap the attached content in the <text> block in cases where your data should be generated for the client without the wrapper tag:

image

This code will generate the following content for the client, please note - no wrapping tags:

image

HTML coding


By default, content using the @ block is automatically HTML-coded for improved protection against XSS attacks.

Layout / MasterPage - The Basics


It is very important to have a uniform appearance on all pages of your website or application. ASP.NET 2.0 introduced the concept of “master pages” that can help achieve this result when using .aspx pages or templates. Razor also supports this concept using “layout pages”, which allow you to define a site template and then inherit views / pages from it.

The simplest example layout


Below is a simple example of a page layout that we will save under the name “SiteLayout.cshtml”. It can contain any static HTML, as well as any dynamic server code. Next, add a call to the “RenderBody ()” helper method in the place where we want to display a specific content body for the requested URL:

image

Next, we can create a presentation template called “Home.cshtml”, which contains only the necessary code or content to build a specific body of the requested page and is based on the layout template:

image

Notice how you explicitly set the “LayoutPage” property in the code of our Home.cshtml file. This means that we want to use the SiteLayout.cshtml template as the layout for this view. We can also set the layout file directly in the ASP.NET MVC controller, specifying Home.cshtml as a presentation template or by setting it with a standard layout for the site (in this case, we define it in one project file and all presentation templates pick it up automatically)

When we generate Home.cshtml as a presentation template, it will merge the contents of the layout and sub-pages, and send the contents to the client:

image

Compact, clean and expressive code


I would like to draw attention to the code above and note that the definition of the layout and its use from the views / pages is small. The code in the screenshot contains all the contents of the SiteLayout.cshtml and Home.cshtml files, there are no additional settings or tags, there is no % @ Page% prefix and no other different markup or specified properties.

We try to keep the code you write in the most compact and simple form. We also want to allow anyone to open files in a third-party text editor and change the code. No additional code generation or intellisense is required.

Layout / MasterPage - Add Replaceable Parts


Page layout supports the ability to define various “sections” within that can change the presentation with their own content. This allows you to easily change / fill intermittent content sections on a layout page and provides layout flexibility for your site.

For example, we can go back to our SiteLayout.cshtml and define two sections within the layout that can change the presentation. Let's call these parts “menu” and “footer” and specify what to fill out from optional by passing the optional = parameter to the RenderSection () helper (we do this using the new optional parameters in C #, which I already mentioned)

image

Since the two sections are marked as “optional”, I do not have to define them in my Home.cshtml file. My site continues to work fine, even if they are not there.

Let's go back to Home.cshtml and declare our own Menu and Footer parts. The screenshot below contains all the code for Home.cshtml, nothing else is required. However, I moved the LayoutPage settings to the global level, so they are no longer there.

image

Our own sections overwrite “menu” and “footer” using the @section blocks declared in the file. We decided not to require wrapping the contents of “main / body” inside the section, but instead just to leave it as a string (this reduces the number of clicks and allows you to easily add sections to the layout page without requiring you to go over all pages by changing their syntax)

When we again generate Home.cshtml as a presentation template, it will merge the content of the layout and sub-pages, integrating the two new parts of the page and return the following to the client:

image

Encapsulating and reusing HTML helpers


We looked at how to provide a unified look for the website using the layout pages. Let's now look at how to create reusable HTML helper methods that give us clean encapsulation for generating HTML, and which we can use in our site or even across several different sites.

HTML software helpers


Today, ASP.NET MVC has helper methods that can be called in blocks of code and that encapsulate HTML generation. And they are implemented only in the form of code (most often, as extension methods). All existing HTML extension methods created with ASP.NET MVC will also work when using “Razor”:

image

Declarative HTML Helpers


Generating HTML based on a single class of code works, but is not perfect.

One of the features in Razor is a simple way to create reusable HTML helpers using a more declarative approach. Our plan is to enable you to declare reusable helpers with the helper {} declarative syntax, as shown below.

image

You will be able to place .cshtml files that contain these helpers in the Views \ Helpers directory and subsequently re-use them in any view or page on your site (no additional action is required):

image

Notice how the ProductListing () helper defines the arguments and parameters. You can pass any parameters you want (including optional parameters, types that allow NULL values, generics, etc.). You can also debug this code in Visual Studio.

Important: the helper syntax will not be available in the first beta of Razor, we hope it will be available in future versions. Auxiliary methods designed in the form of code will work immediately.

Passing String Templates as Parameters


Another useful (and unrealistically powerful) feature that we provide with Razor is the ability to pass “string template” parameters to helper methods. These “string patterns” can contain both HTML and code, and can be invoked at the request of a helper method.

Below you see an example of this functionality in action, I use the HTML “Grid” helper that generates the DataGrid for the client:

image

A call to the Grid.Render method is C #. We use new named parameters in C # to pass strongly typed arguments to the Grid.Render method, this feature gives us the complete completion of expressions with instellisense and validation during compilation.

The “format” parameter, which we pass when we declare a column, is a “string template”, it contains both html and code, we can also customize the data format. And the most beautiful thing is that the Grid helper can call our string pattern as a delegate method, and can call it when needed and how many times it wants. In this case, it will call each time it generates a string and passes it to an “element” that our template can use to display the result.

This feature will allow you to develop more powerful HTML helper methods. You can implement them both in code (as you do today) and using the helper {} declarative approach.

Support in Visual Studio


As I noted earlier, one of the main goals of Razor is to minimize the number of keystrokes, as well as easily edit the code with any text editor. We tried to keep the syntax clean, compact and simple.

Despite this, we designed Razor so that you could get all the convenience of editing code in Visual Studio. We will provide full support for HTML, JavaScript and C # / VB code in intellisense in Razor files:

image

Notice how the intellisense for the Product object worked on “@p .”, Inside the <li> element. Note that in the Solution Explorer in the \ Views folder there are both presentation templates .aspx and .cshtml. You can use different presentation engines in a single application, giving you the opportunity to experience what syntax you like.

findings


We think “Razor” provides a new, elegant presentation engine for code-oriented templates. The programming process will be quick and fun. The syntax is compact and reduces the number of keystrokes, while at the same time improving the readability of your markup and code. In the next version of ASP.NET MVC engine will be built into the system. You can delete .cshtml / .vbhtml files in your application and run them as separate pages, which also allows you to use them in ASP.NET Web Forms applications.

All the developers who tested the project in the last few months have left extremely positive reviews. We are going to provide a public beta, as soon as possible and of course we expect to hear your opinion.

Source: https://habr.com/ru/post/98241/


All Articles