1. 环境准备与项目创建第一次接触Asp.NET Core WebAPI时我踩过的第一个坑就是环境配置。很多人以为装个Visual Studio就万事大吉其实远不止如此。这里分享我的标准开发环境清单Visual Studio 2022社区版就够用记得勾选ASP.NET和Web开发工作负载.NET 6 SDK官方推荐LTS版本生产环境更稳定PostmanAPI调试神器比Swagger更灵活SQL Server Express轻量级数据库本地开发足够创建项目时有个关键选择Minimal API还是传统MVC风格我建议新手从传统方式开始。用命令行创建项目时dotnet new webapi -n MyFirstAPI这个命令会生成标准项目结构但有几个隐藏坑点默认启用了Swagger但生产环境需要手动关闭Program.cs使用了新式顶级语句老.NET开发者可能不习惯WeatherForecast示例控制器用了最小化语法实际项目不建议提示如果遇到无法加载DLL错误通常是运行时没装对。用dotnet --list-runtimes检查是否安装了对应版本的ASP.NET Core运行时。2. 控制器与路由的实战技巧2.1 控制器基础新手最容易犯的错误就是混淆ControllerBase和Controller。记住这个铁律纯API项目永远用ControllerBase需要返回视图才用Controller标准控制器写法示例[ApiController] [Route(api/[controller])] public class ProductsController : ControllerBase { [HttpGet] public IActionResult GetAll() { // 实际项目这里应该用异步方法 var products _repository.GetProducts(); return Ok(products); } }2.2 路由配置的坑路由配置看似简单但有几个魔鬼细节[controller]占位符会去掉Controller后缀ProductsController变成/products混合路由时顺序很重要[Route(api/[controller])] [Route(api/v{version:apiVersion}/[controller])] // 支持版本控制动态参数需要类型约束[HttpGet({id:int})] // 限制id必须为int public IActionResult GetById(int id) {...}3. 依赖注入的正确姿势3.1 服务注册的三种生命周期我见过太多人乱用生命周期导致内存泄漏Transient每次请求创建新实例轻量级服务Scoped每个请求一个实例最常用Singleton全局单例要线程安全典型错误案例// 错误DbContext不能是Singleton services.AddSingletonAppDbContext(); // 正确做法 services.AddScopedAppDbContext();3.2 解决循环依赖当A依赖BB又依赖A时可以这样解// 在Program.cs中 builder.Services.AddScopedIServiceA(sp { var b sp.GetRequiredServiceIServiceB(); return new ServiceA(b); });4. 中间件顺序的玄机中间件管道就像洋葱顺序决定行为。这是我总结的黄金顺序ExceptionHandler最外层捕获异常HSTS安全协议HTTPS重定向StaticFiles静态文件Routing路由Authentication认证Authorization授权自定义中间件Endpoints终结点曾经有个生产事故就是因为把CORS放在了Routing之后导致跨域失败。正确写法app.UseCors(AllowAll); // 必须在UseRouting之前 app.UseRouting();5. 配置文件与环境管理5.1 多环境配置ASP.NET Core原生支持环境配置但很多人不会用// 开发环境用appsettings.Development.json // 生产环境自动切换为appsettings.Production.json var env builder.Environment; builder.Configuration .AddJsonFile($appsettings.{env.EnvironmentName}.json, optional: true);5.2 安全存储敏感数据千万别把连接字符串硬编码推荐两种方式开发环境Secret Managerdotnet user-secrets set DB:Password 123456生产环境Azure Key Vault或环境变量6. 异常处理最佳实践全局异常处理我推荐这种组合拳// Program.cs builder.Services.AddProblemDetails(); // 标准化错误响应 app.UseExceptionHandler(exceptionHandlerApp { exceptionHandlerApp.Run(async context { context.Response.ContentType application/json; var exception context.Features.GetIExceptionHandlerFeature()?.Error; var problem new ProblemDetails { Title exception?.GetType().Name, Detail exception?.Message, Status exception switch { NotFoundException 404, _ 500 } }; await context.Response.WriteAsJsonAsync(problem); }); });7. 性能优化技巧7.1 响应压缩简单但效果显著builder.Services.AddResponseCompression(options { options.Providers.AddGzipCompressionProvider(); options.EnableForHttps true; });7.2 缓存策略API缓存可以大幅减轻数据库压力[HttpGet] [ResponseCache(Duration 60)] // 客户端缓存60秒 public IActionResult GetProducts() {...}8. 部署到生产环境8.1 IIS部署注意事项必须安装ASP.NET Core模块web.config需要特殊配置aspNetCore processPathdotnet arguments.\MyApp.dll stdoutLogEnabledtrue/应用程序池要设为无托管代码8.2 Docker部署技巧我的标准Dockerfile模板FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base WORKDIR /app EXPOSE 80 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY [MyAPI.csproj, .] RUN dotnet restore COPY . . RUN dotnet publish -c Release -o /app FROM base AS final WORKDIR /app COPY --frombuild /app . ENTRYPOINT [dotnet, MyAPI.dll]9. 日志与监控9.1 结构化日志别再用Console.WriteLine了Serilog是更好的选择builder.Host.UseSerilog((ctx, lc) lc .WriteTo.Console() .WriteTo.File(logs/log-.txt, rollingInterval: Day));9.2 健康检查生产环境必备builder.Services.AddHealthChecks() .AddSqlServer(Configuration.GetConnectionString(Default)); app.MapHealthChecks(/health);10. 安全防护要点HTTPS重定向builder.Services.AddHttpsRedirection(opts { opts.RedirectStatusCode 308; opts.HttpsPort 443; });CORS策略builder.Services.AddCors(opts { opts.AddPolicy(MyPolicy, policy { policy.WithOrigins(https://trusted.com) .AllowAnyHeader() .AllowAnyMethod(); }); });11. 测试策略11.1 单元测试xUnit是首选记得Mock外部依赖public class ProductsControllerTests { [Fact] public async Task Get_ReturnsProducts() { var mockRepo new MockIProductRepository(); mockRepo.Setup(repo repo.GetAllAsync()) .ReturnsAsync(new ListProduct { new Product() }); var controller new ProductsController(mockRepo.Object); var result await controller.Get(); var okResult Assert.IsTypeOkObjectResult(result); var items Assert.IsTypeListProduct(okResult.Value); Assert.Single(items); } }11.2 集成测试使用WebApplicationFactorypublic class ApiTests : IClassFixtureWebApplicationFactoryProgram { private readonly HttpClient _client; public ApiTests(WebApplicationFactoryProgram factory) { _client factory.CreateClient(); } [Fact] public async Task Get_ReturnsSuccess() { var response await _client.GetAsync(/api/products); response.EnsureSuccessStatusCode(); } }12. 常见故障排查502 Bad Gateway检查应用是否崩溃查看Windows事件日志启动超时增加IIS的启动超时时间跨域失败确保CORS中间件顺序正确依赖注入失败检查服务生命周期是否匹配13. 进阶技巧13.1 动态API版本控制builder.Services.AddApiVersioning(opts { opts.DefaultApiVersion new ApiVersion(1, 0); opts.ReportApiVersions true; }); // 控制器中使用 [ApiVersion(1.0)] [Route(api/v{version:apiVersion}/[controller])] public class ProductsController : ControllerBase {...}13.2 实时通信集成SignalR实现实时推送builder.Services.AddSignalR(); app.MapHubNotificationHub(/notifications);14. 生产环境检查清单部署前务必检查[ ] 关闭开发者异常页面[ ] 启用HTTPS重定向[ ] 设置正确的CORS策略[ ] 配置日志轮转[ ] 实现健康检查端点[ ] 设置适当的缓存头15. 性能监控Application Insights是Azure生态的首选builder.Services.AddApplicationInsightsTelemetry(opts { opts.ConnectionString builder.Configuration[APPINSIGHTS_CONNECTIONSTRING]; });对于非Azure环境PrometheusGrafana是不错的选择builder.Services.AddHealthChecks() .AddPrometheusGatewayHealthPublisher(); app.UseHttpMetrics(); app.MapMetrics();16. 持续集成/部署GitHub Actions示例name: Deploy API on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Setup .NET uses: actions/setup-dotnetv3 with: dotnet-version: 6.0.x - name: Publish run: dotnet publish -c Release -o ./publish - name: Deploy to Azure Web App uses: azure/webapps-deployv2 with: app-name: MyAPI package: ./publish17. 微服务架构考量当API需要拆分为微服务时使用Ocelot作为API网关服务发现用Consul跨服务通信用gRPC替代部分REST调用gRPC服务示例syntax proto3; service ProductService { rpc GetProduct (ProductRequest) returns (ProductResponse); } message ProductRequest { int32 id 1; } message ProductResponse { int32 id 1; string name 2; }18. 领域驱动设计实践复杂业务推荐采用DDD分层架构Application层用例 ↑ ↓ Domain层业务逻辑 ↓ ↑ Infrastructure层实现)典型项目结构MyAPI.Domain领域模型MyAPI.Application应用服务MyAPI.Infrastructure持久化实现MyAPI.API表现层19. 容器化进阶技巧多阶段构建优化Docker镜像# 第一阶段构建 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src COPY . . RUN dotnet restore RUN dotnet publish -c Release -o /app # 第二阶段运行时 FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime WORKDIR /app COPY --frombuild /app . ENTRYPOINT [dotnet, MyAPI.dll] # 添加健康检查 HEALTHCHECK --interval30s --timeout3s \ CMD curl -f http://localhost/health || exit 120. 前端集成方案20.1 与React/Vue集成推荐前后端分离架构API项目独立部署前端项目用nginx托管开发时配置代理// vite.config.js export default defineConfig({ server: { proxy: { /api: http://localhost:5000 } } })20.2 服务端渲染需要SSR时可以用builder.Services.AddRazorPages(); app.MapRazorPages();21. 国际化和本地化支持多语言API响应builder.Services.AddLocalization(opts { opts.ResourcesPath Resources; }); var supportedCultures new[] { en-US, zh-CN }; app.UseRequestLocalization(opts opts.AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures) );22. 文档自动化除了Swagger还可以用DocFX生成离线文档builder.Services.AddSwaggerGen(c { c.SwaggerDoc(v1, new OpenApiInfo { Title My API, Version v1, Description API文档 }); });23. 消息队列集成集成RabbitMQ处理异步任务builder.Services.AddHostedServiceQueueConsumerService(); builder.Services.AddSingletonIMessageProducer, RabbitMQProducer();24. 分布式追踪用OpenTelemetry实现端到端追踪builder.Services.AddOpenTelemetryTracing(builder { builder.AddAspNetCoreInstrumentation() .AddHttpClientInstrumentation() .AddJaegerExporter(); });25. 无服务器部署Azure Functions的无服务器方案public static class MyFunction { [FunctionName(GetProducts)] public static async TaskIActionResult Run( [HttpTrigger(AuthorizationLevel.Function, get)] HttpRequest req) { return new OkObjectResult(await productService.GetAll()); } }26. 性能压测技巧用Locust进行API压测from locust import HttpUser, task class ApiUser(HttpUser): task def get_products(self): self.client.get(/api/products)27. 安全加固措施启用防跨站请求伪造(CSRF)保护设置Content Security Policy(CSP)头定期更新所有NuGet包使用OWASP ZAP进行安全扫描28. 缓存策略进阶分布式Redis缓存builder.Services.AddStackExchangeRedisCache(opts { opts.Configuration builder.Configuration.GetConnectionString(Redis); });29. 后台任务处理用IHostedService实现后台服务public class BackgroundWorker : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // 执行任务 await Task.Delay(1000, stoppingToken); } } }30. 现代化API设计趋势GraphQL替代部分REST适合复杂数据需求gRPC用于内部服务通信高性能二进制协议CQRS模式读写分离架构事件溯源用事件流记录状态变更31. 实用工具推荐NSwag自动生成TypeScript客户端AutoMapper对象映射FluentValidation优雅的参数验证Polly弹性瞬态故障处理32. 团队协作规范统一代码风格(.editorconfig)使用Git Hooks做提交前检查制定API设计规范(命名/版本控制)接口变更通过OpenAPI文档同步33. 性能计数器监控Windows性能计数器配置builder.Services.AddHealthChecks() .AddProcessAllocatedMemoryHealthCheck(maximumMegabytes: 512) .AddPrivateMemoryHealthCheck(maximumMegabytes: 1024);34. 自动化API测试用Postman Collection做自动化测试newman run MyAPI.postman_collection.json \ --environmentProduction.postman_environment.json35. 实用调试技巧热重载dotnet watch run远程调试vsdbg工具内存转储分析ProcdumpWinDbg网络跟踪Fiddler或Wireshark36. 数据库迁移策略EF Core迁移命令备忘# 创建迁移 dotnet ef migrations add InitialCreate # 应用迁移 dotnet ef database update # 生成SQL脚本 dotnet ef migrations script -o migration.sql37. 响应式扩展用System.Reactive处理事件流public IObservableProduct GetProductStream() { return Observable.Interval(TimeSpan.FromSeconds(1)) .Select(_ _productRepository.GetRandom()); }38. 实时日志查看用Serilog.Sinks.Browser实现浏览器实时日志builder.Services.AddSerilogLogging(opts { opts.WriteTo.BrowserConsole(); });39. 多租户架构实现租户隔离的几种方案每个租户独立数据库共享数据库Schema隔离共享表租户ID过滤40. 结语与持续学习技术永远在演进建议定期关注Microsoft官方ASP.NET Core博客.NET Conf年度大会GitHub上的dotnet/runtime仓库Stack Overflow的asp.net-core标签