Una colección de bibliotecas de ayuda para proyectos de API mínimos.
Una biblioteca que proporciona ayudantes de enrutamiento para proyectos API mínimos para el registro automático de puntos finales utilizando la reflexión.
La biblioteca está disponible en Nuget. Simplemente busque minimalHelpers .
dotnet add package MinimalHelpers.Routing Cree una clase para mantener el registro de los manipuladores de ruta y hacer que implementando la interfaz 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 ) ;
}
// ...
} Llame al método de extensión MapEndpoints() en el objeto de aplicación web dentro de Program.cs antes de la invocación del método Run() :
// using MinimalHelpers.Routing;
app . MapEndpoints ( ) ;
app . Run ( ) ; De forma predeterminada, MapEndpoints() escaneará el ensamblaje de llamadas para buscar clases que implementen la interfaz IEndpointRouteHandlerBuilder . Si los manejadores de su ruta se definen en otra asamblea, tiene dos alternativas:
MapEndpoints() que toma el ensamblaje para escanear como argumentoMapEndpointsFromAssemblyContaining<T>() y especifique un tipo que esté contenido en el ensamblaje que desea escanear También puede decidir explícitamente qué tipos (entre los que implementan la interfaz IRouteEndpointHandlerBuilder ) que realmente desea asignar, pasando un predicado al método MapEndpoints :
app . MapEndpoints ( type =>
{
if ( type . Name . StartsWith ( "Products" ) )
{
return false ;
}
return true ;
} ) ;Tenga en cuenta que estos métodos se basan en la reflexión para escanear el ensamblaje y encontrar las clases que implementan la interfaz
IEndpointRouteHandlerBuilder. Esto puede tener un impacto en el rendimiento, especialmente en grandes proyectos. Si tiene problemas de rendimiento, considere usar el método de registro explícito. Además, esta solución es incompatibil con AOT nativo.
Una biblioteca que proporciona un generador de origen para el registro de puntos finales automáticos en proyectos de API mínimos.
La biblioteca está disponible en Nuget. Simplemente busque minimalHelpers .
dotnet add package MinimalHelpers.Routing.Analyzers Cree una clase para mantener el registro de los manipuladores de ruta y hacer que implementando la interfaz 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 ) ;
}
// ...
}Tenga en cuenta que solo necesita usar el paquete MinimalPers.Routing.Analyzers . Con este generador de origen, la interfaz
IEndpointRouteHandlerBuilderse genera automáticamente.
Llame al método de extensión MapEndpoints() en el objeto de aplicación web dentro de Program.cs antes de la invocación del método Run() :
app . MapEndpoints ( ) ;
app . Run ( ) ;Tenga en cuenta que el método
MapEndpointses generado por el generador de origen.
Una biblioteca que proporciona ayudantes de OpenApi para proyectos API mínimos.
La biblioteca está disponible en Nuget. Simplemente busque minimalhelpers.openapi en la GUI del administrador de paquetes o ejecute el siguiente comando en el CLI .NET :
dotnet add package MinimalHelpers.OpenApiMétodos de extensión para Openapi
Esta biblioteca proporciona algunos métodos de extensiones que simplifican la configuración de OpenAPI en proyectos API mínimos. Por ejemplo, es posible personalizar la descripción de una respuesta utilizando su código de estado:
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 extensión para RouteHandlerBuilder
A menudo tenemos puntos finales con múltiples valores de retorno de 4xx, cada uno de los cuales produce una respuesta ProblemDetails :
endpoints . MapGet ( "/api/people/{id:guid}" , Get )
. ProducesProblem ( StatusCodes . Status400BadRequest )
. ProducesProblem ( StatusCodes . Status401Unauthorized )
. ProducesProblem ( StatusCodes . Status403Forbidden )
. ProducesProblem ( StatusCodes . Status404NotFound ) ; Para evitar múltiples llamadas a ProducesProblem , podemos usar el método de extensión ProducesDefaultProblem proporcionado por la biblioteca:
endpoints . MapGet ( "/api/people/{id:guid}" , Get )
. ProducesDefaultProblem ( StatusCodes . Status400BadRequest , StatusCodes . Status401Unauthorized ,
StatusCodes . Status403Forbidden , StatusCodes . Status404NotFound ) ; Una biblioteca que proporciona un filtro de punto final para proyectos API mínimos para realizar la validación con anotaciones de datos, utilizando la biblioteca de minivalidación.
La biblioteca está disponible en Nuget. Simplemente busque minimalhelpers.validation en la GUI del administrador de paquetes o ejecute el siguiente comando en el .net CLI :
dotnet add package MinimalHelpers.ValidationDecora una clase con atributos para definir las reglas de validación:
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 ; }
} Agregue el método de extensión WithValidation<T>() para habilitar el filtro de validación:
using MinimalHelpers . Validation ;
app . MapPost ( "/api/people" , ( Person person ) =>
{
// ...
} )
. WithValidation < Person > ( ) ; Si la validación falla, la respuesta será una 400 Bad Request con un objeto ValidationProblemDetails que contiene los errores de validación, por ejemplo:
{
"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. "
]
}
} Si desea personalizar la validación, puede usar el método de extensión 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)" ;
} ) ; Puede usar la ValidationErrorTitleMessageFactory , por ejemplo, si desea localizar la propiedad title de la respuesta utilizando un archivo Resx.
Una biblioteca que proporciona un filtro de punto final para proyectos API mínimos para realizar validación utilizando Validación Fluent.
La biblioteca está disponible en Nuget. Simplemente busque minimalHelpers.FlUentValidation en la GUI del administrador de paquetes o ejecute el siguiente comando en el CLI .NET :
dotnet add package MinimalHelpers.FluentValidationCree una clase que extienda AbstractValidator y defina las reglas de validación:
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 los validadores en la colección de servicios:
using FluentValidation ;
// Assuming the validators are in the same assembly as the Program class
builder . Services . AddValidatorsFromAssemblyContaining < Program > ( ) ; Agregue el método de extensión WithValidation<T>() para habilitar el filtro de validación:
using MinimalHelpers . FluentValidation ;
app . MapPost ( "/api/products" , ( Product product ) =>
{
// ...
} )
. WithValidation < Product > ( ) ; Si la validación falla, la respuesta será una 400 Bad Request con un objeto ValidationProblemDetails que contiene los errores de validación, por ejemplo:
{
"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'. "
]
}
} Si desea personalizar la validación, puede usar el método de extensión 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)" ;
} ) ; Puede usar la ValidationErrorTitleMessageFactory , por ejemplo, si desea localizar la propiedad title de la respuesta utilizando un archivo Resx.
Contribuir
El proyecto está en constante evolución. Las contribuciones son bienvenidas. No dude en presentar problemas y extraer solicitudes en el repositorio y los abordaremos lo que podamos.