C# 入门篇:ASP.NET Core Web API 实战
背景
ASP.NET Core 是微软开源的跨平台 Web 框架,在 TechEmpower 基准测试中常年 Top 10。本教程带你构建一个完整的图书管理 Web API。
核心概念
1. 中间件管道
请求依次经过每个中间件,构成管道(Pipeline)。内置中间件:异常处理、静态文件、路由、认证、CORS。
var app = builder.Build();
app.UseExceptionHandler("/error");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
2. 依赖注入(DI)
.NET 内置 IoC 容器。注册服务后,通过构造函数自动注入。
builder.Services.AddScoped<IBookService, BookService>();
builder.Services.AddDbContext<AppDbContext>(...);
public class BooksController : ControllerBase
{
private readonly IBookService _service;
public BooksController(IBookService service) => _service = service;
}
3. 配置系统
支持 appsettings.json、环境变量、命令行参数,自动合并。
{
"ConnectionStrings": {
"Default": "Data Source=app.db"
}
}
var connStr = builder.Configuration.GetConnectionString("Default");
分步操作
第一步:创建项目
dotnet new webapi -n BookApi
cd BookApi
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
第二步:定义模型与 DbContext
public class Book
{
public int Id { get; set; }
public string Title { get; set; } = "";
public string Author { get; set; } = "";
public decimal Price { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Book> Books => Set<Book>();
public AppDbContext(DbContextOptions<AppDbContext> opts) : base(opts) {}
}
第三步:创建 Service 层
public interface IBookService
{
Task<List<Book>> GetAllAsync();
Task<Book?> GetByIdAsync(int id);
Task<Book> CreateAsync(Book book);
Task<bool> UpdateAsync(int id, Book book);
Task<bool> DeleteAsync(int id);
}
第四步:编写 Controller
利用 [ApiController] 属性自动处理模型验证错误。
第五步:数据库迁移
dotnet ef migrations add InitialCreate
dotnet ef database update
思考题
AddScoped、AddSingleton、AddTransient 三种生命周期有什么区别?
- 中间件顺序为什么重要?如果
UseAuthentication 放在 UseAuthorization 之后会怎样?
- Entity Framework Core 的
AsNoTracking() 什么场景使用?
C# 进阶篇:EF Core、异步编程与性能优化
背景
Entity Framework Core 是 .NET 最流行的 ORM。掌握其高级用法与异步编程模式,是构建高性能 .NET 应用的基础。
核心概念
1. Task-based 异步模式
public IActionResult GetBooks()
{
var books = _context.Books.ToList(); // 阻塞线程
return Ok(books);
}
public async Task<IActionResult> GetBooksAsync()
{
var books = await _context.Books.ToListAsync(); // 释放线程
return Ok(books);
}
2. EF Core 查询优化
var books = await _context.Books.ToListAsync();
foreach (var b in books) Console.WriteLine(b.Author.Name);
var books = await _context.Books
.Include(b => b.Author)
.ToListAsync();
var result = await _context.Books
.Select(b => new { b.Title, AuthorName = b.Author.Name })
.ToListAsync();
3. 并发处理
public class Book
{
[Timestamp]
public byte[] RowVersion { get; set; }
}
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
}
4. 原生 SQL 和存储过程
var books = await _context.Books
.FromSqlRaw("SELECT * FROM Books WHERE Price > {0}", minPrice)
.ToListAsync();
var result = await _context.Database
.ExecuteSqlRawAsync("EXEC UpdateBookPrice @id, @price",
new SqliteParameter("@id", id),
new SqliteParameter("@price", price));
5. CancellationToken
[HttpGet]
public async Task<IActionResult> GetBooks(CancellationToken ct)
{
var books = await _context.Books.ToListAsync(ct);
return Ok(books);
}
性能检查清单
| 优化项 |
方法 |
| 查询性能 |
投影(Select)、分页、索引、无跟踪查询 |
| 内存 |
AsNoTracking() 只读查询、流式枚举 |
| 并发 |
连接池(AddDbContextPool)、限流中间件 |
| 序列化 |
System.Text.Json 源码生成(AOT) |
| 启动 |
ReadyToRun、Native AOT 编译 |
思考题
ConfigureAwait(false) 在 ASP.NET Core 中还需要吗?为什么?
- EF Core 的
IQueryable 和 IEnumerable 有什么区别?为什么要把 IQueryable 传给 OData?
- Native AOT 有什么限制?哪些场景不适合 AOT 编译?
C# / ASP.NET Core 毕设入门教程
前言
C# 在毕设中的三大主战场:ASP.NET Core Web API 后端、WPF/WinForms 桌面应用、Unity 游戏开发。本教程聚焦毕设最常用的 ASP.NET Core + EF Core 后端开发。
第一章:快速搭建 Web API 项目
三板斧创建项目
dotnet new webapi -n MyProject
cd MyProject
dotnet run
项目结构
MyProject/
├── Controllers/ # API 控制器
├── Models/ # 数据模型
├── Services/ # 业务逻辑
├── Data/ # DbContext
├── appsettings.json # 配置文件
└── Program.cs # 入口
第二章:构建一个完整的 CRUD API
Model
public class TodoItem
{
public int Id { get; set; }
public string Title { get; set; } = "";
public bool IsCompleted { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}
DbContext
public class AppDbContext : DbContext
{
public DbSet<TodoItem> Todos => Set<TodoItem>();
public AppDbContext(DbContextOptions<AppDbContext> o) : base(o) {}
}
Controller(最小 API 风格)
app.MapGet("/todos", async (AppDbContext db) => await db.Todos.ToListAsync());
app.MapPost("/todos", async (TodoItem todo, AppDbContext db) =>
{
db.Todos.Add(todo);
await db.SaveChangesAsync();
return Results.Created($"/todos/{todo.Id}", todo);
});
app.MapDelete("/todos/{id}", async (int id, AppDbContext db) =>
{
var todo = await db.Todos.FindAsync(id);
if (todo is null) return Results.NotFound();
db.Todos.Remove(todo);
await db.SaveChangesAsync();
return Results.NoContent();
});
第三章:毕设常用模式
三层架构
Controller → Service → Repository → DbContext
JWT 认证(毕设加分项)
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => {
options.TokenValidationParameters = new() {
ValidateIssuer = true,
ValidateAudience = true,
};
});
全局异常处理
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("{\"error\":\"服务器内部错误\"}");
});
});
第四章:毕设答辩要点
演示流程建议
- 启动项目
dotnet run
- 打开 Swagger 页面展示 API 列表
- 用 Swagger 调几个接口展示 CRUD
- 展示数据库中的数据(SQLite 用 DB Browser 打开)
常见答辩问题
- "为什么选 ASP.NET Core 而不是 Spring Boot?" → 强调 .NET 生态、LINQ 开发效率、学习曲线
- "数据库用的什么?" → SQLite 零部署,适合毕设
- "安全性怎么保证?" → JWT 认证、参数校验、CORS 配置
思考题
- RESTful API 的设计原则有哪些?你的接口是否符合?
async/await 在 ASP.NET Core 中的作用是什么?
- EF Core 的
Include() 和 ThenInclude() 解决了什么问题?