ASP.NET Core Razor Pages – Introduction

Introduction

With ASP.NET Core 2 around the corner, the hottest new thing that we are getting is Razor Pages. In one of the previous posts, we briefly mentioned ASP.NET Core Razor Pages.

Razor Pages is a new feature of ASP.NET Core that makes coding page-focused scenarios easier and more productive.

Initial impression of the public was that Razor Pages is easier and faster alternative to MVC for smaller apps that are solely page focused. However, it turns out that it just might be bigger than that. Since Razor Pages with ASP.NET Core 2 will be a default option when creating new apps (Empty, Razor Pages, Web API, MVC), it seems that ASP.NET team has big plans for Razor Pages and wants it to be #1 option when creating new web applications.

All of the Razor Pages types and features live in the Microsoft.AspNetCore.Mvc.RazorPages assembly. The MVC package – Microsoft.AspNetCore.Mvc includes the Razor Pages assembly. That means that you can use Razor Pages out of the box with MVC.

One of the advantages of Razor Pages is that it is straightforward to set up and get going. You create a new empty project, you add Pages folder, you add the Page, and you just write code and markup inside of your .cshtml file. Excellent for newcomers and an easy and fast way to learn about ASP.NET Core!

Why?

If you want to build few simple pages with MVC, you have controller actions in separate place, HTML for view in separate place, ViewModel in a different location, routes in separate place, and that just seems like too much.

With Razor Pages, you have this one Razor file (.cshtml), and the code for a single page lives inside of that file, and that file also represents the URL structure of the app (more about this later). Therefore, you got everything inside of one file, and it just works.

However, you CAN separate your code to the code behind file with .cshtml.cs extension. You would usually have your view model and handlers (like action methods in MVC) in that file and handle the logic there. Of course, you could also have your view model moved to separate place.

Creating Razor Pages app

With VS 2017 and .NET Core 2 SDK installed if we follow the old standard path in Visual Studio: File -> New Project -> Web -> ASP.NET Core Web Application we will get the following screen:

I did manually select Individual User Accounts as authentication type.

We can still accomplish the same via CLI:

dotnet new razor --auth Individual

After dotnet CLI creates a new project we get the following structure inside of our project:

The first thing you notice is that there are no Views folder and if we didn’t select Auth option there would be no Controllers folder either. However, in our case, we have AccountController and Account folder inside of Pages folder. Inside of that folder, we have Razor Pages and code that you could previously see in ~Views/Account folder:

Default location for Pages is Pages folder, but that can be changed.

Most of the Pages come with .cs file, which represents the model of the Page:

Inside of .cs files, we can define our logic, Handlers (actions), Model and all needed logic. We can also use it only as glue to the actual .cshtml page and handle only GET/POST/PUT/DELETE, and move the logic to separate class or layer/project.

One important thing to notice is that we need to define @page directive at the top of the .cshtml file. The @page directive tells Razor that this .cshtml file represents a Razor Page:

ASP.NET Core Razor Pages – Core features

Since Razor Pages is part of the MVC stack, we can use anything that comes with MVC inside of our Razor Pages.

Model binding

Model binding that we know from MVC also works with Razor Pages. Just like Action Methods in MVC Controllers, we have Handlers in Razor Pages code.

Consider the ChangePassword page with the following form inside of cshtml:

And the ChangePasswordModel class that lives inside of ChangePassword.cshtml.cs file:

And here is the InputModel class:

InputModel serves the function of ViewModel that we are accustomed to from MVC.

Handlers

We use handlers as methods to deal with HTTP requests (GET, POST, PUT, DELETE..). For example, we could have following methods:

OnGet / OnGetAsync

OnPost / OnPostAsync

OnDelete / OnDeleteAsync

These will be automatically picked up by ASP.NET Core based on the type of HTTP request.

Let’s go back to our previous example with ChangePassword. Part of the code from ChangePassword.cshtml.cs file:

The OnGetAsync and OnPostAsync are convention based names for Razor Pages handlers. Once you open the ChangePassword Page code inside of the OnGetAsync handler will execute. And once you submit a form from ChangePassword.cshtml page the OnPostAsync handler gets triggered.

Also, we can have all of our Page code living in our .cshtml file. For example, we could move those two functions from ChangePassword.cshtml.cs file to ChangePassword.cshtml:

The key to this is @functions directive, which enables function-level content inside of our Razor file.

Tag Helpers and HTML Helpers

We can also use all of existing Tag Helpers and HTML helpers inside of our Razor Pages. Also, we can create our own and use them within Razor Page.

Routing

I have small project setup at GitHub showing how can we do CRUD with Razor Pages – repository here. You do need .NET Core 2.0 Preview 3 (build 6764 should just work) or later and Visual Studio 2017.3 or later.

Here is the project structure with ALL of the files:

Besides two standard files Program.cs and Startup.cs everything is in Pages folder! Do notice that some of the Pages have matching code behind file.

As we mentioned previously, the location (path in the filesystem) of the Page in the project will determine the matching URL.

Here is a table with list of important Page files and routes that correspond to the Pages:

Path to the Page file URL matches ~Pages/Index.cshtml / or /Index ~Pages/Categories/Index.cshtml /Categories or Categories/Index ~Pages/Categories/Edit.cshtml /Categories/Edit/1 ~Pages/Categories/Create.cshtml /Categories/Create

Summary