Documentation

ASP.NET Core Razor Pages

Introduction to Razor Pages

Razor Pages is a page-focused, scenario-driven surface area of ASP.NET Core for building dynamic web UIs. It’s built on top of MVC and provides a more streamlined approach for creating page-based applications compared to traditional MVC. Razor Pages allows developers to colocate their page logic (.cshtml.cs) with their page UI (.cshtml) in a clean, organized manner.

Key Benefit: Razor Pages simplifies the development of page-centric web applications by reducing boilerplate code and improving organization.

Getting Started

To get started with Razor Pages, you can create a new ASP.NET Core Web Application project in Visual Studio or use the .NET CLI:

dotnet new webapp -n MyRazorApp
cd MyRazorApp
dotnet run

This will create a project with a basic Razor Pages structure, including sample pages like Index.cshtml and Privacy.cshtml.

Razor Syntax

Razor is a templating engine used to embed server-side code (C#) within HTML markup. It uses the @ symbol to denote code blocks.

Here's a simple example:

<h1>Welcome, @ViewData["Name"]!</h1>
<p>The current date is: @DateTime.Now.ToShortDateString()</p>

The Page Model

Each Razor Page typically has an associated C# code-behind class, known as a Page Model. This class inherits from PageModel and contains the logic, data, and handlers for the page.

Example: Index.cshtml.cs

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

public class IndexModel : PageModel
{
    public string Message { get; set; }

    public void OnGet()
    {
        Message = "Welcome to the Homepage!";
    }
}

Corresponding Index.cshtml:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="text-center">
    <h1 class="display-4">@Model.Message</h1>
    <p>Learn about <a href="https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-6.0">building web apps with ASP.NET Core</a>.</p>
</div>

Handling Requests

Page Models use handler methods to process HTTP requests. The naming convention is On[HTTPVerb], such as OnGet() for GET requests and OnPost() for POST requests.

Data Binding

Razor Pages automatically bind incoming request data (form fields, query strings, route data) to properties on the Page Model.

If a form field's name attribute matches a public property name on the Page Model, the value will be automatically bound.

<form method="post">
    <input type="text" asp-for="User.Name" />
    <button type="submit">Submit</button>
</form>

In the Page Model:

public class MyFormModel : PageModel
{
    [BindProperty]
    public User User { get; set; }

    public void OnPost()
    {
        // User.Name is automatically populated
        Console.WriteLine($"User Name: {User.Name}");
    }
}
public class User { public string Name { get; set; } }

The [BindProperty] attribute tells the model binder to bind properties from the request. Using the asp-for tag helper is recommended for strong typing and validation integration.

Validation

ASP.NET Core's built-in validation features work seamlessly with Razor Pages. You can use data annotations on your Page Model properties.

using System.ComponentModel.DataAnnotations;

public class RegisterModel : PageModel
{
    [Required]
    [EmailAddress]
    [BindProperty]
    public string Email { get; set; }

    [Required]
    [DataType(DataType.Password)]
    [BindProperty]
    public string Password { get; set; }

    public void OnPost()
    {
        if (!ModelState.IsValid)
        {
            // Handle validation errors
            return Page();
        }
        // Process valid data
    }
}

In the Razor View, use the asp-validation-for tag helper:

<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input asp-for="Email" />
<span asp-validation-for="Email" class="text-danger"></span>

Layout Pages

Layout pages (e.g., _Layout.cshtml) define common UI elements like headers, footers, and navigation that are shared across multiple pages.

The <render-body /> tag helper in the layout page renders the content of the individual Razor Page.

Routing

By default, Razor Pages use convention-based routing. The file path within the Pages folder determines the URL. For example, Pages/Admin/Users.cshtml maps to the /Admin/Users URL.

You can customize routing using the @page directive and route templates or by configuring routing in Startup.cs.

@page "{id:int?}" // Optional integer route parameter
@page "/products/{category}/{slug}" // Custom route template
Note: The default routing convention makes it easy to manage URLs for your pages.

Dependency Injection

Razor Pages fully support ASP.NET Core's built-in dependency injection (DI) container. You can inject services into your Page Models to access them.

public class MyService
{
    public string GetData() => "Injected Service Data";
}

public class ServicePageModel : PageModel
{
    private readonly MyService _myService;

    public ServicePageModel(MyService myService)
    {
        _myService = myService;
    }

    public string ServiceData { get; private set; }

    public void OnGet()
    {
        ServiceData = _myService.GetData();
    }
}

Testing Razor Pages

Razor Pages can be tested effectively using unit tests and integration tests. You can use the TestServer and HttpClient to simulate requests and verify responses.

Advanced Topics

Explore topics such as:

For more detailed information, please refer to the official ASP.NET Core Razor Pages documentation.