ASP.NET Core 8 Website - Razor Pages

PART 5: Converting the Application to Razor Pages

This part moves Home and Privacy out of C# strings and into .cshtml files. The shared layout will be introduced in PART 6.

1. Create the Pages directory

mkdir Pages

2. Replace Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();

var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();

app.MapFallback(() =>
{
    string html = """
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Page Not Found - basicdotnet</title>
            <link rel="stylesheet" href="/css/site.css">
        </head>
        <body>
            <header class="site-header">
                <nav class="navigation">
                    <a class="site-name" href="/">basicdotnet</a>
                    <a class="nav-link" href="/">Home</a>
                    <a class="nav-link" href="/privacy">Privacy</a>
                </nav>
            </header>
            <main class="page-content">
                <h1 class="error-code">404 - Page Not Found</h1>
                <p>The requested page could not be found.</p>
                <p><a href="/">Return to the Home page</a></p>
            </main>
        </body>
        </html>
        """;

    return Results.Content(html, "text/html",
        statusCode: StatusCodes.Status404NotFound);
});

app.Run();

AddRazorPages() registers the required services. MapRazorPages() discovers pages and maps their routes.

3. Create Pages/Index.cshtml

@page

@{
    ViewData["Title"] = "Home";
    string serverTime = DateTime.Now.ToString("HH:mm:ss");
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewData["Title"] - basicdotnet</title>
    <link rel="stylesheet" href="/css/site.css">
</head>
<body>
    <header class="site-header">
        <nav class="navigation">
            <a class="site-name" href="/">basicdotnet</a>
            <a class="nav-link" href="/">Home</a>
            <a class="nav-link" href="/privacy">Privacy</a>
        </nav>
    </header>
    <main class="page-content home-content">
        <h1>Welcome to basicdotnet</h1>
        <p>A simple ASP.NET Core web app built with Razor Pages.</p>
        <p>It's @serverTime on the server.</p>
    </main>
</body>
</html>

4. Create Pages/Privacy.cshtml

@page

@{
    ViewData["Title"] = "Privacy Policy";
}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewData["Title"] - basicdotnet</title>
    <link rel="stylesheet" href="/css/site.css">
</head>
<body>
    <header class="site-header">
        <nav class="navigation">
            <a class="site-name" href="/">basicdotnet</a>
            <a class="nav-link" href="/">Home</a>
            <a class="nav-link" href="/privacy">Privacy</a>
        </nav>
    </header>
    <main class="page-content">
        <h1>@ViewData["Title"]</h1>
        <p>basicdotnet is a demonstration application.</p>
        <p>This website does not collect or store personal information.</p>
    </main>
</body>
</html>

5. Check the structure

basicdotnet/
├── Pages/
│   ├── Index.cshtml
│   └── Privacy.cshtml
├── wwwroot/
│   └── css/site.css
├── basicdotnet.csproj
└── Program.cs

6. Build, run and test

dotnet build
dotnet run
URLSource
/Pages/Index.cshtml
/privacyPages/Privacy.cshtml
/contactMapFallback

What has improved?

  • HTML is written directly in .cshtml files.
  • Routes are inferred from filenames.
  • Razor expressions insert server-side values.
  • Program.cs is substantially smaller.

Home and Privacy still repeat the document structure, head, stylesheet and navigation markup.

Next: PART 6 introduces Pages/Shared/_Layout.cshtml to remove this duplication.