一、数据库配置
选择合适的数据库提供程序
.NET 支持 SQL Server、MySQL、Oracle 等数据库,每种数据库都有对应的官方或第三方提供程序。以 SQL Server 为例,常见的是 Microsoft.EntityFrameworkCore.SqlServer,通过 NuGet 安装后就能直接使用。MySQL 可以按项目实际情况选择 MySql.Data.EntityFrameworkCore,Oracle 则通常用 Oracle.EntityFrameworkCore。这一步没什么花活,关键是版本要和你手上的数据库、EF Core 版本对齐,不然后面迁移时容易踩坑。
配置数据库连接字符串
通常把连接字符串放在 appsettings.json 里:
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOUR_SERVER_NAME;Database=YOUR_DATABASE_NAME;User ID=YOUR_USERNAME;Password=YOUR_PASSWORD;Trusted_Connection=False;MultipleActiveResultSets=true"
}
}
YOUR_SERVER_NAME、YOUR_DATABASE_NAME、YOUR_USERNAME、YOUR_PASSWORD 都要替换成真实值。如果用 Windows 身份验证,可以把 User ID 和 Password 去掉,改成 Trusted_Connection=True。
在 Program.cs 里读取连接字符串并注册 DbContext:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<YourDbContext>(options =>
options.UseSqlServer(connectionString));
这里的 YourDbContext 是你自己定义的上下文类,负责和数据库打交道。
数据库迁移(以 EF Core 为例)
做迁移前,通常还要装 Microsoft.EntityFrameworkCore.Design。它不负责运行时功能,主要是给迁移命令用的。
先定义一个继承自 DbContext 的类:
using Microsoft.EntityFrameworkCore;
public class YourDbContext : DbContext
{
public YourDbContext(DbContextOptions<YourDbContext> options) : base(options)
{
}
// 定义 DbSet 属性来映射数据库表
public DbSet<YourEntity> YourEntities { get; set; }
}
YourEntity 对应数据库里的表。
然后在包管理器控制台或终端里执行迁移命令,注意切到包含 YourDbContext 的项目:
dotnet ef migrations add InitialCreate:创建一个名为InitialCreate的迁移。名字可以换,但最好能看出这次改了什么。dotnet ef database update:把数据库更新到最新迁移状态。
二、依赖注入配置
理解依赖注入
依赖注入(Dependency Injection,简称 DI)就是把对象怎么创建、依赖谁这件事交给外部容器处理。对于 WebAPI 来说,这个容器已经内置好了,直接用就行。实际开发里,它最大的价值不是'高级',而是让控制器别自己到处 new 对象,测试和维护都会轻松一些。
注册服务
Program.cs 里通过 builder.Services 注册服务。
先看框架自带的日志服务:
builder.Services.AddLogging();
再看一个自定义服务。假设有 IYourService 和它的实现 YourService:
public interface IYourService
{
void DoSomething();
}
public class YourService : IYourService
{
public void DoSomething()
{
// 业务逻辑代码
}
}
在 Program.cs 中注册它:
builder.Services.AddScoped<IYourService, YourService>();
AddScoped 的意思是每个请求一个实例,同一个请求内拿到的是同一个对象。这个生命周期在 WebAPI 里很常用,尤其是和数据库上下文配套的时候。AddSingleton 是整个应用一个实例,AddTransient 则是每次获取都重新创建。
使用依赖注入
控制器里直接通过构造函数接收依赖:
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]")]
public class YourController : ControllerBase
{
private readonly IYourService _yourService;
public YourController(IYourService yourService)
{
_yourService = yourService;
}
[HttpGet]
public IActionResult Get()
{
_yourService.DoSomething();
return Ok("Service executed successfully");
}
}
容器会在控制器创建时把 IYourService 自动注入进来。
三、Swagger 配置
安装 Swagger 相关包
安装 Swashbuckle.AspNetCore 就够了。它负责把 Web API 的接口描述、文档页和调试入口串起来。很多项目后面会把它当成接口自测入口用,省得每次都开 Postman。
配置 Swagger 服务
在 Program.cs 中添加 Swagger 配置:
using Swashbuckle.AspNetCore.SwaggerGen;
using Microsoft.OpenApi.Models;
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Your WebApi Title",
Version = "v1",
Description = "A detailed description of your WebApi",
Contact = new OpenApiContact
{
Name = "Your Name",
Email = "[email protected]",
Url = new Uri("https://example.com")
}
});
// 配置 XML 注释文件路径,用于生成详细的接口文档
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
SwaggerDoc 定义版本、标题、描述和联系人信息。IncludeXmlComments 用来把 XML 注释带进文档里,前提是你在项目属性里打开了 XML 文档文件生成。
启用中间件:
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Your WebApi V1");
c.RoutePrefix = "swagger";// 设置 Swagger UI 的访问路径
});
这样访问 http://localhost:YOUR_PORT/swagger 就能打开页面。
四、接口接收和输出大小写配置
接口接收大小写配置
默认情况下,WebAPI 处理 JSON 时对属性名是大小写不敏感的。很多时候这更省事,但如果你要严格对齐前后端字段名,也可以关掉这个行为:
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
});
这样一来,客户端传来的属性名大小写必须和模型一致,否则就绑定不上。
接口输出大小写配置
使用 Newtonsoft.Json
老项目里经常还能看到 Newtonsoft.Json。要用它控制输出,先装 Microsoft.AspNetCore.Mvc.NewtonsoftJson,然后这样配:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
DefaultContractResolver 默认会把属性名转成驼峰风格。如果你想保持原属性名,通常要改成自定义 ContractResolver,或者选别的解析器。
使用 System.Text.Json
新一些的 .NET 版本默认用 System.Text.Json,配置方式更直接:
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
JsonNamingPolicy.CamelCase 会把输出转成驼峰命名。如果想保留原名,设置成 null 就行。
五、跨域配置
什么是跨域
前端页面和 API 不在同一个源上时,浏览器的同源策略会拦住请求。协议、域名、端口只要有一个不同,就算跨域。前后端分离项目里,这几乎是绕不开的配置。
配置跨域
先在 appsettings.json 里写允许的来源:
{
"AllowedOrigins": [
"http://localhost:3000",
"https://example.com"
]
}
然后在 Program.cs 里读取并注册 CORS 策略:
using Microsoft.AspNetCore.Cors.Infrastructure;
var allowedOrigins = builder.Configuration.GetSection("AllowedOrigins").Get<string[]>();
var corsBuilder = new CorsPolicyBuilder();
corsBuilder.AllowAnyHeader();
corsBuilder.AllowAnyMethod();
corsBuilder.WithOrigins(allowedOrigins);
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigins", corsBuilder.Build());
});
再启用它:
app.UseCors("AllowSpecificOrigins");
如果只是开发期临时联调,也可以放开所有来源:
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
然后用 app.UseCors("AllowAll");。
这个方案图省事,但不适合直接照搬到生产环境。
六、身份验证与授权配置
身份验证
.NET WebAPI 支持多种认证方式,JWT、OAuth 2.0、Windows 身份验证都能接。这里以 JWT 为例,先安装 Microsoft.AspNetCore.Authentication.JwtBearer。
配置 JWT:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var jwtSettings = builder.Configuration.GetSection("JwtSettings");
var key = Encoding.ASCII.GetBytes(jwtSettings["SecretKey"]);
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtSettings["Issuer"],
ValidAudience = jwtSettings["Audience"],
IssuerSigningKey = new SymmetricSecurityKey(key)
};
});
JwtSettings 里通常放 SecretKey、Issuer、Audience。这几个值必须和签发 token 的逻辑一致,不然验证会直接失败。
授权
先启用授权服务:
builder.Services.AddAuthorization();
然后可以在控制器上按角色限制访问:
[ApiController]
[Route("[controller]")]
[Authorize(Roles = "Admin")]
public class AdminController : ControllerBase
{
// 只有具有 Admin 角色的用户才能访问此控制器的方法
}
如果角色不够用,也可以上策略。比如定义一个年龄策略:
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("MustBeOver21", policy =>
policy.RequireAssertion(context =>
{
// 这里可以编写自定义的授权逻辑,例如检查用户年龄
var user = context.User;
// 假设用户声明中包含年龄信息
var ageClaim = user.FindFirst("Age");
if (ageClaim != null)
{
int age = int.Parse(ageClaim.Value);
return age >= 21;
}
return false;
}));
});
控制器里使用这个策略:
[ApiController]
[Route("[controller]")]
[Authorize(Policy = "MustBeOver21")]
public class AgeRestrictedController : ControllerBase
{
// 只有满足 MustBeOver21 策略的用户才能访问此控制器的方法
}
这种写法比单纯角色判断灵活,但也更依赖你自己把声明设计清楚。
七、日志配置
选择日志框架
.NET 自带 ILogger,但不少项目还是会用 Serilog。它和 ASP.NET Core 的集成比较顺手,输出格式、目标 sink 也好扩展。这里安装 Serilog.AspNetCore 和 Serilog.Sinks.Console 就够用了。
配置 Serilog
在 Program.cs 中配置:
using Serilog;
using Serilog.Events;
var logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);
这套配置的思路很朴素:把框架内部噪声压一压,保留必要信息,再输出到控制台。后面如果要接文件、ELK 或其他日志系统,继续往 LoggerConfiguration 上加 sink 就行。


