Razor Pages

Razor Pages is a page-focused programming model for building web UI with ASP.NET Core. It makes it easier to build cohesive sets of Razor files—including Razor markup, C#, and other code—that work together to present data. Razor Pages is built on top of MVC and is recommended for scenarios where you are building page-centric application functionality.

It simplifies the development of Razor-based web applications by providing a cleaner separation between concerns and a more intuitive structure compared to traditional MVC controllers and views, especially for scenarios involving many distinct pages.

Razor Syntax

Razor is a templating engine used for creating dynamic web pages. It allows you to embed server-side C# code within HTML using a special syntax:

  • @ symbol is used to transition from HTML to C# code.
  • @variableName displays the value of a variable.
  • @{ ... } block for multiple C# statements.
  • @if, @foreach, @using, etc., for control flow.
@page @model IndexModel @{ ViewData["Title"] = "Home page"; } <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Current time on server: @DateTime.Now</p> </div>

Page Model

Each Razor Page is typically associated with a "Page Model" class, which inherits from PageModel. This class handles the logic for the page, such as retrieving data, processing form submissions, and exposing properties and methods to the Razor markup.

// Pages/Index.cshtml.cs using Microsoft.AspNetCore.Mvc.RazorPages; public class IndexModel : PageModel { public string Message { get; set; } public void OnGet() { Message = "Hello from the Page Model!"; } }

The Razor file (Index.cshtml) uses the @page directive and the @model directive to link to its Page Model:

@page @model IndexModel @{ ViewData["Title"] = "Index Page"; } <h1>@Model.Message</h1> <p>This is a Razor Page example.</p>

Routing

Razor Pages uses a file-based routing convention. The URL path for a Razor Page is derived from its file path relative to the Pages folder.

  • Pages/Index.cshtml maps to /
  • Pages/About.cshtml maps to /About
  • Pages/Products/List.cshtml maps to /Products/List

You can customize routing using the @page directive with an explicit route template:

@page "/my-custom-url" @model MyCustomPageModel

Layouts

Layouts allow you to define a common structure for multiple Razor Pages, such as headers, footers, and navigation bars. By default, Razor Pages uses the _Layout.cshtml file found in the Pages/Shared folder.

To specify a different layout or no layout, you can use the Layout property in the Page Model or directly in the Razor file:

@{ Layout = "_AnotherLayout.cshtml"; }

Or in the Page Model's constructor or OnGet method:

public class MyPageModel : PageModel { public MyPageModel() { Layout = "_AnotherLayout.cshtml"; } public void OnGet() { } }

Handling Forms

Razor Pages provide an intuitive way to handle form submissions using HTTP POST methods. The Page Model's handler methods, typically named OnPost..., are invoked when a form is submitted via POST.

Example Form:

// Pages/Contact.cshtml.cs using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; public class ContactModel : PageModel { [BindProperty] public string UserName { get; set; } public string ResultMessage { get; set; } public void OnGet() { } public IActionResult OnPost() { if (!string.IsNullOrEmpty(UserName)) { ResultMessage = $"Hello, {UserName}!"; } else { ResultMessage = "Please enter your name."; } return Page(); // Renders the current page again } }

The [BindProperty] attribute automatically binds form values to properties of the Page Model.

Data Binding

[BindProperty] is a powerful attribute for data binding. It can be used to bind form data, route data, and query string parameters to Page Model properties. When used with POST requests, it's commonly used to bind form inputs.

Validation

ASP.NET Core's built-in validation attributes can be applied to Page Model properties. These attributes can then be leveraged for both server-side and client-side validation.

using System.ComponentModel.DataAnnotations; public class ProductModel : PageModel { [Required] [StringLength(50, ErrorMessage = "Name cannot be longer than 50 characters.")] [BindProperty] public string Name { get; set; } // ... other properties and methods }

Client-side validation requires including the necessary JavaScript libraries (e.g., jQuery Validation) and rendering validation tags in your Razor markup.

Dependency Injection

Razor Pages seamlessly integrates with ASP.NET Core's built-in Dependency Injection system. You can inject services into your Page Models to access them:

using Microsoft.AspNetCore.Mvc.RazorPages; public class DataPageModel : PageModel { private readonly IMyDataService _dataService; public DataPageModel(IMyDataService dataService) { _dataService = dataService; } public void OnGet() { var data = _dataService.GetData(); // ... use data } }

Advanced Topics

Explore further for: