Razor Pages Quickstart

Serve Razor Pages where each .cshtml can have an optional sibling .cshtml.ps1 script that builds a per-request model.

Full source

File: pwsh/tutorial/examples/11.1-RazorPages.ps1

<#
    Sample Kestrun Server showing PowerShell-backed Razor Pages.
    This example demonstrates enabling the Razor Pages runtime and serving pages from a root folder.
    FileName: 11.1-RazorPages.ps1
#>

param(
    [int]$Port = 5000,
    [IPAddress]$IPAddress = [IPAddress]::Loopback
)

# Initialize Kestrun root directory
# the default value is $PWD
# This is recommended in order to use relative paths without issues
Initialize-KrRoot -Path $PSScriptRoot

# Create a new logger
New-KrLogger |
    Set-KrLoggerLevel -Value Debug |
    Add-KrSinkConsole |
    Register-KrLogger -SetAsDefault -Name 'DefaultLogger'

# Create a new Kestrun server
New-KrServer -Name 'RazorPages'

# Add a listener on the configured port and IP address
Add-KrEndpoint -Port $Port -IPAddress $IPAddress

# Add a Razor Pages handler to the server
Add-KrPowerShellRazorPagesRuntime -RootPath './Assets/Pages'

# Application-wide metadata (AVAILABLE TO ALL RUNSPACES)
$AppInfo = [pscustomobject]@{
    Name = 'Kestrun Razor Demo'
    Environment = 'Development'
    StartedUtc = [DateTime]::UtcNow
    Version = Get-KrVersion -AsString
}

Write-KrLog -Level Information -Message "Starting Kestrun RazorPages server '{name}' version {version} in {environment} environment on {ipaddress}:{port}" `
    -Values $AppInfo.Name, $AppInfo.Version, $AppInfo.Environment, $IPAddress, $Port

# Define feature flags for the application
$FeatureFlags = @{
    RazorPages = $true
    Cancellation = $true
    HotReload = $false
}

Write-KrLog -Level Information -Message 'Feature Flags: {featureflags}' -Values $($FeatureFlags | ConvertTo-Json -Depth 3)

# Define a Message of the Day (MOTD) accessible to all pages
$Motd = @'
Welcome to Kestrun.
This message comes from the main server script.
Defined once, visible everywhere.
'@

Write-KrLog -Level Information -Message 'Message of the Day: {motd}' -Values $Motd

# Enable Kestrun configuration
Enable-KrConfiguration


# Start the server asynchronously
Start-KrServer

Step-by-step

  1. Root: Call Initialize-KrRoot so the sample can use relative paths reliably.
  2. Logging: Create a console logger and set it as default.
  3. Server: Create a server named RazorPages.
  4. Listener: Bind to the configured IP address and port.
  5. Razor runtime: Enable PowerShell-backed Razor Pages with Add-KrPowerShellRazorPagesRuntime.
  6. App state: Define $AppInfo, $FeatureFlags, and $Motd to be visible to all pages.
  7. Pipeline: Finalize the server configuration with Enable-KrConfiguration.
  8. Start: Start the server with Start-KrServer.

Try it

# Home page
curl -i http://127.0.0.1:5000/

# A couple of sample pages (served from the pages folder)
curl -i http://127.0.0.1:5000/About
curl -i http://127.0.0.1:5000/Status

PowerShell equivalents:

Invoke-WebRequest http://127.0.0.1:5000/ | Select-Object StatusCode, Headers
Invoke-WebRequest http://127.0.0.1:5000/About | Select-Object StatusCode
Invoke-WebRequest http://127.0.0.1:5000/Status | Select-Object StatusCode

How the page model works

  • For a request like /About, Razor renders About.cshtml.
  • If About.cshtml.ps1 exists, Kestrun runs it first.
  • The page script sets $Model (commonly a PSCustomObject), and Razor can read it via @model Kestrun.PowerShellPageModel and Model.Data.

Troubleshooting

Symptom Cause Fix
404 for all pages Razor runtime not enabled Ensure Add-KrPowerShellRazorPagesRuntime is called before Enable-KrConfiguration and Start-KrServer
404 for a specific page File name or path mismatch Confirm the .cshtml file exists under the configured -RootPath and casing matches on Linux
Page renders but model is empty No sibling script or $Model not set Add Page.cshtml.ps1 and assign $Model (for example a PSCustomObject)
Relative paths fail Root not initialized Call Initialize-KrRoot -Path $PSScriptRoot at the top of the script

References


Previous / Next

Previous: Razor Next: Razor Pages with Antiforgery