Your First Razor page

In this lesson, we will introduce ASP.NET Core and Razor, the ASP.NET Core language for creating dynamic web pages.

What is ASP.NET Core?

ASP.NET Core is a .NET Core based framework for creating web applications. In turn, a framework may be defined as a logical architecture for creating a class of applications.

However, ASP.NET Core is much more than this, since, together with an architectural setting, it offers tools, libraries, and Razor. Razor is used for dynamically creating the content of web pages.

ASP.NET Core is the .NET Core / .NET 5 preferred choice for creating any type of web application. It is the evolution of the old ASP.NET running in the classic 4.x framework. Since it runs in .NET Core / .NET 5, applications are portable on a wide range of machines and operating systems that include Windows and most Linux distributions. Moreover, it has been optimized for dynamic link library (DLL) size and performance, and at the moment, it is probably the most performant and modular web framework available on the market.

Web applications are not necessarily-public web sites. They may also be private web sites running in a private network. Often also enterprise applications are implemented as private web sites because how easily they are deployed and updated.

Moreover, web applications are not necessarily made of web pages that are accessible with a web browser, but they may also contain the so-called web API, which is the web application way for interacting with other software instead of with humans.

This course focuses just on web applications designed for interacting with humans, and more specifically on Web applications that create HTML pages that users can visualize with a Browser.

Different types of browser-based web applications

Browser-based applications somehow create HTML content that is rendered in a Web browser. This HTML content can be created directly in the user browser or in the web server by an ASP.NET Core application and then sent to the user browser.

The first case is an example of a Single Page Applications (or SPA) because the web server sends the browser just a unique HTML page that works as a kind of frame for the HTML created in the browser itself. This frame page contains all references needed to download the whole application code from the server. Once the application code is downloaded, it creates and updates the HTML pages content, as needed.

SPAs get the data to show to the user by interacting with Web APIs.

However this course will focus on the second case: we’ll learn how to create the HTML that is rendered by the browser on the server-side. More specifically, on how to create the HTML content with ASP.NET Core and with a pattern called MVC (Model View Controller).

According to the MVC pattern, the user interface is split into logical code and graphic code. The logical code defines the pattern of interaction with the user, and what data to show on each HTML page, while the graphic code defines how to represent that data in HTML. The graphic code is enclosed in files called views while the logical code is enclosed in classes called controllers. Controllers and views communicate through objects called models that describe what data to represent in the HTML pages. We will describe the MVC pattern in detail later in this course.

Creating dynamic content with Razor

The focus of any browser-based application is to generate dynamic HTML, which is HTML content that is not fixed but depends on data extracted from a database or from any other source of information.

For example, when we go to a “movies-of-the-day” web page, we expect information on the movies we can watch that day, or in future days, rather than fixed list of movies.

The dynamic creation of HTML content is usually performed with the help of the so called HTML templates. Templates mix actual HTML with other syntactic constructs that, among other features, enable:

  1. The insertion of data contained in variables or class instances in the HTML
  2. The conditional selection of contents
  3. The repetition of template snippets on all elements of a collection

Imagine that we have a collection of objects that each contains information about a movie. We can build the HTML needed to show the user the full list of movies by running a template snippet on all objects in this collection.

Usually, templates are based on ad-hoc template-building languages. The ASP.NET Core templates-building language is called Razor.

Razor templates are organized into separate files called Razor pages or Razor views with the .cshtml extension. During application build, Razor files are transformed into C# classes that are compiled together with the remainder of the application.

We’ll explore Razor and Razor files in-depth later in this course.

The structure of an ASP.NET Core MVC application

Together with HTML templates, Razor files can also contain the code for retrieving retrieving all the data they need to feed templates. In this case, the Razor file is called a Razor page. It is assigned an URL so that it can be invoked directly by the user browser.

When using the MVC pattern, Razor files cooperate with other classes, called controllers, to produce HTML pages. More specifically, controllers handle the pattern of interaction with the user and prepare all the data that must be shown on the HTML page. The Razor files, on the other hand, are responsible for representing that data in HTML. Razor files that cooperate with controllers are called Razor views.

Besides controllers and Razor views, ASP.NET Core MVC applications contain other classes and files. Some of them have the usual role of conveying data and performing generic data processing, but some are specific to ASP.NET Core and are needed for the whole application to run properly. We will analyze each of them in detail throughout the course.

Running a Razor page

This chapter focuses on the Razor syntax, so we will not create controllers as prescribed by the MVC pattern. Instead, we will create independent Razor pages, each exposed on the web with its own URL.

A Razor page can be made independent by placing it in the Page project folder and by adding a @page directive at the beginning of its file as shown below:

Press + to interact
@using MyNamespace

Directives are placed at the beginning of the Razor.cshtml file and always start with a @. The first directive must be @page must be the first directive, so it must be placed at the beginning of the file.

After the code snippet shows a @using directive, it declares a namespace as the using ... statement in a usual C# class file. Therefore, after @using MyNamespace, we may avoid prefixing all types contained in the MyNamespace namespace with MyNamespace.

Later on, in this course, we will see other useful directives.

The URL of an independent Razor page depends on its path in the Pages project folder. More specifically, it is obtained by chaining the application URL with its path relative to the Pages folder. Below are some examples that clarify the concept with an application with a URL of https://localhost:5001.

Path URL
/Pages/MyPage.cshtml https://localhost:5001/MyPage
/Pages/Index.cshtml https://localhost:5001/Index or https://localhost:5001/
/Pages/Customers/Edit.cshtml https://localhost:5001/Customers/Edit
/Pages/Customers/Index.cshtml https://localhost:5001/Customers/Index or https://localhost:5001/Customers/

The examples above show that the page name Index has the peculiarity of mapping both to the /Index and to the / empty URL segments.

The simple ASP.NET Core Application shown below contains a single Index Razor page. You can try to edit the value of the Counter property, and the Razor template code and see what happens when you run the application.


    ViewData["Title"] = "Home page";

<div class="text-center">
    <h1 class="display-4">Welcome: @counter</h1>
    <p>Learn about <a href="">building Web apps with ASP.NET Core</a>.</p>

    private int counter = 0;
    public void OnGet()
        counter = 7;

    public void OnPost()
Passing data to a Razor template

Click on the “Run” button and wait for the application to compile. You can observe the compilation progress in the “Terminal” tab. When the compilation is complete, you can interact with the application by clicking the link at the bottom of the SPA widget.

In the @function block, we may define any member, that is, fields, properties, and methods. In particular, the OnGet and OnPost methods have a special meaning since they are invoked when the page URL receives a GET or a POST request, respectively. There are also async versions of them called OnGetAsync and OnPostAsync.

Here, we must place the code that computes the data used to customize the template that precedes the @function block. In the example above, we simply assign a value to the counter field.

Finally, properties and fields containing the computed data are invoked in the template block.