根本原因是项目模板错误或配置缺失:创建的是Web API模板、未安装Razor运行时编译包、控制器未继承Controller类;视图路径须为Views/{ControllerName}/{ActionName}.cshtml,且需确保模型非空及命名空间正确引用。

ASP.NET Core MVC 中没有“添加视图”向导自动生成 .cshtml 文件的默认行为(不像旧版 ASP.NET MVC),必须手动创建或依赖控制器动作右键菜单——但这个菜单是否出现,取决于项目类型和 SDK 配置。
为什么右键控制器里找不到“添加视图”?
这是最常卡住新手的第一步。根本原因不是操作错了,而是项目模板不对:
- 你创建的是
ASP.NET Core Web API模板(默认不含视图支持) - 你用了
Microsoft.NET.Sdk.Web但没安装Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation包(开发期编译视图需要) - 控制器类没继承
Controller(比如继承了ApiController),导致 VS 不识别为 MVC 控制器上下文
验证方法:打开控制器,确认类声明是 public class HomeController : Controller,且命名空间含 Microsoft.AspNetCore.Mvc。
手动创建 .cshtml 视图文件的路径和命名规则
视图文件必须放在 Views/{ControllerName}/{ActionName}.cshtml 路径下,大小写敏感,且控制器名要去掉 Controller 后缀:
-
HomeController→ 对应Views/Home/文件夹 -
Index()方法 → 对应Views/Home/Index.cshtml -
UserProfileController→ 对应Views/UserProfile/,不是Views/Userprofile/
如果路径错,运行时会报 The view 'Index' was not found,错误页里会列出它实际查找的所有路径,直接照着建就行。
ViewBag / ViewData / ViewModel 三种传值方式怎么选?
它们不是并列替代关系,适用场景差异明显:
-
ViewBag是动态对象,适合临时、少量、非关键数据(如页面标题、通知消息),但无编译检查,容易拼错属性名 -
ViewData是字典,需手动as类型转换,比ViewBag略安全一点,但依然弱类型 - 强类型
@model MyViewModel是唯一推荐用于表单、列表、详情页的方式;它让 Razor 编译器能校验属性存在性,也支持asp-for标签助手自动绑定
示例:@model List<Movie> 比 @ViewBag.Movies 更可靠,尤其在重构实体类字段名时。
Razor 视图中引用模型属性的常见陷阱
即使 @model 声明正确,运行时仍可能报 Object reference not set to an instance of an object:
- 控制器返回
View(null)或View(new List<Movie>())但视图里写了@Model.First().Title—— 忘记判空 - 使用
asp-for="Title"时,Title是string类型,但模型里定义成了public string? Title { get; set; }(可空引用类型),Razor 在 .NET 6+ 默认开启 nullable 检查,会警告甚至报错 -
@using引入命名空间漏掉子命名空间,比如模型在MyApp.Models.ViewModels,但只写了@using MyApp.Models
最稳妥的做法:在视图顶部用 @model 显式声明类型,并在访问前用 @if (Model?.Any() == true) 或 @Model?.Title ?? "N/A" 处理空值。
真正麻烦的从来不是“怎么建文件”,而是路径匹配规则、模型生命周期和空引用这三者交织在一起时的静默失败——调试时多看一眼 ViewLocationExpander 实际搜了哪些路径,比反复重命名文件更省时间。


















