Latest update Android YouTube

The Complete Guide to Razor Pages in .NET

Estimated read time: 18 min
The Complete Guide to Razor Pages in .NET

Introduction to Razor Pages

Razor Pages is a page-focused framework for building dynamic, data-driven web applications with ASP.NET Core. It simplifies traditional MVC (Model-View-Controller) patterns by combining the controller and view components into a single page model.

What Are Razor Pages?

Razor Pages provide:

  • A page-based programming model
  • Simplified development workflow compared to MVC
  • Built on ASP.NET Core
  • Uses Razor syntax for server-side rendering
  • Combines markup (HTML) with C# code

History and Evolution

  • Introduced in ASP.NET Core 2.0 (2017)
  • Designed to make web development more approachable
  • Evolved alongside MVC in subsequent .NET Core releases
  • Now a first-class citizen in ASP.NET Core

Key Benefits

  1. Simplified Architecture: Combines controller and view logic
  2. Organized Structure: Each page is self-contained
  3. Productivity: Less ceremony than MVC for page-focused apps
  4. Flexibility: Can be used alongside MVC in the same project
  5. Performance: Same high performance as ASP.NET Core MVC

Setting Up the Development Environment

Prerequisites

  1. .NET SDK: Latest stable version
  2. IDE Options:
    • Visual Studio (Windows/Mac)
    • Visual Studio Code (Cross-platform)
    • JetBrains Rider (Cross-platform)
  3. Web Browser: Chrome, Edge, Firefox, etc.

Creating a New Razor Pages Project

Using Visual Studio

  1. File → New → Project
  2. Select "ASP.NET Core Web App"
  3. Choose project name and location
  4. In the configuration dialog:
    • Select .NET version
    • Choose "ASP.NET Core Web App" template
    • Ensure "Razor Pages" is selected
  5. Click Create

Using .NET CLI

dotnet new webapp -o MyRazorApp

cd MyRazorApp

dotnet run

Project Structure

A new Razor Pages project contains:

MyRazorApp/

├─��� Pages/               # Contains Razor Pages

│   ├── Shared/          # Shared layouts and partials

│   ├── _ViewStart.cshtml

│   ├── _ViewImports.cshtml

│   └── Index.cshtml     # Default page

├── wwwroot/             # Static files (CSS, JS, images)

├── appsettings.json     # Configuration

├── Program.cs           # Startup and configuration

└── MyRazorApp.csproj    # Project file

Understanding Razor Pages Fundamentals

Basic Components

  1. Page File (.cshtml): Contains HTML markup with Razor syntax
  2. Page Model File (.cshtml.cs): Contains C# code (handler methods, properties)
  3. Layout Files: Define common structure for multiple pages
  4. Partial Views: Reusable UI components

The Page Model

The Page Model (also called code-behind) is a C# class that:

  • Handles HTTP requests
  • Contains business logic
  • Manages page state
  • Prepares data for the view

Example Index.cshtml.cs:

public class IndexModel : PageModel

{

    public void OnGet()

    {

        // Initialization logic for GET requests

    }

    

    public IActionResult OnPost()

    {

        // Handle form submissions

        return Page();

    }

}

Razor Syntax Basics

Razor syntax allows mixing HTML with C# code:

@page

@model IndexModel

<h1>Welcome, @Model.UserName!</h1>

@{

    var currentDate = DateTime.Now;

}

<p>Today is: @currentDate.ToShortDateString()</p>

@if(Model.IsPremiumUser)

{

    <div class="premium-banner">

        Thank you for being a premium member!

    </div>

}

Creating Your First Razor Page

Step-by-Step Guide

  1. Add a New Page:
    • Right-click Pages folder → Add → Razor Page
    • Choose "Razor Page" template
    • Name it "Welcome.cshtml"
  2. Edit the Page Model (Welcome.cshtml.cs):
    public class WelcomeModel : PageModel
    
    {
    
        [BindProperty]
    
        public string Name { get; set; }
    
        
    
        public string Greeting { get; private set; }
    
        
    
        public void OnGet()
    
        {
    
            // Runs on initial page load
    
        }
    
        
    
        public IActionResult OnPost()
    
        {
    
            Greeting = $"Hello, {Name}! Welcome to our site.";
    
            return Page();
    
        }
    
    }
  3. Edit the View (Welcome.cshtml):
    @page
    
    @model WelcomeModel
    
    <h1>Welcome Page</h1>
    
    <form method="post">
    
        <div class="form-group">
    
            <label asp-for="Name"></label>
    
            <input asp-for="Name" class="form-control" />
    
        </div>
    
        <button type="submit" class="btn btn-primary">Submit</button>
    
    </form>
    
    @if(!string.IsNullOrEmpty(Model.Greeting))
    
    {
    
        <div class="alert alert-success mt-3">
    
            @Model.Greeting
    
        </div>
    
    }

Understanding the @page Directive

The @page directive:

  • Must be the first directive in a Razor Page
  • Makes the file into an MVC action
  • Routes requests directly to the page
  • Can include route parameters: @page "{id:int}"

Handler Methods

Razor Pages use convention-based handler methods:

  • OnGet(): Handles HTTP GET requests
  • OnPost(): Handles HTTP POST requests
  • OnGetAsync(): Async version of OnGet
  • OnPostAsync(): Async version of OnPost
  • Custom handlers: OnPost[Action]()

Routing in Razor Pages

Default Routing

By default, Razor Pages use a file-based routing system:

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

Customizing Routes

You can customize routes using:

  1. Route Templates in the @page directive:
    @page "/about-us"
  2. Route Parameters:
    @page "/products/{id:int}"
  3. Convention-based routing in Program.cs:
    builder.Services.AddRazorPages(options => {
    
        options.Conventions.AddPageRoute("/About", "/about-us");
    
    });

Route Constraints

Common route constraints:

  • {id:int}: Must be an integer
  • {id:guid}: Must be a GUID
  • {name:alpha}: Alphabetic characters only
  • {slug:regex(^[a-z0-9_-]+$)}: Custom regex

Accessing Route Data

In the Page Model:

public void OnGet(int id)

{

    // id comes from route parameter

}

// Or using RouteData

public void OnGet()

{

    var id = RouteData.Values["id"];

}

Working with Data

Model Binding

Razor Pages automatically bind form data to properties:

public class ContactModel : PageModel

{

    [BindProperty]

    public ContactForm Input { get; set; }

    

    public class ContactForm

    {

        [Required]

        public string Name { get; set; }

        

        [EmailAddress]

        public string Email { get; set; }

        

        public string Message { get; set; }

    }

    

    public IActionResult OnPost()

    {

        if(!ModelState.IsValid)

        {

            return Page();

        }

        

        // Process the form

        return RedirectToPage("/ThankYou");

    }

}

Data Access Options

  1. Entity Framework Core (Recommended for most applications)
  2. Dapper (For lightweight data access)
  3. ADO.NET (For full control)
  4. Other ORMs (NHibernate, etc.)
  5. Web APIs (Client-side data access)

Example with EF Core

  1. Add NuGet package:
    • Microsoft.EntityFrameworkCore.SqlServer
    • Microsoft.EntityFrameworkCore.Tools
  2. Create DbContext:
    public class AppDbContext : DbContext
    
    {
    
        public AppDbContext(DbContextOptions<AppDbContext> options)
    
            : base(options) { }
    
            
    
        public DbSet<Product> Products { get; set; }
    
    }
    
    public class Product
    
    {
    
        public int Id { get; set; }
    
        public string Name { get; set; }
    
        public decimal Price { get; set; }
    
    }
  3. Register in Program.cs:
    builder.Services.AddDbContext<AppDbContext>(options =>
    
        options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
  4. Use in Page Model:
    public class ProductsModel : PageModel
    
    {
    
        private readonly AppDbContext _context;
    
        
    
        public ProductsModel(AppDbContext context)
    
        {
    
            _context = context;
    
        }
    
        
    
        public List<Product> Products { get; set; }
    
        
    
        public async Task OnGetAsync()
    
        {
    
            Products = await _context.Products.ToListAsync();
    
        }
    
    }

Forms and Validation

Creating Forms

Razor Pages provides tag helpers for form creation:

<form method="post">

    <div asp-validation-summary="ModelOnly" class="text-danger"></div>

    

    <div class="form-group">

        <label asp-for="Input.Name" class="control-label"></label>

        <input asp-for="Input.Name" class="form-control" />

        <span asp-validation-for="Input.Name" class="text-danger"></span>

    </div>

    

    <div class="form-group">

        <label asp-for="Input.Email" class="control-label"></label>

        <input asp-for="Input.Email" class="form-control" />

        <span asp-validation-for="Input.Email" class="text-danger"></span>

    </div>

    

    <button type="submit" class="btn btn-primary">Submit</button>

</form>

Validation

ASP.NET Core provides built-in validation attributes:

public class ContactForm

{

    [Required]

    [StringLength(100)]

    public string Name { get; set; }

    

    [Required]

    [EmailAddress]

    public string Email { get; set; }

    

    [Phone]

    public string Phone { get; set; }

    

    [Range(1, 5)]

    public int Rating { get; set; }

    

    [DataType(DataType.MultilineText)]

    public string Comments { get; set; }

}

Client-Side Validation

Automatically enabled when:

  1. jQuery Validation is included
  2. Model has validation attributes
  3. Form uses tag helpers

Required scripts (in _Layout.cshtml):

<script src="~/lib/jquery/dist/jquery.min.js"></script>

<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script>

<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>

Layouts and Partial Views

Layout Pages

Define common structure in Pages/Shared/_Layout.cshtml:

<!DOCTYPE html>

<html>

<head>

    <title>@ViewData["Title"] - My App</title>

    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />

</head>

<body>

    <header>

        <!-- Navigation -->

    </header>

    

    <main>

        @RenderBody()

    </main>

    

    <footer>

        <!-- Footer content -->

    </footer>

    

    <script src="~/lib/jquery/dist/jquery.min.js"></script>

    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>

    @await RenderSectionAsync("Scripts", required: false)

</body>

</html>

Using Layouts

Set layout in _ViewStart.cshtml:

@{

    Layout = "_Layout";

}

Or override per page:

@{

    Layout = "_AlternateLayout";

}

Sections

Define sections in layout:

@section Scripts {

    <script>

        // Page-specific scripts

    </script>

}

Partial Views

Reusable components in Pages/Shared/ or Pages/[Folder]/:

  1. Create _LoginPartial.cshtml:
    @if(User.Identity.IsAuthenticated)
    
    {
    
        <form asp-page="/Logout" method="post">
    
            <button type="submit">Logout</button>
    
        </form>
    
    }
    
    else
    
    {
    
        <a asp-page="/Login">Login</a>
    
    }
  2. Include in layout or page:
    <partial name="_LoginPartial" />

Dependency Injection in Razor Pages

Built-in DI Container

ASP.NET Core includes a built-in DI container. Common services:

  1. Configuration: IConfiguration
  2. Logging: ILogger<T>
  3. Database: DbContext
  4. Authentication: IAuthenticationService
  5. Email: IEmailSender

Registering Services

In Program.cs:

Post a Comment

Feel free to ask your query...
Cookie Consent
We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Site is Blocked
Sorry! This site is not available in your country.