ASP.NET MVC 完整教程
ASP.NET MVC 是微软用于构建 Web 应用程序的一种强大、灵活且可测试的框架,它基于经典的 MVC (Model-View-Controller) 设计模式,将应用程序的关注点清晰地分离开来。

目录
-
第一部分:基础入门
- 什么是 ASP.NET MVC?
- 为什么选择 MVC?(与传统 Web Forms 的对比)
- 环境准备与项目创建
- MVC 项目核心文件结构解析
- 第一个 MVC 应用程序:Hello World!
-
第二部分:核心概念详解
- M - Model (模型): 数据与业务逻辑
- V - View (视图): 用户界面
- C - Controller (控制器): 应用程序的指挥官
- 路由: 请求是如何到达控制器的?
- 控制器与视图的数据传递
-
第三部分:进阶实践
- 数据模型与验证
- 使用 Entity Framework (EF) 与数据库交互
- 强类型视图与
@model指令 - 布局、部分视图和 Razor 语法
- 使用 Bootstrap 快速美化界面
-
第四部分:高级主题
(图片来源网络,侵删)- 身份验证与授权
- 依赖注入
- Web API 简介
- 单元测试
第一部分:基础入门
什么是 ASP.NET MVC?
ASP.NET MVC 是一个用于构建 Web 应用程序的框架,它遵循 MVC 设计模式,将应用程序分为三个主要部分:
- Model (模型): 代表应用程序的数据和业务逻辑,它不关心数据如何显示或用户如何操作。
- View (视图): 负责显示数据,它是用户看到并与之交互的 UI 界面。
- Controller (控制器): 接收用户的输入,调用模型处理数据,然后选择一个视图来展示结果,它是 Model 和 View 之间的桥梁。
为什么选择 MVC?
| 特性 | ASP.NET MVC | ASP.NET Web Forms |
|---|---|---|
| 控制力 | 高,开发者对 HTML、CSS 和 URL 有完全的控制。 | 低,由 ViewState 和服务器控件封装,抽象了 HTTP 细节。 |
| 可测试性 | 高,天然支持单元测试,因为组件是解耦的。 | 较低,依赖 HttpContext 和页面生命周期,测试较复杂。 |
| 性能 | 较高,没有 ViewState,生成的 HTML 更轻量。 | 较低,ViewState 会产生大量数据,影响页面大小和性能。 |
| 学习曲线 | 较陡,需要理解 HTTP、路由等 Web 基础。 | 较平缓,对初学者更友好,像开发桌面应用。 |
| 适用场景 | 大型、复杂、需要高 SEO 和灵活 UI 的 Web 应用。 | 快速开发的企业级应用、内部管理系统、报表系统。 |
环境准备与项目创建
- 安装 Visual Studio: 下载并安装 Visual Studio Community (免费版)。
- 安装 .NET SDK: 确保安装了对应版本的 .NET SDK (如 .NET 6/7/8)。
- 创建项目:
- 打开 Visual Studio。
- 选择 "创建新项目"。
- 搜索并选择 "ASP.NET Web 应用程序"。
- 为项目命名,点击 "创建"。
- 在下一个窗口中,选择 "Web 应用程序 (Model-View-Controller)" 模板,然后点击 "创建"。
MVC 项目核心文件结构
创建的项目会包含以下关键文件夹:
Controllers/: 存放所有控制器类。HomeController.cs。Models/: 存放数据模型类。Views/: 存放所有的视图文件。Home/: 对应HomeController的视图。Shared/: 存放共享视图,如_Layout.cshtml(主布局页)。
wwwroot/: 存放静态文件,如 CSS、JavaScript、图片等。App_Start/: (在旧版本中常见) 包含路由配置等,在新版中,这些配置常放在Program.cs中。Program.cs: 应用程序的入口点,配置服务和中间件(包括路由)。appsettings.json: 应用程序的配置文件。
第一个 MVC 应用程序:Hello World!
- 运行项目: 按
F5或点击 "开始调试" 按钮,浏览器会打开,并显示主页。 - 查看流程:
- 你在浏览器中访问
http://localhost:xxxx/。 - 这个请求被
Program.cs中的路由规则捕获。 - 路由规则
{controller=Home}/{action=Index}/{id?}将请求映射到HomeController的Index方法。 HomeController的Index方法执行完毕,返回一个ViewResult。- MVC 框架在
Views/Home/文件夹下寻找Index.cshtml文件,并将其渲染成 HTML 返回给浏览器。
- 你在浏览器中访问
第二部分:核心概念详解
M - Model (模型)
模型是应用程序的核心,它包含:
- 属性: 定义数据结构,一个
Product模型可以有Id,Name,Price等属性。 - 数据注解: 用于验证和定义数据模型在 UI 上的显示方式。
[Required],[StringLength(100)]。
示例 (Models/Product.cs):

using System.ComponentModel.DataAnnotations;
namespace MvcMovie.Models
{
public class Product
{
public int Id { get; set; }
[Required]
[StringLength(100)]
public string Name { get; set; }
[Range(0.01, 10000)]
public decimal Price { get; set; }
}
}
V - View (视图)
视图是用户看到的 HTML,在 ASP.NET MVC 中,视图通常使用 Razor 语法,Razor 是一种轻量级的标记语法,让你可以在 HTML 中嵌入 C# 代码。
示例 (Views/Home/About.cshtml):
@{
ViewData["Title"] = "About Us";
}
<h2>@ViewData["Title"]</h2>
<h3>Welcome to our About page!</h3>
<p>This is a simple example of a Razor view.</p>
- 符号用于切换到 C# 模式。
@ViewData["Title"]从ViewData字典中获取数据并显示。
C - Controller (控制器)
控制器是处理用户输入、调用模型、并决定返回哪个视图的类,每个公共方法称为一个 Action。
示例 (Controllers/HomeController.cs):
using Microsoft.AspNetCore.Mvc;
namespace MvcMovie.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View(); // 返回 Views/Home/Index.cshtml
}
public IActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View(); // 返回 Views/Home/About.cshtml
}
}
}
HomeController继承自Controller基类。Index()和About()是 Action 方法。return View();会默认寻找一个与 Action 同名的视图文件。
路由
路由是连接 URL 和控制器的机制,它定义了 URL 模式应该如何映射到 Controller 和 Action。
在 ASP.NET Core 中,路由主要在 Program.cs 中配置:
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// ... 服务配置
var app = builder.Build();
// 1. 配置路由
app.UseRouting();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
// ... 中间件配置
app.Run();
pattern: "{controller=Home}/{action=Index}/{id?}"是默认路由规则。{controller}: 必需部分,映射到控制器名(如Home)。{action}: 必需部分,映射到 Action 方法名(如Index)。{id?}: 可选部分,通常用于获取记录 ID。
- 访问
/Products/Details/5,路由系统会尝试调用ProductsController的Details(int id)方法,并将5作为参数传入。
控制器与视图的数据传递
控制器需要向视图传递数据,有几种常见方式:
- ViewData: 一个
Dictionary<string, object>,数据是弱类型的。 - ViewBag: 基于
ViewData的动态包装器,语法更简洁,但也是弱类型的。 - 强类型模型 (Model): 推荐使用,通过
@model指令,视图可以直接接收一个强类型的对象。
示例 (传递强类型模型):
Controller:
public IActionResult ProductDetail(int id)
{
var product = new Product { Id = id, Name = "Laptop", Price = 999.99m };
return View(product); // 将 product 对象传递给视图
}
View (Views/Product/ProductDetail.cshtml):
@model MvcMovie.Models.Product // 定义视图接收的模型类型
<h2>Product Details</h2>
<div>
<h4>@Model.Name</h4>
<p>Price: @Model.Price.ToString("C")</p> // C 是货币格式
</div>
第三部分:进阶实践
数据模型与验证
利用模型上的数据注解,可以轻松实现客户端和服务器端验证。
Controller (处理 POST 请求):
[HttpPost]
[ValidateAntiForgeryToken] // 防止跨站请求伪造
public IActionResult Create(Product product)
{
if (ModelState.IsValid) // 检查模型是否通过验证
{
// 保存到数据库...
return RedirectToAction("Index");
}
// 如果验证失败,重新显示创建页面,并显示错误信息
return View(product);
}
View (使用 Tag Helper 显示验证信息):
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Create</button>
</form>
asp-for="Name"会自动生成name="Name"的input标签,并绑定模型属性。asp-validation-for="Name"会在该字段验证失败时显示错误信息。
使用 Entity Framework (EF) 与数据库交互
Entity Framework (EF) Core 是微软的 ORM(对象关系映射)框架,让你可以用 C# 对象来操作数据库。
-
安装 EF Core: 通过 NuGet 包管理器安装
Microsoft.EntityFrameworkCore.SqlServer和Microsoft.EntityFrameworkCore.Tools。 -
创建 DbContext:
DbContext是 EF 与数据库交互的主要入口。// Models/MovieContext.cs using Microsoft.EntityFrameworkCore; namespace MvcMovie.Models { public class MovieContext : DbContext { public MovieContext (DbContextOptions<MovieContext> options) : base(options) { } public DbSet<Movie> Movie { get; set; } } } -
注册 DbContext: 在
Program.cs中注册服务。// Program.cs builder.Services.AddDbContext<MovieContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("MovieContext"))); -
进行 CRUD 操作: 现在可以在 Controller 中通过依赖注入使用
MovieContext来查询、添加、修改和删除数据。
强类型视图与 @model 指令
如前所述,这是 MVC 的最佳实践,它能让你的视图获得编译时检查和智能提示,更加安全和高效。
布局、部分视图和 Razor 语法
- 布局 (
_Layout.cshtml): 定义了网站的整体结构(如头部、导航栏、页脚),其他视图可以“套用”这个布局。 - 部分视图 (
_PartialView.cshtml): 可重用的 HTML 片段,可以嵌入到其他视图中,一个产品列表、一个导航菜单等。 - Razor 语法:
@code { ... }: 定义代码块。@if (...) { ... } else { ... }: 条件语句。@for (...) { ... },@foreach (...) { ... }: 循环语句。- 转义 符号,
@(someVariable)。
使用 Bootstrap 快速美化界面
ASP.NET MVC 模板通常默认集成了 Bootstrap。
- 在
_Layout.cshtml的<head>中引入 Bootstrap CSS。 - 在
<body>底部引入 Bootstrap JS (需要 jQuery 和 Popper.js)。 - 在视图中使用 Bootstrap 的 CSS 类来快速构建响应式布局。
<div class="container"> <div class="row"> <div class="col-md-8"> <!-- 主要内容 --> </div> <div class="col-md-4"> <!-- 侧边栏 --> </div> </div> </div>
第四部分:高级主题
身份验证与授权
ASP.NET Identity 是微软推荐的会员系统,用于处理用户注册、登录、角色管理等,它支持本地登录和外部登录(如 Google, Facebook)。
- 身份验证: 验证用户的身份(“你是谁?”),通常使用登录、Cookie、JWT 等机制。
- 授权: 验证用户是否有权限访问某个资源(“你能做什么?”),只有管理员才能删除用户。
在 Controller 或 Action 上使用特性来控制访问:
[Authorize] // 必须登录才能访问
public IActionResult Profile() { ... }
[Authorize(Roles = "Admin")] // 必须是 Admin 角色才能访问
public IActionResult DeleteUser(int id) { ... }
依赖注入
依赖注入是 ASP.NET Core 的核心特性,它是一种设计模式,可以降低组件之间的耦合度,提高可测试性和可维护性。
-
注册服务: 在
Program.cs中,使用builder.Services.AddScoped<IMovieRepository, MovieRepository>();来注册服务接口和其实现。 -
注入服务: 在需要的地方(如 Controller 的构造函数),声明该接口,框架会自动提供一个实例。
public class MoviesController : Controller { private readonly IMovieRepository _movieRepository; public MoviesController(IMovieRepository movieRepository) { _movieRepository = movieRepository; } }
Web API 简介
ASP.NET MVC 和 ASP.NET Web API 使用了很多相同的基础设施(如路由、依赖注入、控制器),主要区别在于:
- MVC: 主要用于返回 HTML 页面给浏览器。
- Web API: 主要用于返回数据(通常是 JSON 或 XML)给客户端(如 JavaScript 应用、移动 App)。
创建一个 API Controller 只需让 Controller 继承自 ControllerBase,并返回 IActionResult 或特定类型(如 List<Movie>)。
[ApiController]
[Route("api/[controller]")]
public class MoviesApiController : ControllerBase
{
[HttpGet]
public IEnumerable<Movie> Get()
{
// 从数据库获取电影列表并返回
}
}
单元测试
由于 MVC 的松耦合设计,对 Controller 和 Model 进行单元测试非常容易,你可以使用像 xUnit、NUnit、Moq 这样的测试框架。
示例测试一个 Controller Action:
// 测试代码
[Fact]
public void Index_ReturnsAViewResult_WithAListOfMovies()
{
// Arrange
var mockRepo = new Mock<IMovieRepository>();
mockRepo.Setup(repo => repo.GetAll()).Returns(GetTestMovies());
var controller = new MoviesController(mockRepo.Object);
// Act
var result = controller.Index();
// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<List<Movie>>(viewResult.Model);
Assert.Equal(2, model.Count);
}
学习资源推荐
- 微软官方文档: ASP.NET Core Documentation - 最权威、最全面的资料。
- ASP.NET Core 教程 (官方): Build web apps with ASP.NET Core
- ASP.NET MVC 5 教程 (经典): ASP.NET MVC 教程 - 菜鸟教程 (适合快速入门)
- 书籍: 《ASP.NET Core in Action》、《Pro ASP.NET Core MVC》等。
- 视频: Pluralsight, Udemy, Bilibili 上有大量高质量的 ASP.NET MVC/ASP.NET Core 课程。
希望这份详细的教程能为你打开 ASP.NET MVC 的大门!祝你学习愉快!
