Razor Pages: Your Website’s Magic Recipe Book 🍳
Imagine you’re running a magical restaurant. Every dish you make has a recipe card that tells you exactly what to cook and how to present it. That’s exactly what Razor Pages does for your website!
What Are Razor Pages?
Think of Razor Pages like a recipe book for your website:
- Each page is one recipe card
- The recipe (code) tells you what to do when someone orders
- The presentation (HTML) shows how the dish looks on the plate
Simple Example:
- A visitor clicks “Contact Us” on your website
- Razor Pages finds the
Contact.cshtmlrecipe card - It cooks up the data and serves a beautiful contact page!
Real Life:
- A “Hello World” page = one recipe card that says “Just say Hello!”
- A login page = recipe card that checks your username and password
- A product list = recipe card that fetches products from the kitchen (database)
The Recipe Card Has Two Parts
Every Razor Page comes as a pair of files:
📁 Pages/
📄 Index.cshtml ← The plate (what users see)
📄 Index.cshtml.cs ← The recipe (the cooking logic)
They work together like bread and butter!
Razor Pages Overview
Razor Pages is like having a personal chef for each page of your website.
Why Use Razor Pages?
| Old Way (MVC) | Razor Pages Way |
|---|---|
| 3 separate files | 2 files together |
| Code lives far from view | Code lives next to view |
| More jumping around | Everything in one place |
Your First Razor Page
The View (Welcome.cshtml):
@page
@model WelcomeModel
<h1>Hello, @Model.VisitorName!</h1>
<p>Welcome to our store.</p>
The Logic (Welcome.cshtml.cs):
public class WelcomeModel : PageModel
{
public string VisitorName { get; set; }
public void OnGet()
{
VisitorName = "Friend";
}
}
What happens:
- Someone visits
/Welcome OnGet()runs and setsVisitorName = "Friend"- The page shows “Hello, Friend!”
Page Model: The Brain Behind Each Page
The Page Model is like the chef’s brain - it knows:
- What ingredients (data) to prepare
- How to cook them (logic)
- When to do what (handlers)
Anatomy of a Page Model
public class ContactModel : PageModel
{
// 🧺 Ingredients (Properties)
public string Message { get; set; }
[BindProperty]
public string Email { get; set; }
// 👨🍳 Cooking methods (Handlers)
public void OnGet()
{
Message = "Send us a message!";
}
public void OnPost()
{
// Process the form
}
}
The [BindProperty] Magic Wand
When a visitor fills a form, how does the data get to your code?
Without [BindProperty]:
// You must manually grab it
var email = Request.Form["email"];
With [BindProperty]:
[BindProperty]
public string Email { get; set; }
// Magic! It's already filled in!
Think of [BindProperty] as a waiter who automatically brings the customer’s order to the kitchen!
Page Handlers: The Action Buttons
Page Handlers are like buttons on a remote control. Each button does something different!
The Main Handlers
graph TD A["Visitor arrives"] --> B{What did they do?} B -->|Just viewing| C["OnGet"] B -->|Submitted form| D["OnPost"] B -->|Updating something| E["OnPut"] B -->|Deleting something| F["OnDelete"]
OnGet - The Welcome Handler
Runs when someone visits your page:
public void OnGet()
{
// Prepare data for display
Products = GetAllProducts();
}
OnPost - The Form Handler
Runs when someone submits a form:
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page(); // Show errors
}
SaveToDatabase(Email);
return RedirectToPage("/ThankYou");
}
Named Handlers - Multiple Buttons!
What if you have two buttons on one page?
<!-- In your .cshtml file -->
<form method="post">
<button asp-page-handler="Save">
Save Draft
</button>
<button asp-page-handler="Publish">
Publish Now
</button>
</form>
// In your .cshtml.cs file
public void OnPostSave()
{
// Save as draft
}
public void OnPostPublish()
{
// Publish immediately
}
The naming pattern is: On + Post + HandlerName
Razor Pages Routing: Finding the Right Page
Routing is like the GPS for your website. When someone types a URL, routing figures out which page to show!
How URLs Map to Pages
| URL | Finds This File |
|---|---|
/ |
Pages/Index.cshtml |
/Contact |
Pages/Contact.cshtml |
/Products/List |
Pages/Products/List.cshtml |
The @page Directive - Your Address
Every Razor Page starts with @page:
@page
<!-- This page lives at /PageName -->
Custom Routes - Choose Your Own Address
Want a custom URL? Easy!
@page "/my-cool-page"
<!-- Now accessible at /my-cool-page -->
Route Parameters - Dynamic URLs
Need to pass data in the URL? Use curly braces:
@page "{id}"
| URL | id value |
|---|---|
/Products/42 |
42 |
/Products/999 |
999 |
In your Page Model:
public void OnGet(int id)
{
Product = GetProduct(id);
}
Optional Parameters
Sometimes the parameter is optional:
@page "{id?}"
Now both /Products and /Products/42 work!
Constraints - Bouncer for Your URLs
Only want numbers? Add a constraint:
@page "{id:int}"
| URL | Result |
|---|---|
/Products/42 |
Works! |
/Products/hello |
404 Not Found |
Putting It All Together
Here’s a complete example of a Product Details page:
Products/Details.cshtml:
@page "{id:int}"
@model DetailsModel
<h1>@Model.Product.Name</h1>
<p>Price: $@Model.Product.Price</p>
<form method="post">
<input type="hidden"
asp-for="Product.Id" />
<button asp-page-handler="AddToCart">
Add to Cart
</button>
</form>
Products/Details.cshtml.cs:
public class DetailsModel : PageModel
{
[BindProperty]
public Product Product { get; set; }
public void OnGet(int id)
{
Product = _db.Products.Find(id);
}
public IActionResult OnPostAddToCart()
{
_cart.Add(Product.Id);
return RedirectToPage("/Cart");
}
}
The Flow of a Razor Page Request
graph TD A["User types URL"] --> B["Routing finds the page"] B --> C["Page Model created"] C --> D{GET or POST?} D -->|GET| E["OnGet runs"] D -->|POST| F["OnPost runs"] E --> G["Data prepared"] F --> G G --> H["View rendered"] H --> I["HTML sent to browser"] I --> J["User sees the page!"]
Quick Reference Card
| Concept | What It Does | Example |
|---|---|---|
@page |
Marks file as Razor Page | @page |
PageModel |
Base class for logic | class MyModel : PageModel |
OnGet() |
Handles page visits | public void OnGet() |
OnPost() |
Handles form submits | public void OnPost() |
[BindProperty] |
Auto-fills from form | [BindProperty] public string Name |
{id} |
URL parameter | @page "{id}" |
{id?} |
Optional parameter | @page "{id?}" |
{id:int} |
Must be integer | @page "{id:int}" |
You Did It! 🎉
You now understand the four pillars of Razor Pages:
- Overview - One page = one feature, simple and organized
- Page Model - The brain that holds data and logic
- Handlers - OnGet, OnPost, and named handlers for actions
- Routing - URLs find pages through smart patterns
Razor Pages makes building websites feel like cooking with a well-organized recipe book. Each page knows exactly what to do, and you always know where to find things!
Next step: Build your first Razor Page and watch the magic happen! 🚀
