razor pages 无需控制器和手动路由,@page 必须首行、双文件生成、@model 全限定名严格匹配、数据在 onget 加载、program.cs 需 addrazorpages 和 maprazorpages。

直接创建 Razor Pages 不需要控制器或手动配置路由,@page 加上、双文件生成、OnGet 里加载数据,页面就可访问——这是它和 MVC 的根本区别。
怎么新建一个合法的 Razor Page 文件
必须用 Visual Studio 的“Razor 页面”模板生成,不能手建 .cshtml 单文件,也不能选错成“Razor 视图”。否则会缺失 .cshtml.cs 后置类、没有 @page 指令、运行时 404。
- 在
Pages文件夹右键 → “添加” → “新建项” → 选“Razor 页面”(不是“Razor 视图”) - 生成后必须有两份文件:
PizzaList.cshtml和PizzaList.cshtml.cs -
@page必须是.cshtml文件第一行,前面不能有空行、注释或空白字符,否则编译报错:The 'page' directive must be the first content in the file
为什么 @model 类型总报错:The model item passed into the ViewDataDictionary is of type '' but this ViewDataDictionary is for type ''
这是命名空间或类名不匹配导致的运行时类型校验失败。Razor 页面的 @model 指令必须和后置类的完整声明完全一致——包括大小写、命名空间、类名。
-
PizzaList.cshtml中写:@model ContosoPizza.Pages.PizzaListModel - 那
PizzaList.cshtml.cs中就必须是:public class PizzaListModel : PageModel,且所在命名空间为ContosoPizza.Pages - 漏写命名空间(如只写
@model PizzaListModel)或大小写错误(如pizzalistmodel),都会触发这个InvalidOperationException
数据该在哪加载:OnGet 还是构造函数
必须在 OnGet 或 OnGetAsync 方法中加载数据,不能在 PageModel 构造函数里做任何依赖注入后的异步操作或数据库访问。
- 构造函数执行时机早于请求上下文建立,
HttpContext、ModelState、ModelStateDictionary都不可用 -
OnGet是第一个能安全使用 DI 服务、读取路由参数、写入ViewData或TempData的入口 - 带路由参数时,例如
@page "/pizza/{id:int}",对应方法签名应为:public void OnGet(int id),框架自动绑定 - 别在
@{ }代码块里重复声明同名属性(如var Pizzas = new List<pizza>();</pizza>),会遮蔽@Model.Pizzas
Program.cs 里忘了 MapRazorPages 就会 404
Razor Pages 不走 MVC 的 MapControllerRoute,必须显式调用 MapRazorPages(),否则所有 @page 页面都返回 404。
- 确认
Program.cs中有这两行(顺序不能颠倒):builder.Services.AddRazorPages();和app.MapRazorPages(); -
MapRazorPages()必须在UseRouting()之后、app.Run()之前 - 如果同时用了 MVC,不要把
MapRazorPages()和MapControllerRoute()写反顺序,否则 Razor Pages 路由可能被 MVC 的通配规则覆盖
最容易忽略的是 @page 的位置和 @model 的全限定名——它们不出现在运行时错误堆栈里,但只要错一个字符,页面就白屏或抛出类型不匹配异常,调试时得先盯死这两处。











