最小API项目的助手库集合。
为最小API项目提供路由助手的库,用于使用反射自动端点注册。
该库可在Nuget上找到。只需在包装管理器中搜索MinimalHelpers.Routing或在.NET CLI中运行以下命令:
dotnet add package MinimalHelpers.Routing创建一个类来保存您的路由处理程序注册并使IT实现IEndpointRouteHandlerBuilder接口:
public class PeopleEndpoints : MinimalHelpers . Routing . IEndpointRouteHandlerBuilder
{
public static void MapEndpoints ( IEndpointRouteBuilder endpoints )
{
endpoints . MapGet ( "/api/people" , GetList ) ;
endpoints . MapGet ( "/api/people/{id:guid}" , Get ) ;
endpoints . MapPost ( "/api/people" , Insert ) ;
endpoints . MapPut ( "/api/people/{id:guid}" , Update ) ;
endpoints . MapDelete ( "/api/people/{id:guid}" , Delete ) ;
}
// ...
}在program.cs内部的webapplication对象上调用MapEndpoints()扩展方法在Run()方法调用之前:
// using MinimalHelpers.Routing;
app . MapEndpoints ( ) ;
app . Run ( ) ;默认情况下, MapEndpoints()将扫描调用汇编以搜索实现IEndpointRouteHandlerBuilder接口的类。如果您的路线处理程序在另一个组件中定义,则有两种选择:
MapEndpoints()超载MapEndpointsFromAssemblyContaining<T>()扩展方法并指定要扫描的组件中包含的类型您还可以明确地确定要实际映射的类型(在实现IRouteEndpointHandlerBuilder界面的类型中),将谓词传递给MapEndpoints方法:
app . MapEndpoints ( type =>
{
if ( type . Name . StartsWith ( "Products" ) )
{
return false ;
}
return true ;
} ) ;请注意,这些方法依靠反射来扫描组件并找到实现
IEndpointRouteHandlerBuilder接口的类。这可能会产生性能影响,尤其是在大型项目中。如果您有绩效问题,请考虑使用明确的注册方法。此外,该解决方案与天然AOT不兼容。
在最小API项目中为自动端点注册提供源生成器的库。
该库可在Nuget上找到。只需在包装管理器GUI中搜索MinimalHelpers.Routing或在.NET CLI中运行以下命令:
dotnet add package MinimalHelpers.Routing.Analyzers创建一个类来保存您的路由处理程序注册并使IT实现IEndpointRouteHandlerBuilder接口:
public class PeopleEndpoints : IEndpointRouteHandlerBuilder
{
public static void MapEndpoints ( IEndpointRouteBuilder endpoints )
{
endpoints . MapGet ( "/api/people" , GetList ) ;
endpoints . MapGet ( "/api/people/{id:guid}" , Get ) ;
endpoints . MapPost ( "/api/people" , Insert ) ;
endpoints . MapPut ( "/api/people/{id:guid}" , Update ) ;
endpoints . MapDelete ( "/api/people/{id:guid}" , Delete ) ;
}
// ...
}请注意,您只需要使用MinimalHelpers.Routing.Analyzers套件。使用此源生成器,
IEndpointRouteHandlerBuilder接口是自动生成的。
在program.cs内部的webapplication对象上调用MapEndpoints()扩展方法在Run()方法调用之前:
app . MapEndpoints ( ) ;
app . Run ( ) ;注意
MapEndpoints方法是由源生成器生成的。
为最小API项目提供OpenAPI帮助者的图书馆。
该库可在Nuget上找到。只需在包装管理器GUI中搜索minimalhelpers.openapi或在.NET CLI中运行以下命令:
dotnet add package MinimalHelpers.OpenApiOpenAPI的扩展方法
该库提供了一些扩展方法,可以简化最小API项目中的OpenAPI配置。例如,可以使用其状态代码自定义响应的描述:
endpoints . MapPost ( "login" , LoginAsync )
. AllowAnonymous ( )
. WithValidation < LoginRequest > ( )
. Produces < LoginResponse > ( StatusCodes . Status200OK )
. Produces < LoginResponse > ( StatusCodes . Status206PartialContent )
. Produces ( StatusCodes . Status403Forbidden )
. ProducesValidationProblem ( )
. WithOpenApi ( operation =>
{
operation . Summary = "Performs the login of a user" ;
operation . Response ( StatusCodes . Status200OK ) . Description = "Login successful" ;
operation . Response ( StatusCodes . Status206PartialContent ) . Description = "The user is logged in, but the password has expired and must be changed" ;
operation . Response ( StatusCodes . Status400BadRequest ) . Description = "Incorrect username and/or password" ;
operation . Response ( StatusCodes . Status403Forbidden ) . Description = "The user was blocked due to too many failed logins" ;
return operation ;
} ) ;RouteHandlerBuilder的扩展方法
通常,我们有多个4xx返回值的端点,每个端点都会产生ProblemDetails响应:
endpoints . MapGet ( "/api/people/{id:guid}" , Get )
. ProducesProblem ( StatusCodes . Status400BadRequest )
. ProducesProblem ( StatusCodes . Status401Unauthorized )
. ProducesProblem ( StatusCodes . Status403Forbidden )
. ProducesProblem ( StatusCodes . Status404NotFound ) ;为了避免多次呼叫ProducesProblem ,我们可以使用库提供的ProducesDefaultProblem扩展方法:
endpoints . MapGet ( "/api/people/{id:guid}" , Get )
. ProducesDefaultProblem ( StatusCodes . Status400BadRequest , StatusCodes . Status401Unauthorized ,
StatusCodes . Status403Forbidden , StatusCodes . Status404NotFound ) ; 一个为最小API项目提供端点过滤器的库,该项目使用Mignivalation库使用数据注释执行验证。
该库可在Nuget上找到。只需搜索最小值。
dotnet add package MinimalHelpers.Validation装饰具有定义验证规则的属性的课程:
using System . ComponentModel . DataAnnotations ;
public class Person
{
[ Required ]
[ MaxLength ( 20 ) ]
public string ? FirstName { get ; set ; }
[ Required ]
[ MaxLength ( 20 ) ]
public string ? LastName { get ; set ; }
[ MaxLength ( 50 ) ]
public string ? City { get ; set ; }
}添加WithValidation<T>()扩展方法以启用验证过滤器:
using MinimalHelpers . Validation ;
app . MapPost ( "/api/people" , ( Person person ) =>
{
// ...
} )
. WithValidation < Person > ( ) ;如果验证失败,则响应将是一个400 Bad Request ,其中包含验证错误的ValidationProblemDetails问题对象,例如:
{
"type" : " https://tools.ietf.org/html/rfc9110#section-15.5.1 " ,
"title" : " One or more validation errors occurred " ,
"status" : 400 ,
"instance" : " /api/people " ,
"traceId" : " 00-009c0162ba678cae2ee391815dbbb59d-0a3a5b0c16d053e6-00 " ,
"errors" : {
"FirstName" : [
" The field FirstName must be a string or array type with a maximum length of '20'. "
],
"LastName" : [
" The LastName field is required. "
]
}
}如果要自定义验证,则可以使用ConfigureValidation扩展方法:
using MinimalHelpers . Validation ;
builder . Services . ConfigureValidation ( options =>
{
// If you want to get errors as a list instead of a dictionary.
options . ErrorResponseFormat = ErrorResponseFormat . List ;
// The default is "One or more validation errors occurred"
options . ValidationErrorTitleMessageFactory =
( context , errors ) => $ "There was { errors . Values . Sum ( v => v . Length ) } error(s)" ;
} ) ;例如,如果要使用RESX文件本地化响应的title属性,则可以使用ValidationErrorTitleMessageFactory 。
为最小API项目提供端点过滤器的库,以使用FulentValidation执行验证。
该库可在Nuget上找到。只需在包装管理器GUI中搜索MinimalHelpers.FluentValidation或在.NET CLI中运行以下命令:
dotnet add package MinimalHelpers.FluentValidation创建一个扩展AbstractValidator并定义验证规则的类:
using FluentValidation ;
public record class Product ( string Name , string Description , double UnitPrice ) ;
public class ProductValidator : AbstractValidator < Product >
{
public ProductValidator ( )
{
RuleFor ( p => p . Name ) . NotEmpty ( ) . MaximumLength ( 50 ) . EmailAddress ( ) ;
RuleFor ( p => p . Description ) . MaximumLength ( 500 ) ;
RuleFor ( p => p . UnitPrice ) . GreaterThan ( 0 ) ;
}
}在服务集合中注册验证器:
using FluentValidation ;
// Assuming the validators are in the same assembly as the Program class
builder . Services . AddValidatorsFromAssemblyContaining < Program > ( ) ;添加WithValidation<T>()扩展方法以启用验证过滤器:
using MinimalHelpers . FluentValidation ;
app . MapPost ( "/api/products" , ( Product product ) =>
{
// ...
} )
. WithValidation < Product > ( ) ;如果验证失败,则响应将是一个400 Bad Request ,其中包含验证错误的ValidationProblemDetails问题对象,例如:
{
"type" : " https://tools.ietf.org/html/rfc9110#section-15.5.1 " ,
"title" : " One or more validation errors occurred " ,
"status" : 400 ,
"instance" : " /api/products " ,
"traceId" : " 00-f4ced0ae470424dd04cbcebe5f232dc5-bbdcc59f310ebfb8-00 " ,
"errors" : {
"Name" : [
" 'Name' cannot be empty. "
],
"UnitPrice" : [
" 'Unit Price' must be grater than '0'. "
]
}
}如果要自定义验证,则可以使用ConfigureValidation扩展方法:
using MinimalHelpers . Validation ;
builder . Services . ConfigureValidation ( options =>
{
// If you want to get errors as a list instead of a dictionary.
options . ErrorResponseFormat = ErrorResponseFormat . List ;
// The default is "One or more validation errors occurred"
options . ValidationErrorTitleMessageFactory =
( context , errors ) => $ "There was { errors . Values . Sum ( v => v . Length ) } error(s)" ;
} ) ;例如,如果要使用RESX文件本地化响应的title属性,则可以使用ValidationErrorTitleMessageFactory 。
贡献
该项目不断发展。欢迎捐款。随时提出问题并提取回购请求,我们将尽可能地解决。