Razor Pages in ASP.NET Core

Build dynamic, data-driven HTML UIs with Razor Pages.

What are Razor Pages?

Razor Pages is a page-based programming model for building web UIs with ASP.NET Core. It simplifies the development of page-focused scenarios compared to MVC. Each Razor Page consists of two primary components:

  • Razor Page File (.cshtml): Contains HTML markup, Razor syntax for embedding server-side code, and references to a Page Model.
  • Page Model (optional, .cshtml.cs): A C# class that contains the logic for the Razor Page, including event handlers, data properties, and validation logic.

This model provides a cleaner separation of concerns for web applications, particularly for scenarios where a direct page-to-logic mapping is desired.

Getting Started with Razor Pages

To create a new Razor Page project, you can use the ASP.NET Core Web App template in Visual Studio or the .NET CLI:

dotnet new webapp -o MyRazorApp

The template includes a default set of Razor Pages in the Pages folder, such as Index.cshtml and About.cshtml, along with their corresponding Page Models.

Creating a New Razor Page

To add a new Razor Page:

  1. Create a new file named MyNewPage.cshtml in the Pages folder.
  2. Add basic HTML structure:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>My New Page</title>
    </head>
    <body>
        <h1>Welcome to My New Page!</h1>
    </body>
    </html>
  3. (Optional) Create a corresponding Page Model file named MyNewPage.cshtml.cs in the same folder:
    using Microsoft.AspNetCore.Mvc.RazorPages;
    
    public class MyNewPageModel : PageModel
    {
        public string Message { get; set; }
    
        public void OnGet()
        {
            Message = "This message is from the Page Model.";
        }
    }
  4. Update the .cshtml file to reference the Page Model and display its properties:
    @page
    @model MyNewPageModel
    @{
        ViewData["Title"] = "My New Page";
    }
    
    <h1>@ViewData["Title"]</h1>
    <p>@Model.Message</p>

Page Model Lifecycle and Event Handlers

Razor Pages have a lifecycle managed by the ASP.NET Core framework. You can intercept specific stages of this lifecycle by implementing handler methods in your Page Model. The most common handlers are:

  • OnGet(): Handles GET requests for the page.
  • OnPost(): Handles POST requests for the page.
  • OnPut(), OnDelete(), etc.: For other HTTP verbs.

You can also define specific handlers with different names, like OnGetProducts() or OnPostCreateUser(). These are invoked based on the request's route data.

Tip: By default, Razor Pages uses convention-based routing. A request to /MyNewPage will execute the OnGet() handler of MyNewPageModel.

Example of Specific Handlers

using Microsoft.AspNetCore.Mvc.RazorPages;

public class ProductListModel : PageModel
{
    public List<string> Products { get; set; }

    public void OnGet()
    {
        Products = new List<string> { "Laptop", "Keyboard", "Mouse" };
    }

    public void OnGetDetails(int productId)
    {
        // Logic to fetch a specific product
        Products = new List<string> { $"Product {productId}" };
    }
}

To invoke OnGetDetails, the URL would be something like /Products?handler=Details&productId=123 or /Products/Details/123 if configured.

Layouts and Partial Views

Razor Pages integrate seamlessly with layouts and partial views, allowing you to share common UI elements like headers, footers, and navigation menus. The default layout is typically found in Pages/Shared/_Layout.cshtml.

You can specify a different layout for a specific page or disable the layout:

@{
    Layout = "~/Pages/Shared/_CustomLayout.cshtml";
}

Or to disable the layout:

@{
    Layout = null;
}

Forms and Data Submission

Submitting forms in Razor Pages is straightforward. You can use the asp-page-handler tag helper to direct form submissions to specific handlers in your Page Model.

<form method="post">
    <input asp-for="MyInput" />
    <button type="submit" asp-page-handler="SubmitData">Submit</button>
</form>

In the Page Model:

public class MyFormPageModel : PageModel
{
    [BindProperty]
    public string MyInput { get; set; }

    public void OnPostSubmitData()
    {
        // Process MyInput
        Console.WriteLine($"Received: {MyInput}");
    }
}
Remember: Use the [BindProperty] attribute on properties in your Page Model that you want to bind form values to.

Routing and URLs

Razor Pages uses a file-system based routing convention. The URL path typically mirrors the directory structure of the `.cshtml` files within the Pages folder. For example:

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

You can customize routing using the @page directive with route templates or by configuring routes in Program.cs (or Startup.cs in older versions).

@page "{id:int}"
@model ProductDetailsModel

This would map Pages/Products/Details.cshtml to URLs like /Products/Details/123.