Uma coleção de bibliotecas de ajuda para projetos mínimos de API.
Uma biblioteca que fornece ajudantes de roteamento para projetos mínimos de API para registro automático de pontos de extremidade usando a reflexão.
A biblioteca está disponível no NUGET. Basta procurar por minimalhelpers .
dotnet add package MinimalHelpers.Routing Crie uma classe para manter o registro de seus manipuladores de rotas e torná -lo implementando a interface 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 ) ;
}
// ...
} Ligue para o método de extensão MapEndpoints() no objeto WebApplication Inside Inside Program.cs Antes do método Run() Invocação:
// using MinimalHelpers.Routing;
app . MapEndpoints ( ) ;
app . Run ( ) ; Por padrão, MapEndpoints() digitalizará o Assembly de chamada para pesquisar classes que implementam a interface IEndpointRouteHandlerBuilder . Se seus manipuladores de rota forem definidos em outra montagem, você terá duas alternativas:
MapEndpoints() que leva a montagem para digitalizar como argumentoMapEndpointsFromAssemblyContaining<T>() Você também pode decidir explicitamente quais tipos (entre os que implementam a interface IRouteEndpointHandlerBuilder ) que você realmente deseja mapear, passando um predicado para o método MapEndpoints :
app . MapEndpoints ( type =>
{
if ( type . Name . StartsWith ( "Products" ) )
{
return false ;
}
return true ;
} ) ;NOTA Esses métodos dependem da reflexão para digitalizar a montagem e encontrar as classes que implementam a interface
IEndpointRouteHandlerBuilder. Isso pode ter um impacto de desempenho, especialmente em grandes projetos. Se você tiver problemas de desempenho, considere usar o método de registro explícito. Além disso, esta solução é incompatibil com AOT nativo.
Uma biblioteca que fornece um gerador de origem para o registro automático de terminais em projetos mínimos de API.
A biblioteca está disponível no NUGET. Basta procurar por minimalhelpers .
dotnet add package MinimalHelpers.Routing.Analyzers Crie uma classe para manter o registro de seus manipuladores de rotas e torná -lo implementando a interface 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 ) ;
}
// ...
}NOTA Você só precisa usar o pacote MinimLelHelpers.Routing.Analyzers . Com este gerador de origem, a interface
IEndpointRouteHandlerBuilderé gerada automaticamente.
Ligue para o método de extensão MapEndpoints() no objeto WebApplication Inside Inside Program.cs Antes do método Run() Invocação:
app . MapEndpoints ( ) ;
app . Run ( ) ;Nota O método
MapEndpointsé gerado pelo gerador de origem.
Uma biblioteca que fornece ajudantes do OpenAPI para projetos mínimos de API.
A biblioteca está disponível no NUGET. Basta procurar por minimalhelpers.openapi na GUI do gerenciador de pacotes ou executar o seguinte comando na .NET CLI :
dotnet add package MinimalHelpers.OpenApiMétodos de extensão para openapi
Esta biblioteca fornece alguns métodos de extensão que simplificam a configuração do OpenAPI em projetos mínimos de API. Por exemplo, é possível personalizar a descrição de uma resposta usando seu código de status:
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 ;
} ) ;Métodos de extensão para RouteHandlerBuilder
Freqüentemente, temos pontos de extremidade com vários valores de retorno 4xx, cada um dos quais produz uma resposta ProblemDetails :
endpoints . MapGet ( "/api/people/{id:guid}" , Get )
. ProducesProblem ( StatusCodes . Status400BadRequest )
. ProducesProblem ( StatusCodes . Status401Unauthorized )
. ProducesProblem ( StatusCodes . Status403Forbidden )
. ProducesProblem ( StatusCodes . Status404NotFound ) ; Para evitar várias chamadas para ProducesProblem , podemos usar o método de extensão de produtores de produção ProducesDefaultProblem fornecido pela biblioteca:
endpoints . MapGet ( "/api/people/{id:guid}" , Get )
. ProducesDefaultProblem ( StatusCodes . Status400BadRequest , StatusCodes . Status401Unauthorized ,
StatusCodes . Status403Forbidden , StatusCodes . Status404NotFound ) ; Uma biblioteca que fornece um filtro de endpoint para projetos mínimos de API para realizar a validação com anotações de dados, usando a biblioteca de minivalidação.
A biblioteca está disponível no NUGET. Basta procurar por minimalhelpers .
dotnet add package MinimalHelpers.ValidationDecora uma aula com atributos para definir as regras de validação:
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 ; }
} Adicione o método de extensão WithValidation<T>() para ativar o filtro de validação:
using MinimalHelpers . Validation ;
app . MapPost ( "/api/people" , ( Person person ) =>
{
// ...
} )
. WithValidation < Person > ( ) ; Se a validação falhar, a resposta será uma 400 Bad Request com um objeto ValidationProblemDetails contendo os erros de validação, por exemplo:
{
"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. "
]
}
} Se você deseja personalizar a validação, pode usar o método de extensão 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)" ;
} ) ; Você pode usar o ValidationErrorTitleMessageFactory , por exemplo, se desejar localizar a propriedade title da resposta usando um arquivo RESX.
Uma biblioteca que fornece um filtro de terminal para projetos mínimos de API para realizar validação usando o fluentValidação.
A biblioteca está disponível no NUGET. Basta procurar por minimalhelpers.fluentValidation na GUI do gerenciador de pacotes ou executar o seguinte comando na .NET CLI :
dotnet add package MinimalHelpers.FluentValidationCrie uma classe que estende a abstrataValidator e defina as regras de validação:
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 ) ;
}
}Registre os validadores na coleção de serviços:
using FluentValidation ;
// Assuming the validators are in the same assembly as the Program class
builder . Services . AddValidatorsFromAssemblyContaining < Program > ( ) ; Adicione o método de extensão WithValidation<T>() para ativar o filtro de validação:
using MinimalHelpers . FluentValidation ;
app . MapPost ( "/api/products" , ( Product product ) =>
{
// ...
} )
. WithValidation < Product > ( ) ; Se a validação falhar, a resposta será uma 400 Bad Request com um objeto ValidationProblemDetails contendo os erros de validação, por exemplo:
{
"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'. "
]
}
} Se você deseja personalizar a validação, pode usar o método de extensão 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)" ;
} ) ; Você pode usar o ValidationErrorTitleMessageFactory , por exemplo, se desejar localizar a propriedade title da resposta usando um arquivo RESX.
Contribuir
O projeto está em constante evolução. Contribuições são bem -vindas. Sinta -se à vontade para arquivar problemas e puxar solicitações no repositório e abordá -las como pudermos.