ASP.NET Core MVC是官方推荐的开箱即用MVC实现,无需手写分层;控制器需继承Controller,返回IActionResult,模型为POCO类,视图按约定路径存放并匹配模型类型。

ASP.NET Core MVC 是官方推荐的、开箱即用的 MVC 实现,不是靠手写三个类模拟出来的“伪 MVC”。直接用框架,别自己造轮子。
为什么不用手动实现 Controller/Model/View 分层
手写 Controller 基类、IView 接口、ViewEngine 解析逻辑,看似“理解本质”,实际会卡在路由绑定、模型绑定、依赖注入、生命周期管理、异步支持等底层细节上。ASP.NET Core 已把 MVC 拆成可替换的组件(如 MvcOptions、IActionResult、ViewResult),你只需要按约定组织代码。
- 控制器必须继承
Controller或ControllerBase,方法返回IActionResult类型 - 模型类只需是普通 C# 类(POCO),无需继承特定基类或打属性标记(除非需要验证)
- 视图文件必须放在
Views/{ControllerName}/{ActionName}.cshtml路径下,且使用@model声明类型
最简可行的 MVC 三件套写法
以一个显示用户列表的场景为例,不引入数据库或服务层,聚焦结构本身:
@* Views/Home/Index.cshtml *@ @model List用户列表
@foreach (var user in Model) {
- @user.Name (@user.Email)
}
// Controllers/HomeController.cs
public class HomeController : Controller
{
public IActionResult Index()
{
var users = new List
{
new User { Name = "张三", Email = "zhang@example.com" },
new User { Name = "李四", Email = "li@example.com" }
};
return View(users); // 自动查找 Views/Home/Index.cshtml
}
} // Models/User.cs
public class User
{
public string Name { get; set; }
public string Email { get; set; }
}常见踩坑点:View 和 Controller 不匹配
错误现象:The view 'Index' was not found. 或 InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List`1[MyApp.Models.User]', but this ViewDataDictionary instance requires a model item of type 'MyApp.Models.User'.
-
return View(users)传的是List,但视图里写了@model User→ 必须改成@model List - 视图文件名拼错,比如写成
Index.cshtm(少了个 l)或放在Views/Shared/Index.cshtml却没加[ViewLocationFormats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.razor.razorviewengineoptions.viewlocationformats)配置 - 控制器方法名不是
public IActionResult Index(),而是public void Index()→ 框架无法识别为 Action,也不会触发视图查找
需要自定义行为时,优先扩展而非重写
比如想统一处理未授权请求,不要重写整个 Controller 基类,而是用过滤器:
// Filters/RequireAuthFilter.cs
public class RequireAuthFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (!context.HttpContext.User.Identity.IsAuthenticated)
{
context.Result = new RedirectToActionResult("Login", "Account", null);
}
}
}然后在控制器上加 [TypeFilter,或全局注册到 services.AddControllersWithViews(options => options.Filters.Add
真正难的从来不是“怎么分三层”,而是路由怎么配、模型绑定怎么调、ViewComponent 怎么复用、TagHelper 怎么写——这些才是日常高频问题。MVC 结构只是骨架,血肉全在配置和约定里。










