快速展示原型之Minimal API开发
Minimal API官网地址: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/minimal-apis/security?view=aspnetcore-7.0
Minimal API 背景介绍
Minimal APIs 是指在 ASP.NET Core 中引入的一种轻量级的 API 开发模式。它的产生背景是为了简化 API 的创建和开发流程,减少样板代码,并提供更灵活的方式来定义和配置 API 端点。
在传统的 ASP.NET Core 中,创建 API 需要定义控制器类和路由配置,并编写一系列的动作方法和路由规则。这样的开发模式在一些简单的场景下可能会显得过于繁琐和冗余。
Minimal APIs 的定义和配置更加简洁和直观,可以在一个单独的文件中定义整个 API,而无需创建控制器类和路由配置。它通过使用 Lambda 表达式和链式调用的方式,将路由、HTTP 方法和请求处理逻辑直接绑定在一起,减少了样板代码的数量。
Minimal APIs 的应用场景包括但不限于:
快速原型开发:在快速原型开发阶段,Minimal APIs 可以帮助开发者快速创建和测试 API 端点,减少开发时间和代码量。
小型项目和微服务:对于小型项目或者微服务,Minimal APIs 提供了一种简洁的方式来定义和配置 API,减少了项目结构的复杂性。
单个端点的简单 API:对于只有一个或者少量端点的简单 API,Minimal APIs 可以提供更加直观和简洁的开发方式。
快速验证和测试:Minimal APIs 可以用于快速验证和测试一些想法或者概念,以及进行一些临时性的 API 开发。
需要注意的是,Minimal APIs 并不适用于所有场景。对于复杂的 API 或者需要更多配置和扩展的情况,传统的控制器和路由配置方式可能更加合适。
功能代码示例
在 Minimal API 中,ASP.NET Core 的一些功能可以通过简化的语法和约定来体现。下面是一些常见的功能在 Minimal API 中的体现方式:
路由和端点定义:
使用
app.MapGet()
、app.MapPost()
等方法来定义路由和处理不同的 HTTP 请求方法。可以直接在路由路径中使用参数,如
{name}
,并将其作为方法参数进行处理。var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello, Minimal API!");
app.MapPost("/", () => "Received a POST request!");
app.MapPut("/", () => "Received a PUT request!");
app.MapDelete("/", () => "Received a DELETE request!");
app.MapMethods("/hello", new[] { "GET", "POST", "PUT", "DELETE" }, () =>
{
var method = Context.Request.Method;
return $"Received a {method} request to /hello";
});
app.Run();
app.MapGet() 方法用于处理 HTTP GET 请求,当请求的路径为根路径 / 时,返回 "Hello, Minimal API!"。
app.MapPost() 方法用于处理 HTTP POST 请求,当请求的路径为根路径 / 时,返回 "Received a POST request!"。
app.MapPut() 方法用于处理 HTTP PUT 请求,当请求的路径为根路径 / 时,返回 "Received a PUT request!"。
app.MapDelete() 方法用于处理 HTTP DELETE 请求,当请求的路径为根路径 / 时,返回 "Received a DELETE request!"。
app.MapMethods() 方法用于处理指定的 HTTP 请求方法,当请求的路径为 /hello 且方法为 GET、POST、PUT 或 DELETE 时,返回相应的信息。
请求和响应处理:
使用方法参数来获取请求中的数据,如路由参数、查询字符串参数和请求体参数。
使用
Results
类来生成响应,如Results.Ok()
、Results.BadRequest()
等。var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ICustomService, CustomService>();
var app = builder.Build();
app.MapGet("/hello/{name}", (string name) =>
{
return $"Hello, {name}!";
});
app.MapPost("/api/submit", async (HttpRequest request) =>
{
// 从请求体中获取数据
var data = await request.ReadFromJsonAsync<CustomData>();
// 处理数据并生成响应
var result = ProcessData(data);
return Results.Ok(result);
});
app.Run();
public class CustomData
{
public string Name { get; set; }
public int Age { get; set; }
}
public class CustomService : ICustomService
{
// 服务实现代码
}
public interface ICustomService
{
// 服务接口定义
}
在上面的示例中,我们定义了两个端点:
- `GET /hello/{name}`:使用路由参数 `name` 来获取请求中的数据,并返回相应的问候消息。
- `POST /api/submit`:使用 `HttpRequest` 参数来获取请求体中的数据,并进行处理,然后生成响应。
在 `POST /api/submit` 端点中,我们使用 `ReadFromJsonAsync<T>()` 方法从请求体中异步读取 JSON 数据,并将其转换为 `CustomData` 对象。然后,我们可以对数据进行处理,并生成相应的结果。最后,我们使用 `Results.Ok()` 方法将结果作为 JSON 响应返回。
希望这个更全面的代码示例能够帮助你理解在 Minimal API 中如何处理请求和响应。如果你有任何其他问题,请随时提问。
中间件和管道:
使用
app.UseMiddleware<CustomMiddleware>()
来添加自定义的中间件。使用
app.MapGet().UseMiddleware<AuthenticationMiddleware>()
在特定的端点上使用中间件。```csharp
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading.Tasks;
var builder = WebApplication.CreateBuilder(args);
// 注册自定义中间件
builder.Services.AddTransient<CustomMiddleware>();
var app = builder.Build();
// 使用自定义中间件
app.UseMiddleware<CustomMiddleware>();
// 定义路由和处理请求的方法
app.MapGet("/", () => "Hello, Minimal API!");
app.Run();
// 自定义中间件
public class CustomMiddleware
{
private readonly RequestDelegate _next;
public CustomMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
// 在请求处理之前执行的逻辑
Console.WriteLine("CustomMiddleware: Before request");
// 调用下一个中间件或处理程序
await _next(context);
// 在请求处理之后执行的逻辑
Console.WriteLine("CustomMiddleware: After request");
}
}
```
在上面的示例中,我们首先通过 `builder.Services.AddTransient<CustomMiddleware>()` 将自定义中间件注册到容器中。然后,在 `app.UseMiddleware<CustomMiddleware>()` 中使用自定义中间件。这样,每次请求进入应用程序时,都会先经过自定义中间件的处理。
自定义中间件的实现类 `CustomMiddleware` 必须具有 `InvokeAsync` 方法,该方法接收一个 `HttpContext` 对象和一个 `RequestDelegate` 对象作为参数。在 `InvokeAsync` 方法中,我们可以在请求处理之前和之后执行一些逻辑。
在上面的示例中,我们在自定义中间件的 `InvokeAsync` 方法中打印了一些日志信息,以展示自定义中间件的使用方式。
模型绑定和验证:
可以通过方法参数直接进行模型绑定,无需显式地使用
[FromBody]
或[FromQuery]
等特性。使用
ModelState
进行模型验证,并返回相应的结果。var builder = WebApplication.CreateBuilder(args);
// 定义模型类
public class Person
{
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
[Range(18, 100, ErrorMessage = "Age must be between 18 and 100")]
public int Age { get; set; }
public string Email { get; set; }
}
// 注册模型验证器
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var errors = new List<string>();
foreach (var modelState in context.ModelState.Values)
{
foreach (var error in modelState.Errors)
{
errors.Add(error.ErrorMessage);
}
}
return new BadRequestObjectResult(errors);
};
});
var app = builder.Build();
app.MapPost("/person", async (Person person) =>
{
if (!ModelState.IsValid)
{
return Results.BadRequest(ModelState);
}
// 处理有效的 person 对象
return Results.Ok(person);
});
app.Run();
```
在上面的示例中,我们定义了一个 `Person` 类作为模型,并在属性上使用了一些数据注解来定义验证规则。在 `app.MapPost` 方法中,我们直接将 `Person` 类作为参数,Minimal API 会自动进行模型绑定和验证。如果模型验证失败,我们通过自定义的 `InvalidModelStateResponseFactory` 来返回验证错误信息。
当我们发送 POST 请求到 `/person` 路径时,Minimal API 会自动将请求体中的 JSON 数据绑定到 `Person` 对象,并进行模型验证。如果模型验证失败,将返回包含验证错误信息的 BadRequest 响应;如果模型验证成功,将返回包含有效的 `Person` 对象的 Ok 响应。
这样,我们就可以通过方法参数来实现模型绑定和验证,而无需显式地使用 `[FromBody]` 或 `[FromQuery]` 等特性。
异常处理:
使用
app.RunExceptionHandler()
来捕获并处理应用程序中的异常。var builder = WebApplication.CreateBuilder(args);
// 注册自定义的异常处理中间件
builder.Services.AddSingleton<ExceptionHandlerMiddleware>();
var app = builder.Build();
// 使用自定义的异常处理中间件
app.UseMiddleware<ExceptionHandlerMiddleware>();
app.MapGet("/", () => throw new Exception("Something went wrong!"));
app.Run();
// 自定义异常处理中间件
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
public ExceptionHandlerMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
// 执行下一个中间件
await _next(context);
}
catch (Exception ex)
{
// 处理异常并生成响应
context.Response.StatusCode = 500;
await context.Response.WriteAsync($"An error occurred: {ex.Message}");
}
}
}
```
在上面的代码示例中,我们定义了一个自定义的异常处理中间件 `ExceptionHandlerMiddleware`,它接受一个 `RequestDelegate` 参数作为下一个中间件。在 `InvokeAsync` 方法中,我们使用 `try-catch` 块来捕获应用程序中的异常。如果发生异常,我们设置响应的状态码为 500,并将异常信息写入响应。
在应用程序的主函数中,我们注册了自定义的异常处理中间件,并在根路径上抛出一个异常,以模拟应用程序中的异常情况。当访问根路径时,异常处理中间件将捕获并处理异常,并返回相应的错误响应。
通过这种方式,你可以自定义异常处理中间件来捕获和处理应用程序中的异常,并生成适当的响应。
依赖注入:
使用
app.Services.AddSingleton<TService, TImplementation>()
或app.Services.AddScoped<TService, TImplementation>()
将服务注册到容器中。可以直接在方法参数中使用依赖注入的服务。
当使用 Minimal API 进行开发时,可以使用依赖注入来注册和使用服务。下面是一个更全面的代码示例,演示了如何在 Minimal API 中使用依赖注入:
```csharp
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
var builder = WebApplication.CreateBuilder();
// 注册服务
builder.Services.AddSingleton<IMyService, MyService>();
var app = builder.Build();
// 使用服务
app.MapGet("/", (IMyService myService) =>
{
var result = myService.DoSomething();
return result;
});
app.Run();
// 服务接口
public interface IMyService
{
string DoSomething();
}
// 服务实现
public class MyService : IMyService
{
public string DoSomething()
{
return "Hello from MyService!";
}
}
```
在上面的示例中,我们首先使用 `builder.Services.AddSingleton<IMyService, MyService>()` 将 `MyService` 注册为 `IMyService` 接口的实现,这样就可以在应用程序中使用 `IMyService` 进行依赖注入。
然后,在 `app.MapGet()` 方法中,我们将 `IMyService` 作为参数传入,Minimal API 将自动从容器中解析并提供一个 `IMyService` 实例。在处理请求时,我们可以直接使用 `myService` 来调用 `IMyService` 中的方法。
这样,我们就可以在 Minimal API 中方便地使用依赖注入来管理和使用服务。
身份验证和授权:
使用
app.UseAuthentication()
和app.UseAuthorization()
启用身份验证和授权中间件。使用
RequireAuthorization()
方法来标记需要进行身份验证和授权的端点。
1. 首先,确保已经在项目中添加了所需的身份验证和授权相关的 NuGet 包,如 `Microsoft.AspNetCore.Authentication` 和 `Microsoft.AspNetCore.Authorization`。
2. 在 `Program.cs` 文件中,使用 `builder.Services.AddAuthentication()` 和 `builder.Services.AddAuthorization()` 方法来注册身份验证和授权服务:
```csharp
var builder = WebApplication.CreateBuilder(args);
// 注册身份验证服务
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
// 配置 JWT Bearer 认证选项
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
});
// 注册授权服务
builder.Services.AddAuthorization();
var app = builder.Build();
```
3. 在 `Configure` 方法中,使用 `app.UseAuthentication()` 和 `app.UseAuthorization()` 方法来启用身份验证和授权中间件:
```csharp
app.UseAuthentication();
app.UseAuthorization();
```
4. 在需要进行身份验证和授权的端点上,使用 `RequireAuthorization()` 方法来标记需要进行身份验证和授权的端点:
```csharp
app.MapGet("/hello", () => "Hello, Minimal APIs!")
.RequireAuthorization();
```
5. 在需要进行授权的端点上,可以使用 `[Authorize]` 特性来标记需要进行授权的端点:
```csharp
app.MapGet("/secret", () => "This is a secret page.")
.RequireAuthorization()
.WithMetadata(new AuthorizeAttribute());
```
6. 在需要获取当前用户信息的地方,可以通过方法参数的方式获取 `HttpContext`,并使用 `User` 属性来获取当前用户的身份信息:
```csharp
app.MapGet("/profile", (HttpContext context) =>
{
var user = context.User;
// 获取用户信息并进行处理
// ...
return "User Profile";
})
.RequireAuthorization();
```
通过以上代码示例,你可以在 Minimal API 中实现身份验证和授权的功能。请注意,这只是一个基本示例,实际应用中可能需要根据具体的需求进行配置和扩展。
Swagger:
使用
app.UseSwagger()
和app.UseSwaggerUI()
启用 Swagger 支持和 Swagger UI。
var builder = WebApplication.CreateBuilder(args);
// 添加 Swagger
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
});
var app = builder.Build();
// 启用 Swagger UI
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API v1");
});
app.MapGet("/", () => "Hello, Minimal APIs!");
app.Run();
```
在上述示例中,我们首先在 `CreateHostBuilder` 方法中使用 `AddSwaggerGen` 方法配置 Swagger,指定了 API 的标题和版本信息。
然后,在应用程序构建完成后,我们使用 `UseSwagger` 方法启用 Swagger 支持,并使用 `UseSwaggerUI` 方法配置 Swagger UI 的终结点。
最后,我们定义了一个简单的根路径处理程序,以便在浏览器中查看 Swagger UI。
运行应用程序后,你可以通过访问 `http://localhost:5000/swagger` 来查看 Swagger UI,并浏览和测试你的 API。
Filter:
使用
app.AddFilter<CustomFilter>()
将过滤器添加到应用程序。当使用 Minimal API 开发时,可以通过自定义 Filter 来实现全局的过滤器功能。下面是一个更全面的代码示例:
1. 创建自定义的过滤器类 `CustomFilter`:
```csharp
public class CustomFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// 在执行操作之前的逻辑
Console.WriteLine("Before action execution");
// 执行下一个过滤器或操作
var resultContext = await next();
// 在执行操作之后的逻辑
Console.WriteLine("After action execution");
}
}
```
2. 在应用程序中注册过滤器:
```csharp
var builder = WebApplication.CreateBuilder(args);
// 注册过滤器
builder.Services.AddFilter<CustomFilter>();
var app = builder.Build();
app.MapGet("/", () => "Hello, Minimal APIs!")
.RequireAuthorization()
.WithFilter<CustomFilter>(); // 添加过滤器到端点
app.Run();
```
在上面的示例中,我们创建了一个名为 `CustomFilter` 的自定义过滤器类,并实现了 `IAsyncActionFilter` 接口。在 `OnActionExecutionAsync` 方法中,我们可以编写在执行操作之前和之后需要执行的逻辑。
在应用程序中,我们使用 `builder.Services.AddFilter<CustomFilter>()` 将自定义过滤器添加到服务容器中。然后,我们在 `app.MapGet()` 方法链中使用 `.WithFilter<CustomFilter>()` 将过滤器添加到特定的端点。
当请求到达该端点时,过滤器的逻辑将在执行操作之前和之后被调用。
通过这些简化的语法和约定,Minimal API 提供了一种更简洁、更直观的方式来开发和配置 ASP.NET Core 应用程序,使得代码更加清晰和易于维护。
快速展示原型之Minimal API开发的更多相关文章
- 【.NET 6】使用.NET 6开发minimal api以及依赖注入的实现、VS2022热重载和自动反编译功能的演示
前言: .net 6 LTS版本发布已经有若干天了.此处做一个关于使用.net 6 开发精简版webapi(minimal api)的入门教程,以及VS2022 上面的两个强大的新技能(热重载.代码自 ...
- 【.NET6】gRPC服务端和客户端开发案例,以及minimal API服务、gRPC服务和传统webapi服务的访问效率大对决
前言:随着.Net6的发布,Minimal API成了当下受人追捧的角儿.而这之前,程序之间通信效率的王者也许可以算得上是gRPC了.那么以下咱们先通过开发一个gRPC服务的教程,然后顺势而为,再接着 ...
- C#设计模式总结 C#设计模式(22)——访问者模式(Vistor Pattern) C#设计模式总结 .NET Core launch.json 简介 利用Bootstrap Paginator插件和knockout.js完成分页功能 图片在线裁剪和图片上传总结 循序渐进学.Net Core Web Api开发系列【2】:利用Swagger调试WebApi
C#设计模式总结 一. 设计原则 使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性.并且,在进行设计的时候,也需要遵循以下几个原则:单一职责原则.开放封闭原则.里氏代替 ...
- 《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目
CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + ...
- 高性能PHP框架thinkphp5.0.0 Beta发布-为API开发而设计
ThinkPHP V5.——为API开发而设计的高性能框架 ThinkPHP5..0版本是一个颠覆和重构版本,采用全新的架构思想,引入了很多的PHP新特性,优化了核心,减少了依赖,实现了真正的惰性加载 ...
- [转]常用的快速Web原型图设计工具
转自大神: http://www.cnblogs.com/lhb25/archive/2009/04/25/1443254.html 做产品原型是非常重要的一个环节,做产品原型就会用使用各式各样的工具 ...
- 报表引擎API开发入门— EJB程序数据源
我们前面讲了几个数据源,今天我们来讲一下EJB数据源,这篇讲完我们数据源这部分就讲完了.数据连接不需要直接访问数据库,而是使用EJB做为数据源.FR通过定义程序数据集使用EJB的相关类获取到EJB数据 ...
- 通过beego快速创建一个Restful风格API项目及API文档自动化
通过beego快速创建一个Restful风格API项目及API文档自动化 本文演示如何快速(一分钟内,不写一行代码)的根据数据库及表创建一个Restful风格的API项目,及提供便于在线测试API的界 ...
- 浅谈php对api开发的作用
最近正在做一个手机APP的服务端API开发,虽然是基于Ruby on Rails的,做的也不太专业,不过大致相通,希望能够给你一些启发. 首先,如果是比较简单的手机APP,例如新闻客户端这样的不会涉及 ...
- 深入浅出百度地图API开发系列(1):前言
百度地图API目前在地图API领域越来越受到众多开发者的关注,许多应用都使用到了百度地图API服务,包括博主me,我自己使用做的是Javascript API,根据经验,我想整理出一份系列教程,如果能 ...
随机推荐
- Avalonia开发Markdown编辑器
Avalonia开发Markdown编辑器 今天熟悉Avalonia UI,做一个Markdown的文本编辑器. 代码我上传了Github,地址: https://github.com/raokun/ ...
- XTTS系列之三:中转空间的选择和优化
通常选择XTTS做迁移的数据库都不会太小的,至少都是几T.几十T这样的规模,这种级别的数据量原有空间不够用,所以在迁移过程临时用作存放迁移数据库备份文件的空间也是需要提前考虑规划的问题. 最近就有客户 ...
- pod setup 慢 的问题
由于更换了硬盘,重装了系统,需要重新配置环境,发现现在安装cocapods比之前坑更深了, 装环境时遇到pod setup才几kb的下载速度(即使用梯子也是巨慢),实在是没法用在网上尝试了各种方法,但 ...
- Web网页音视频通话之Webrtc相关操作(一)
目录 打开摄像头/关闭摄像头 静音/解除静音 打开视频/关闭视频 截图且下载 打开摄像头/关闭摄像头 效果图 HTML <!DOCTYPE html> <html lang=&quo ...
- PlayWright(十七)- 参数化
今天来讲下参数化,具体是什么意思呢,举个例子 比如我们要测试登录功能,第一步会填写账号,第二步会填写密码,这是一条完整的操作,但是其中会有很多条用例比如账号错误.密码错误.账号为空.密码为空的各种 ...
- 论文解读(DWL)《Dynamic Weighted Learning for Unsupervised Domain Adaptation》
[ Wechat:Y466551 | 付费咨询,非诚勿扰 ] 论文信息 论文标题:Dynamic Weighted Learning for Unsupervised Domain Adaptatio ...
- [golang]使用logrus自定义日志模块
简介 logrus是一个第三方日志库,性能虽不如zap和zerolog,但方便易用灵活.logrus完全兼容标准的log库,还支持文本.JSON两种日志输出格式. 特点 相较于标准库,logrus有更 ...
- Typora 主题,设置代码块Mac风格三个小圆点
目录 打造Typora主题 1 typoa样式修改步骤 1.1 第一步打开偏好设置 1.2 第二步打开主题文件夹 2 标题添加颜色 3 表格优化 4 代码块Mac风格三个圆点 5 主题总代码如下: 打 ...
- 【pandas小技巧】--花哨的DataFrame
最近github上发现了一个库(plottable),可以用简单的方式就设置出花哨的 DataFrame 样式. github上的地址:https://github.com/znstrider/plo ...
- Java - ReentrantLock锁分析
Java - JUC核心类AbstractQueuedSynchronizer(AQS)底层实现 一. AQS内部结构介绍 JUC是Java中一个包 java.util.concurrent . ...