Razor Pages是ASP.NET Core 2.0引入的一种页面开发模型,与传统的MVC模式相比,它把页面相关的逻辑集中在一起,一个页面对应一个处理类,结构更简单,特别适合开发内容型网站、后台管理系统这类以页面为单位的应用。这篇文章用实际操作的方式,带你从零开始创建一个Razor Pages项目,并逐步完成一个完整的数据录入与展示功能。

一、创建项目并了解Razor Pages的结构
先确认本机已安装.NET SDK,可以在命令行执行dotnet --version查看版本。创建项目非常简单,打开终端执行以下命令即可生成一个Razor Pages模板项目:
dotnet new webapp -o MyRazorApp cd MyRazorApp dotnet run
命令执行完毕后,浏览器访问 https://localhost:5001 就能看到模板自带的首页。如果想用Visual Studio,则在新建项目时选择「ASP.NET Core Web 应用」模板,确认勾选「启用 Razor Pages」即可,两者生成的结果是一样的。
生成的项目中,Pages文件夹是Razor Pages的核心目录,所有页面都放在这里。打开Pages/Index.cshtml你会看到页面顶部有一行@page指令,这个指令是Razor Pages的标志,它告诉框架这个文件是一个独立页面而不是MVC的局部视图,少了这一行页面将无法直接被访问。
除了.cshtml视图文件,Pages目录下还有一个Index.cshtml.cs文件,这就是页面对应的PageModel类。它承担了页面的数据处理工作,比如准备显示数据、处理表单提交等。这种一个页面对应一个类的模式叫「单文件模型」,相比MVC把Controller和View分离的写法,查找某个页面的逻辑要直观得多。另外,Pages/_ViewImports.cshtml和Pages/Shared文件夹负责引入命名空间和布局页,新页面不需要手动添加using语句就能使用标签助手等特性。
二、Razor Pages页面的组成与页面路由规则
Razor Pages的路由遵循「文件即路由」的原则,Pages目录下的文件路径直接映射为URL地址。例如Pages/Products/Detail.cshtml对应的访问路径就是 /Products/Detail。如果需要自定义路由参数,可以在@page指令后面直接写模板:
@page "/product/{id:int}"
<h2>商品编号:@RouteData.Values["id"]</h2>这里的{id:int}是路由约束,表示参数必须是整数,否则返回404。这种写法不需要像MVC那样单独配置路由表,直接写在页面顶部即可,非常直观。
PageModel类中通过OnGet、OnPost这样的处理方法响应不同类型的HTTP请求。方法名遵循 On + HTTP动词 + 可选处理程序名称 的规则。比如同一个页面有多个表单按钮时,可以通过asp-page-handler指定处理程序:
public void OnGet() { }
public void OnPostSave() { }
public void OnPostDelete() { }页面上对应的按钮写成<button asp-page-handler="Save">保存</button>和<button asp-page-handler="Delete">删除</button>,框架会根据handler名称自动调用对应方法,避免在一个OnPost里写一堆if判断,代码可读性明显提升。
三、实战:创建一个带表单提交的用户信息页面
下面完成一个完整例子:创建一个用户信息录入页面,提交后在页面上显示提交结果。先在Pages目录下新建User.cshtml和User.cshtml.cs两个文件(也可以在Visual Studio中右键Pages文件夹,添加「Razor 页面」并勾选生成PageModel类)。
PageModel部分代码如下:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel.DataAnnotations;
public class UserModel : PageModel
{
[BindProperty]
[Required(ErrorMessage = "姓名不能为空")]
[StringLength(10, ErrorMessage = "姓名不能超过10个字")]
public string Name { get; set; }
[BindProperty]
[Range(1, 120, ErrorMessage = "年龄必须在1到120之间")]
public int Age { get; set; }
public string Result { get; set; }
public void OnGet()
{
// 首次访问页面时初始化
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
// 校验失败,返回当前页面,错误信息自动显示
return Page();
}
Result = $"用户 {Name},年龄 {Age},提交成功!";
return Page();
}
}这里有两个关键点值得展开说明。第一个是[BindProperty]特性,它让属性与页面上同名的表单字段自动绑定,属性默认只对POST请求绑定,GET请求需要加SupportsGet = true参数。第二个是ModelState.IsValid校验,配合DataAnnotations特性,框架会在提交时自动执行验证,校验失败时返回Page(),页面上的验证标签助手会自动渲染错误提示,不需要手写校验代码。
页面的视图部分如下:
@page
@model UserModel
<h2>用户信息录入</h2>
<form method="post">
<div>
<label>姓名</label>
<input asp-for="Name" />
<span asp-validation-for="Name"></span>
</div>
<div>
<label>年龄</label>
<input asp-for="Age" />
<span asp-validation-for="Age"></span>
</div>
<button type="submit">提交</button>
</form>
@if (!string.IsNullOrEmpty(Model.Result))
{
<p style="color:green">@Model.Result</p>
}asp-for标签助手会自动为输入框生成name、id以及对应的类型属性,asp-validation-for则负责显示校验错误。运行项目访问 /User,就能看到一个带服务端验证的完整表单页。
四、页面跳转与开发效率技巧
实际开发中经常需要在页面之间跳转并传递数据。PageModel中常用的方式有三种:RedirectToPage用于跳转到指定页面,可以带路由参数;TempData配合[TempData]特性可以跨页面传递一次性数据,常用于操作成功提示。示例:
public IActionResult OnPost()
{
// 处理完成后跳转到列表页
return RedirectToPage("List", new { id = 1 });
}需要注意的是,RedirectToPage的参数是页面名称而不是URL,写"List"会自动定位到当前目录下的List.cshtml,跨目录时要写"/Products/Detail"这样的完整路径。
开发调试阶段还有一个很实用的功能叫Runtime Compilation,安装Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation包并在Program中调用AddRazorRuntimeCompilation()后,修改.cshtml文件无需重启应用,保存刷新即可生效,能节省大量调试时间。另外,配合基架(Scaffold)功能可以基于实体类自动生成增删改查全套页面,命令如下:
dotnet aspnet-codegenerator razorpage -m Student -dc AppDbContext -udl -outDir Pages/Students
掌握这些基础之后,Razor Pages的日常开发基本就够用了。它省去了MVC中Controller、View、ViewModel来回切换的成本,逻辑集中在PageModel里,配合标签助手和模型绑定,写一个功能完整的页面通常只需要几十行代码,是C# Web开发中性价比很高的选择。
Razor PagesC#开发ASP.NET Core修改时间:2026-09-13 15:36:49