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.
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.
- Expressions:
@Model.SomeProperty
renders the value ofSomeProperty
. - Code Blocks:
@{ var message = "Hello"; }
defines a code block. - Statements:
@if (DateTime.Now.DayOfWeek == DayOfWeek.Friday) { <p>TGIF!</p> }
renders content conditionally.
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.
OnGet()
: Handles GET requests to the page.OnGet(int id)
: Handles GET requests with a route parameter.OnPost()
: Handles POST requests.OnPostSave()
: Handles POST requests to a specific action.
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
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:
- Creating reusable components with Tag Helpers and View Components.
- Handling AJAX requests.
- Implementing authentication and authorization.
- Integrating with JavaScript frameworks.
For more detailed information, please refer to the official ASP.NET Core Razor Pages documentation.