Razor Pages Concepts in ASP.NET Core
Last updated: October 26, 2023
On this page:
What are Razor Pages?
Razor Pages is a page-focused programming model for building dynamic web UIs with ASP.NET Core. It provides a simpler, higher-productivity alternative to MVC controllers and actions for application pages. Razor Pages simplifies common web development tasks, making it easier to build robust, feature-rich web applications.
It's built on top of the ASP.NET Core framework and leverages Razor syntax for embedding server-side code within HTML.
Key Benefits
- Simplicity: Offers a cleaner, more direct way to build page-based applications compared to traditional MVC.
- Productivity: Reduces boilerplate code and simplifies common web development scenarios.
- Testability: Page models are easily testable classes.
- Organization: Encourages a clear separation of concerns for each page.
- Full Framework Support: Benefits from all the features of ASP.NET Core, including dependency injection, middleware, and configuration.
File Structure
Razor Pages are organized in a convention-based structure within your project, typically in a folder named Pages
. Each Razor Page consists of two primary files:
- Razor View (.cshtml): Contains the HTML markup and Razor syntax for rendering the UI.
- Page Model (.cshtml.cs): A C# class that inherits from
PageModel
and handles the logic for the page, such as data retrieval, business logic, and request handling.
For example, a page named Contact.cshtml
would typically have a corresponding Contact.cshtml.cs
file in the same directory.
Pages/
├── _ViewImports.cshtml
├── _ViewStart.cshtml
├── Index.cshtml
├── Index.cshtml.cs
├── About.cshtml
├── About.cshtml.cs
└── Contact.cshtml
└── Contact.cshtml.cs
The Razor Page Model
The Page Model class is the heart of a Razor Page. It inherits from Microsoft.AspNetCore.Mvc.RazorPages.PageModel
and provides a C# representation of the page's logic.
Key features of the Page Model include:
- Properties: Used to pass data between the UI and the server.
- Event Handlers: Methods like
OnGet()
,OnPost()
, etc., to handle HTTP requests. - Services: Can inject services (e.g., from dependency injection) to access application functionality.
- Validation: Supports data annotations for client-side and server-side validation.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
public class ContactModel : PageModel
{
[BindProperty]
[Required]
[EmailAddress]
public string Email { get; set; }
[BindProperty]
[Required]
[StringLength(500, ErrorMessage = "Message cannot be longer than 500 characters.")]
public string Message { get; set; }
public string SuccessMessage { get; private set; }
public void OnGet()
{
// Logic for GET request (e.g., load initial data)
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page(); // Return to the same page if validation fails
}
// Process the form data (e.g., send an email)
SuccessMessage = "Thank you for your message!";
return Page(); // Re-render the page with the success message
}
}
Razor Syntax
Razor syntax allows you to embed server-side C# code within your HTML markup. It uses the @
symbol to denote code blocks.
- Expressions:
@Model.PropertyName
to display a property's value. - Code Blocks:
@{ ... }
for multi-line code. - Directives:
@page
,@model
to specify page properties and models. - HTML Helpers: Built-in helpers for forms, inputs, etc.
@page
@model ContactModel
@{
ViewData["Title"] = "Contact Us";
}
Contact Us
@if (!string.IsNullOrEmpty(Model.SuccessMessage))
{
<div class="alert alert-success" role="alert">
@Model.SuccessMessage
</div>
}
<form method="post">
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" asp-for="Email">
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" rows="5" asp-for="Message"></textarea>
<span asp-validation-for="Message" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Send Message</button>
</form>
@section Scripts {
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
}
Handling Requests
Razor Pages use specific methods in the Page Model to handle different HTTP request verbs.
OnGet()
: Handles HTTP GET requests. Use this to load data and initialize the page.OnPost()
: Handles HTTP POST requests. Use this to process form submissions.OnPut()
,OnDelete()
, etc.: For other HTTP verbs.
These methods can return an IActionResult
, such as Page()
(to render the current page), RedirectToPage()
, or RedirectToRoute()
.
Data Binding
Data binding simplifies the process of mapping client-side input (e.g., form fields) to properties in your Page Model. The [BindProperty]
attribute is used to enable binding for a property.
When a form is submitted, ASP.NET Core attempts to bind the incoming request data to the properties marked with [BindProperty]
. This binding happens automatically for POST requests when you call Page()
in your handler.
Model Validation
Razor Pages integrate seamlessly with ASP.NET Core's built-in validation mechanisms, primarily using Data Annotations.
- Decorate Page Model properties with Data Annotation attributes (e.g.,
[Required]
,[EmailAddress]
,[StringLength]
). - Use
ModelState.IsValid
to check if the model is valid. - Use the
asp-validation-for
tag helper in your Razor view to display validation error messages. - Ensure you have the necessary JavaScript validation libraries included in your project (e.g., jQuery Validate and Unobtrusive Validation).
Routing
By default, Razor Pages use a file-system-based routing convention. The URL path for a page corresponds to its file path within the Pages
folder, relative to the root of the application.
Pages/Index.cshtml
maps to/
.Pages/About.cshtml
maps to/About
.Pages/Contact.cshtml
maps to/Contact
.
You can customize routing using attributes like [Route]
on the Page Model, but the convention-based routing is often sufficient.
Layout Pages
Layout pages (e.g., _Layout.cshtml
) are used to define the overall structure and shared elements of your application, such as headers, footers, and navigation menus. They are rendered around individual Razor Page content.
Individual Razor Pages can specify which layout to use in their _ViewStart.cshtml
file or by setting the Layout
property in the Page Model.