csharp的最小api
C# 在 dotnet6 之后添加了 minimalapi, 这允许开发者只需使用少量代码即可构建出一个可用的api程序
创建项目
可在命令行中执行以下代码创建项目
dotnet new webapi -minimal -n myapp
根据使用的sdk版本, 创建的项目模板可能会有所不同, 比 如我在用的sdk版本是8.0.111, 模板中program.cs的内容如下:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
var summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
app.MapGet("/weatherforecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi();
app.Run();
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
上面创建了一个返回列表的接口, 不过这些代码对于讲解来说还是有点多余, 可将 Program.cs
里面的内容都删掉, 从头开始写起
创建接口
var app = WebApplication.CreateBuilder(args).Build();
app.MapGet("/", () => "Hello, World!");
app.Run();
其实只需要三行即可在启动端口的根目录下直接创建一个api接口, 启动程序后访问对应站点即可看到浏览器上输出的 Hello, World!
在miniapi中可以非常简单地创建 restful api
app.MapPost
app.MapDelete
app.MapPut
app.MapGet
通过以上的四个方法可以完成增删改查四种基本的restful操作
参数匹配
由于miniapi接收的是委托类型的参数, 所以在定义参数时与之前常用的controller不同
app.MapGet(route, ([FromQuery] string data) => data);
[FromQuery]
可以说是最基础的一种参数接收形式, 用于接收请求路径?
之后的参数内容, 例如http://{host}:{port}/getdata?data=123
, 委托中获取到的data
就会是123
不过有一点需要注意, 之前在 controller 中可以指定自定义类型来接受多个参数, 比如[FromQuery]InputData data
这种的, 可以一次性接收多个参数, 但是在 miniapi 中不能直接这么使用, InputData
必须要有将 string
类型的参数字符串转换为 InputData
的 TryPrase
方法, 这样就显得尤为麻烦
因此如果想要通过 [FromQuery]
接收多个参数, 最好还是将参数拆开定义
app.MapGet(route, ([FromQuery] string data, [FromQuery] int num) => $@"{data}:{num}");
不过挺好的是 [FromBody]
的用法和以前没啥区别, 还是一样的非常方便
app.MapPost(route, ([FromBody] InputData data) => $@"{data.Data}:{data.Num}");
public class InputData
{
public string Data { get; set; }
public string Num { get; set; }
}
使用依赖注入
众所周知在现在的dotnet中, 依赖注入(DI)是必不可少的, 虽然 miniapi 很简单, 但还是可以正常用上的
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(new Config { Data = "233" });
...
app.MapPost(route, ([FromServices] Config config) => config.Data);
app.Run();
public class Config
{
public string Data { get; set; }
}
在委托的参数列表里可以使用 [FromServices]
从依赖注入容器 中获取注册过的实例
其实在 controller 中也可以使用这种方式注入实例, 只不过在正常情况下一般还是用构造函数注入, 但 miniapi 中只能用这种方式
这种注入方式讲究的就是用啥注入啥, 但是在业务复杂并且需要注入的实例数量比较多的时候, 委托的参数列表就会显得太过冗长, 如果接口数量也同时上升, 那么重复注入的情况就会出现很多次, 这种情况下可能就不如 controller 方便了
总结
miniapi 虽然能满足一些简单的需求, 但对于复杂的业务, 还是建议使用 controller 来实现