File contents Razor Pages
Priority: P1 (OPERATIONAL)
ASP.NET Core Razor Pages patterns for server-rendered web applications.
Implementation Guidelines
PageModel : Keep logic in PageModel, not in .cshtml. Use handlers (OnGet, OnPost).
Model Binding : Use [BindProperty] for form data. [FromQuery] for query params.
Tag Helpers : Use asp-for, asp-action, asp-route-* for type-safe HTML.
Partial Views : Reusable UI components with <partial> tag helper.
View Components : Complex reusable UI with server logic.
Layout : Shared layout in _Layout.cshtml. Use sections for page-specific content.
TempData : Flash messages with PRG (Post-Redirect-Get) pattern.
Anti-Patterns
No logic in .cshtml : Move to PageModel or View Components.
No ViewBag/ViewData : Use strongly-typed models.
No inline CSS/JS : Use external files with bundling.
No form without anti-forgery : Always include @Html.AntiForgeryToken() or use asp-antiforgery.
Code
// Pages/Users/Create.cshtml.cs
public class CreateModel(IUserService userService, ILogger<CreateModel> logger) : PageModel
{
[BindProperty]
public CreateUserInput Input { get; set; } = new();
public List<SelectListItem> Roles { get; set; } = [];
public async Task OnGetAsync()
{
Roles = await GetRolesAsync();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
Roles = await GetRolesAsync();
return Page();
}
var result = await userService.CreateAsync(Input);
if (!result.IsSuccess)
{
ModelState.AddModelError(string.Empty, result.Error!);
Roles = await GetRolesAsync();
return Page();
}
TempData["Success"] = "User created successfully";
return RedirectToPage("./Index");
}
}
@* Pages/Users/Create.cshtml *@
@page
@model CreateModel
<h2>Create User</h2>
@if (TempData["Error"] is string error)
{
<div class="alert alert-danger">@error</div>
}
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="mb-3">
<label asp-for="Input.Name" class="form-label"></label>
<input asp-for="Input.Name" class="form-control" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="Input.Email" class="form-label"></label>
<input asp-for="Input.Email" class="form-control" type="email" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="Input.RoleId" class="form-label"></label>
<select asp-for="Input.RoleId" asp-items="Model.Roles" class="form-select">
<option value="">Select a role</option>
</select>
<span asp-validation-for="Input.RoleId" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Create</button>
<a asp-page="./Index" class="btn btn-secondary">Cancel</a>
</form>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Reference & Examples
For page conventions, view components, and AJAX patterns:
See references/REFERENCE.md.
Related Topics
aspnet-core | blazor | security
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1 --- 2 name: razor-pages 3 description: ASP.NET Core Razor Pages patterns for server-rendered web apps. Use when this capability is needed. 4 --- 5 6 # Razor Pages 7 8 ## **Priority: P1 (OPERATIONAL)** 9 10 ASP.NET Core Razor Pages patterns for server-rendered web applications. 11 12 ## Implementation Guidelines 13 14 - **PageModel**: Keep logic in PageModel, not in `.cshtml`. Use handlers (`OnGet`, `OnPost`). 15 - **Model Binding**: Use `[BindProperty]` for form data. `[FromQuery]` for query params. 16 - **Tag Helpers**: Use `asp-for`, `asp-action`, `asp-route-*` for type-safe HTML. 17 - **Partial Views**: Reusable UI components with `<partial>` tag helper. 18 - **View Components**: Complex reusable UI with server logic. 19 - **Layout**: Shared layout in `_Layout.cshtml`. Use sections for page-specific content. 20 - **TempData**: Flash messages with PRG (Post-Redirect-Get) pattern. 21 22 ## Anti-Patterns 23 24 - **No logic in `.cshtml`**: Move to PageModel or View Components. 25 - **No `ViewBag`/`ViewData`**: Use strongly-typed models. 26 - **No inline CSS/JS**: Use external files with bundling. 27 - **No form without anti-forgery**: Always include `@Html.AntiForgeryToken()` or use `asp-antiforgery`. 28 29 ## Code 30 31 ```csharp 32 // Pages/Users/Create.cshtml.cs 33 public class CreateModel(IUserService userService, ILogger<CreateModel> logger) : PageModel 34 { 35 [BindProperty] 36 public CreateUserInput Input { get; set; } = new(); 37 38 public List<SelectListItem> Roles { get; set; } = []; 39 40 public async Task OnGetAsync() 41 { 42 Roles = await GetRolesAsync(); 43 } 44 45 public async Task<IActionResult> OnPostAsync() 46 { 47 if (!ModelState.IsValid) 48 { 49 Roles = await GetRolesAsync(); 50 return Page(); 51 } 52 53 var result = await userService.CreateAsync(Input); 54 55 if (!result.IsSuccess) 56 { 57 ModelState.AddModelError(string.Empty, result.Error!); 58 Roles = await GetRolesAsync(); 59 return Page(); 60 } 61 62 TempData["Success"] = "User created successfully"; 63 return RedirectToPage("./Index"); 64 } 65 } 66 ``` 67 68 ```html 69 @* Pages/Users/Create.cshtml *@ 70 @page 71 @model CreateModel 72 73 <h2>Create User</h2> 74 75 @if (TempData["Error"] is string error) 76 { 77 <div class="alert alert-danger">@error</div> 78 } 79 80 <form method="post"> 81 <div asp-validation-summary="ModelOnly" class="text-danger"></div> 82 83 <div class="mb-3"> 84 <label asp-for="Input.Name" class="form-label"></label> 85 <input asp-for="Input.Name" class="form-control" /> 86 <span asp-validation-for="Input.Name" class="text-danger"></span> 87 </div> 88 89 <div class="mb-3"> 90 <label asp-for="Input.Email" class="form-label"></label> 91 <input asp-for="Input.Email" class="form-control" type="email" /> 92 <span asp-validation-for="Input.Email" class="text-danger"></span> 93 </div> 94 95 <div class="mb-3"> 96 <label asp-for="Input.RoleId" class="form-label"></label> 97 <select asp-for="Input.RoleId" asp-items="Model.Roles" class="form-select"> 98 <option value="">Select a role</option> 99 </select> 100 <span asp-validation-for="Input.RoleId" class="text-danger"></span> 101 </div> 102 103 <button type="submit" class="btn btn-primary">Create</button> 104 <a asp-page="./Index" class="btn btn-secondary">Cancel</a> 105 </form> 106 107 @section Scripts { 108 <partial name="_ValidationScriptsPartial" /> 109 } 110 ``` 111 112 ## Reference & Examples 113 114 For page conventions, view components, and AJAX patterns: 115 See [references/REFERENCE.md](references/REFERENCE.md). 116 117 ## Related Topics 118 119 aspnet-core | blazor | security 120 121 --- 122 > Converted and distributed by [TomeVault](https://tomevault.io/claim/ngxtm) — claim your Tome and manage your conversions. 123 <!-- tomevault:4.0:skill_md:2026-04-13 -->
tomevault-io/skills-registry/tree/main/ngxtm--devkit--razor-pages commit 8acbe05e13
Frequently asked questions How do I install the Razor Pages skill? Run npx skillmds@latest add tomevault-io/razor-pages in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
What does the Razor Pages skill do? ASP.NET Core Razor Pages patterns for server-rendered web apps. Use when this capability is needed. It is listed under Coding & Dev Tools on SkillMD.
Is Razor Pages safe to use? SkillMD's automated safety review verdict for this skill is PASS. Independent scanners report: SkillSpector: PASS, Skill Scanner: PASS. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
Which AI agents work with Razor Pages? This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Is Razor Pages free to use? Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
Who published Razor Pages? tomevault-io (@tomevault-io) published this skill. Their other Agent Skills are listed on their SkillMD profile.