Getting Started With Razor Pages In ASP.NET Core 2.0

ASP.NET Core 2.0 has introduced several new features and a new project template is among these new features. Microsoft has introduced some new project templates that help us to create new types of applications, except for MVC and Web API. Now, we can create Razor Page applications and SPA applications using Angular or React. Today, we will talk more about Razor pages - what actually a Razor page is, how to create Razor page applications, and some of the fundamentals of Razor pages.

Razor Page is much like MVC and has most of the features of MVC, however, unlike MVC focusing on the controller, it focuses on UI implementation.

Why Razor Page?

The first question that comes to mind while reading about Razor page is "Why Razor Page instead of MVC?". To answer this question in one line, we can say "When focusing on UI or giving priority to UI rather than the complex structure or data logic, we can go with Razor Page rather than MVC".

Actually, in an MVC project which has a Controller, View, Model, View-Model, Routing etc. grouped together to run your application, if you are adding or modifying one single functionality (like want to add one new property), then you have to make changes inside ViewModel, its corresponding Entity, its Mapping Data, as well as its View.

But Razor Page is only for small applications where you have to mainly focus on View. If you make any changes, then you have to manipulate your Razor Page [.cshtml]. Server-side logic can be written on the Razor Page as well, using the @function directive. If you want to make a separate file to your logic, then you can create a code-behind file that inherits PageModel.

Create Razor Page Application

To create a Razor Page application, you should have Visual Studio 2017 with version 15.3 or above with .NET Core SDK 2.0 installed on your system. You can download .NET Core SDK 2.0 from Here and update your Visual Studio using “Visual Studio Installer”.

For creating a new Razor Page application, go to File >> New >>Project - as usual, we do for creating a new project.

From the "New Project" window, choose .NET Core from the left panel and “ASP.NET Core Web Application” from the center panel. then, provide the name of the application and location to save it and click OK.

New Project

From the next window, you have to choose the template which is responsible for creating a Razor page. Select “Web Application” as shown in the below image. Change the authentication to “No Authentication” and click OK.

Razor page

After clicking OK, it will take a few seconds to configure your Razor Page Application. And finally, it will create your app as follows.

NuGet

Above is the basic structure of the Razor Page. It is much like an MVC application but here, you can see there are no Controller and Model folders. It has an important folder “Pages” which contains all the Razor pages and their corresponding code-behind files. The code-behind files or Model Pages are basically used for separation of concern. Other things, like Programs. cs and Startup. cs are most likely similar to MVC.

Now, you can run the application and see the output as in the below screenshot.

ASP.NET Core

To add a new Razor page, just right-click the Pages folder or any folder inside Pages and choose Add > Razor Page to add directly.

Pages Folder

It will open a new window, from where you can choose your Razor page's actual type. You might be using Razor with Entity Framework or you would like to write CRUD code automatically using the Scaffold feature.

 CRUD Code

Templating

The common Razor template is the same as MVC like “_viewStart.cshtml”, “_layout. cshtml”, “about. cshtml” etc., but only folder structure has changed here with Razor Pages. In MVC, these have their predefined folders - for a common template, we use a “Shared” folder inside the View folder and every functionality has its own View folder like Home, Employee, etc.

@Page

Every Razor page has an @Page directive which indicates that this is not a normal MVC Razor View but it is a Razor Page.

@page
@model AboutModel
@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@Model.Message</h3>
<p>Use this area to provide additional information.</p>

Code Behind or Model Page

To write server-side logic, we can create a code behind cshtml.cs file as the following code shown which contains all the server side login, like getting the data from the server, and posting the data on the server. Here, we use the OnGet and OnPost handler to get and post the data.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace RazorPagesExample.Pages
{
    public class AboutModel : PageModel
    {
        public string Message { get; set; }
        public void OnGet()
        {
            Message = "Your application description page.";
        }
    }
}

Razor Page without Code Behind file.

Model Binding

We can bind the property directly with Razor Page using the [BindProperty] attribute. Property decorated with [BindProperty] attribute will automatically be available on the Razor page.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace RazorPagesExample.Pages.Employee
{
    public class IndexModel : PageModel
    {
        [BindProperty]
        public Employee employee { get; set; }

        public void OnGet()
        {
        }
        public void OnPost()
        {
            var data = employee;
        }
    }
    public class Employee
    {
        public int ID { get; set; }
        [Required]
        [StringLength(50, ErrorMessage = "Name length should be 1 to 50.")]
        [Display(Name = "Employee Name")]
        public string Name { get; set; }
        [Required]
        [StringLength(255, ErrorMessage = "Address length should be 1 to 255.")]
        [Display(Name = "Address")]
        public string Address { get; set; }
    }
}

On the Razor page, just use the name of the property and bind the input control with this.

@page  
@model RazorPagesExample.Pages.Employee.IndexModel  

@{  
    ViewData["Title"] = "Employee Page";  
}  
<h2>@ViewData["Title"]</h2>  
<div class="row">  
    <div class="col-md-6">  
        <form method="post">  
            <div class="form-group">  
                <label asp-for="employee.Name"></label>  
                <input asp-for="employee.Name" class="form-control" />  
                <span asp-validation-for="employee.Name" class="text-danger"></span>  
            </div>  
            <div class="form-group">  
                <label asp-for="employee.Address"></label>  
                <input asp-for="employee.Address" class="form-control" />  
                <span asp-validation-for="employee.Address" class="text-danger"></span>  
            </div>  
            <button type="submit" class="btn btn-default">Add Employee</button>  
        </form>  
    </div>  
</div>  

Model Auto-Updating

A defined model with the Razor page will update automatically on the Code-Behind file. You don’t need to take care to bind your model with specific operations. Any changes inside the model data will be reflected in the Model itself.

You can see with the above code if you click on the “Add Employee” button and pass the correct data to avoid the error then data will bind with the model and reflect on the OnPost handler as follows. Here we are not passing the model as a parameter as we do in MVC.

Model

Tag Helpers

As we all know tag helper is basically a feature of Asp.Net MVC and has been included with Razor Page. Now you can bind your data with Razor Page directly using Tag Helpers. As the following code shows, we are using so many Tag Helpers here like “asp-for”, “asp-validation-for” etc.

<form method="post">
    <div class="form-group">
        <label asp-for="employee.Name"></label>
        <input asp-for="employee.Name" class="form-control" />
        <span asp-validation-for="employee.Name" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="employee.Address"></label>
        <input asp-for="employee.Address" class="form-control" />
        <span asp-validation-for="employee.Address" class="text-danger"></span>
    </div>
    <button type="submit" class="btn btn-default">Add Employee</button>
</form>

Handlers

We use handlers to perform server-side operations like getting the data, and posting the data. These handlers are something like HTTP Verb we use in MVC like Get(), Post(), etc.

As a prefix, we use “On” with HTTP Verb in Razor Page which indicates as an event or handlers as OnGet() or OnGetAsync(), OnPost() or OnPostAsync(), etc.

Routing

As compared to MVC routing, Razor Page routing is very simple. We don’t have to write code manually for simple routing. All the pages inside the Pages folder will be called by file name after domain name.

  • http://localhost:51068/index
  • http://localhost:51068/about
  • http://localhost:51068/employee/index

If you would like to pass parameters with a URL then you can add it with the @page directive as follows. Here you can see I am passing one ID which is an integer type.

@page "{id:int}"
@model RazorPagesExample.Pages.Employee.IndexModel
@{
    ViewData["Title"] = "Employee Page";
}

So, when you call the URL, you have to pass the ID which should be integer type as below URL.

http://localhost:51068/employee/index/1

Razor Page Location Routing URL
/Pages/Index.cshtml / OR /index
/Pages/About.cshtml /about
/Pages/Employee/Index.cshtml /employee OR /employee/index
/Pages/Employee/Index.cshtml with ID parameter /employee/index/1


Security

When we talk about security with Razor Page like a CSRF attack, we don’t need the manual code to protect our application from the outer world as we do in MVC. We don’t need to add an AntiRequestForgery Token or verify it. These tasks are done by Razor Page automatically internally.

Conclusion

So today, we have learned what Razor pages are in ASP.NET Core 2.0, and what their fundamentals are.

I hope this post will help you. Please put your feedback in the comments which helps me to improve myself for the next post. If you have any doubts, please do not hesitate to ask and if you like this post, please share it with your friends.