Jubatus.WebApi.Extensions
1.3.37
dotnet add package Jubatus.WebApi.Extensions --version 1.3.37
NuGet\Install-Package Jubatus.WebApi.Extensions -Version 1.3.37
<PackageReference Include="Jubatus.WebApi.Extensions" Version="1.3.37" />
paket add Jubatus.WebApi.Extensions --version 1.3.37
#r "nuget: Jubatus.WebApi.Extensions, 1.3.37"
// Install Jubatus.WebApi.Extensions as a Cake Addin #addin nuget:?package=Jubatus.WebApi.Extensions&version=1.3.37 // Install Jubatus.WebApi.Extensions as a Cake Tool #tool nuget:?package=Jubatus.WebApi.Extensions&version=1.3.37
Jubatus.WebApi.Extensions - Colección de extensiones para WebApis de .NET 8.
Este es un paquete de libre distribución, que inicialmente fue desarrollado para uso en proyectos personales, y para ser muy honesto, me motivé a subirlo a NuGet Gallery, inicialmente para facilitar el despliegue de dichos proyectos a través de contenedores de Docker; pero más allá de eso, espero poder hacer un pequeño aporte a la comunidad, y ahorrarles un poco de trabajo.
Este paquete es una colección de funcionalidades, que por ahora permitirá, a través de Extensions, Interfaces y Dependency Injection la inclusión de ciertas características a un proyecto de tipo WebApi de .NET 8. A continuación se describen las características:
Jubatus.WebApi.Extensions \
| Exceptions \
| GlobalExceptionManager // Manejo de excepciones desde el Middleware.
| Models \
| CypherModel // Modelo para el manejo de usuarios y su contraseña.
| ICypherModel // Interface para definir el modelo de usuarios.
| IEntity // Interface para crear los Modelos y DTO's.
| TokensModel // Modelo para el manejo de Bearer Tokens.
| Settings \
| IJwtSettings // Interface para la configuración del Bearer Token.
| IMongoDbSettings // Interface para la configuración de MongoDB.
| JwtSettings // Clase con la estructura de configuración del JWT.
| MongoDbSettings // Clase con la estructura de configuración del MongoDB.
| FastLogger // Implementación de los delegados de LoggerMessage.
| IRepository // Interface para la implementación del CRUD.
| MongoRepository // Implementación del CRUD con MongoDB.
| Toolbox // Implementación de métodos utilitarios.
| WebApiConfig // Clase principal que crea y asigna las extensiones.
¿Qué novedades y cambios tiene esta versión?
Esta versión 1.3.37 tiene los siguientes cambios:
Se creó la clase estática
FastLogger
la cual contiene delegados deLoggerMessage
para reportar al Logger de una manera más eficiente, y para cada uno de sus niveles: (LogTrace()
,LogDebug()
,LogInfo()
,LogWarning()
,LogError()
, yLogCritical()
). La visibilidad de los mensajes dependerá de la configuración que se tenga en "Logging:LogLevel" en el archivo "appsettings.json".Se actualizó la referencia al paquete de MongoDD.Driver por la versión 2.27.0.
Se eliminó el método estático
GetLogger()
de la clase estáticaToolbox
para darle paso a la implementación deFastLogger
.Se eliminaron las referencias de los paquetes de Serilog.AspNetCore y Destructurama.Attributed, dado que ya no son necesarias por la eliminación del método
GetLogger()
.Se implementó el manejo Global de las Excepciones directamente en el middleware, haciendo uso de la interface
IExceptionHandler
.
¿Cómo adiciono el paquete al proyecto para usarlo?
Abrimos una Terminal en nuestro ambiente de desarrollo de Visual Studio, y nos ubicamos en el directorio donde se encuentra el archivo del proyecto '*.csproj', y allí ejecutamos el siguiente comando:
dotnet add package Jubatus.WebApi.Extensions --version 1.3.37
¿Cómo creo una instancia Singleton de MongoDB y una colección en ella para almacenar mis datos?
- Incluimos el namespace Jubatus.WebApi.Extensions en el Program.cs.
using Jubatus.WebApi.Extensions;
- A continuación creamos una instancia de
WebApiConfig()
, y hacemos el llamado al métodoAddMongoDbExtensions<T>()
, indicando el modelo de datos que vamos a utilizar en la colección de MongoDB (Este modelo debe implementar la interfaceIEntity
).
[...]
var builder = WebApplication.CreateBuilder( args );
[...]
var webApiMgr = new WebApiConfig( builder )
.AddMongoDbExtensions<UsersEntity>();
[!IMPORTANT] El método
AddMongoDbExtensions<T>()
tiene varios parámetros, pero todos con valores por defecto, y son los siguientes:
addMongoDbHealthCheck
: De tipobool
, y nos sirve para indicar se se desea crear/asignar el HealthCheck para la BD de MongoDB (Por defecto está en TRUE).mongoDbHealthCheckTimeout
: De tipodouble
, y nos sirve para configurar el tiempo de espera para la respuesta del HealthCheck de MongoDB (Por defecto está en 3 segundos).configSectionName
: De tipostring
, y lo utilizaremos para indicar el nombre de tiene la sección en el archivo de configuración "appsettings.json", la cual contiene los parámetros para la conexión a MongoDB (Esta sección debe contener mínimamente los parámetros indicados en la interfaceIMongoDbSettings
, y por defecto tiene el valor "MongoDbSettings").
Haciendo el llamado al método
AddMongoDbExtensions<T>()
estamos creando también la colección para almacenar los datos, tomando para su nombre el valor de la llave "CollectionName" de la sección "MongoDbSettings" del archivo de configuración "appsettings.json". Esta colección tendrá la estructura definida en la clase que se pase como parámetro<T>
en el método, que para el ejemplo de arriba, seríaUserEntity
(Esta clase debe implementar la interfaceIEntity
).Para ejecutar el CRUD de la colección definida previamente, debemos apoyarnos de la DI (Dependency Injection), para obtener en el constructor de nuestro Controlador, la instancia Singleton del repositorio, y ya con éste, hacer el llamado a los métodos asíncronos
GetAllAsync()
,GetAsync()
,CreateAsync()
,UpdateAsync()
, yRemoveAsync()
.
public UsersController( IRepository<UsersEntity> usersRepository ): ControllerBase
{ ... }
¿Cómo configuro la Autenticación y Autorización con Bearer Tokens - JWT?
- Incluimos el namespace Jubatus.WebApi.Extensions en el Program.cs.
using Jubatus.WebApi.Extensions;
- A continuación creamos una instancia de
WebApiConfig()
, y hacemos el llamado al métodoAddBearerJwtExtensions()
.
[...]
var builder = WebApplication.CreateBuilder( args );
[...]
var webApiMgr = new WebApiConfig( builder )
.AddBearerJwtExtensions();
[!IMPORTANT] El método
AddBearerJwtExtensions()
tiene un parámetro, el cual tiene un valor por defecto, y es el siguiente:
configSectionName
: De tipostring
, y lo utilizaremos para indicar el nombre que tiene la sección en el archivo de configuración "appsettings.json", en la cual están los parámetros para el Bearer JWT (Esta sección debe contener mínimamente los parámetros indicados en la interfaceIJwtSettings
, y por defecto tiene el valor "JwtSettings").
- Para la autenticación del usuario que está solicitando Bearer Tokens, nos podemos apoyar del método estático
GenerateBearerToken()
de la claseToolbox
. Este método requiere que se suministren los datos del usuario en una clase que implemente la interfaceICypherModel
, y adicional los demás parámetros.
[!IMPORTANT] Para que el método
GenerateBearerToken()
retorne exitosamente un Bearer Token, es necesario que el Usuario y la Contraseña suministrados en el parámerouserData
, correspondan con los datos almacenados en la sección "JwtSettings" del archivo de configuración "appsettings.json", y son los siguientes:
AuthUser
: Usuario autorizado para solicitar Bearer Tokens.AuthPass
: Contraseña del usuario autorizado para solicitar Bearer Tokens (Para cifrar esta contraseña antes de guardarla, se puede apoyar de la extensiónEncryptUserPassword()
de la clase que implemente la interfaceICypherModel
).Se debe tener en cuenta que a cada uno de los controladores que requieran esta autorización deben tener asignado el atributo
[Authorize]
y esto aplicaría para cada uno de los Endpoints definidos allí, a menos que tengan el atributo[AllowAnonymous]
, como lo indica el siguiente ejemplo:
[Authorize]
public UsersController( IRepository<UsersEntity> usersRepository ): ControllerBase
{
...
[AllowAnonymous]
public async Task<ActionResult> AuthenticateAsync( [FromBody] AuthUserDto authUser )
{ ... }
}
¿Cómo implemento en mi Servicio un RateLimiter básico (fixed)?
- Incluimos el namespace Jubatus.WebApi.Extensions en el Program.cs.
using Jubatus.WebApi.Extensions;
- A continuación creamos una instancia de
WebApiConfig()
, y hacemos el llamado al métodoAddFixedRateLimiter()
.
[...]
var builder = WebApplication.CreateBuilder( args );
[...]
var webApiMgr = new WebApiConfig( builder )
.AddFixedRateLimiter();
[!IMPORTANT] El método
AddFixedRateLimiter()
tiene varios parámetros con valores por defecto, y son los siguientes:
permitLimit
: De tipoint
, y nos sirve para indicar el número máximo de request simultáneos (Por defecto tiene el valor 10).secondsTimeout
: De tipodouble
, y nos sirve para indicar el tiempo máximo (en segundos) de cada request (Por defecto tiene el valor 5).processingOrder
: De tipoQueueProcessingOrder
, y nos sirve para indicar el orden de prioridad cuando se tiene pocos recursos en el Sistema (Por defecto tiene el valorQueueProcessingOrder.OldestFirst
).queueLimit
: De tipoint
, y lo utilizaremos para indicar el número máximo de peticiones en cola (Por defecto tiene el valor 2).Para que esta característica tenga efecto en nuestras APIs, debemos incluir el atributo
[EnableRateLimiting( "fixed" )]
, en cada uno de los controladores, como se indica a continuación.
[EnableRateLimiting( "fixed" )]
public UsersController( IRepository<UsersEntity> usersRepository ): ControllerBase
{ ... }
¿Cómo le puedo aplicar el Versionamiento a mis APIs?
- Incluimos el namespace Jubatus.WebApi.Extensions en el Program.cs.
using Jubatus.WebApi.Extensions;
- A continuación creamos una instancia de
WebApiConfig()
, y hacemos el llamado al métodoAddUrlAndHeaderApiVersioning()
.
[...]
var builder = WebApplication.CreateBuilder( args );
[...]
var webApiMgr = new WebApiConfig( builder )
.AddUrlAndHeaderApiVersioning();
[!IMPORTANT] El método
AddUrlAndHeaderApiVersioning()
también tiene varios parámetros con valores por defecto, y son los siguientes:
majorVer
: De tipoint
, y aquí estamos definiendo la versión mayor por defecto (Por defecto tiene el valor 1).minorVer
: De tipoint?
, para indicar la versión menor por defecto (Por defecto tiene el valornull
).status
: De tipostring?
, y aquí podemos incluir un estado adicional a la versión (Por defecto tiene el valornull
).En el controlador de nuestra API, y en cada uno de los Endpoints en el, debemos especificar las versiones a través de atributos, como se muestra a continuación:
[ApiVersion( 1.0 )]
public UsersController( IRepository<UsersEntity> usersRepository ): ControllerBase
{
...
[MapToApiVersion( 1.0 )]
public async Task<ActionResult> AuthenticateAsync( [FromBody] AuthUserDto authUser )
{ ... }
}
¿Cómo mapeo los HealthChecks, el RateLimiter, y/o Autenticación a mi Servicio?
Para completar/terminar la configuración de las funcionalidades adicionadas al Servicio, descritas en la parte de arriba, es necesario que ejecutemos el método BuildWebApp()
de la misma clase WebApiConfig
, como se indica a continuación:
[...]
var builder = WebApplication.CreateBuilder( args );
[...]
var webApiMgr = new WebApiConfig( builder )
.AddMongoDbExtensions<UsersEntity>()
.AddBearerJwtExtensions()
.AddFixedRateLimiter()
.AddUrlAndHeaderApiVersioning();
var app = webApiMgr.BuildWebApp( "api/v{v:apiVersion}/users/health/live", "api/v{v:apiVersion}/users/health/ready" );
[...]
[!IMPORTANT] El método
BuildWebApp()
también tiene varios parámetros con valores por defecto, y son los siguientes:
serviceHealthCheckEndpoint
: De tipostring?
, y aquí debemos suministrar el Endpoint que usaremos para chequear la disponibilidad del Servicio (Por defecto tiene el valornull
, y en ese caso no quedaría habillitado el HealthCheck).mongoHealthCheckEndpoint
: De tipostring?
, y en el que debemos suministrar el Endpoint definido para validar la disponibilidad de la BD de MongoDB (Por defecto tiene el valornull
, y en ese caso no quedaría habilitado el HealthCheck).
Menciones y agradecimientos:
- Agradezco el gran apoyo y sus valiosas recomendaciones de Eddie Velasquez, mi mentor y amigo.
- Gracias a / Thanks so much to Timo Vilppu por su valioso aporte y la información suministrada sobre el tema
IAsyncEnumerable
. - Gracias tambien a / Thanks so much to Michael Altmann por su aporte e información sobre
FluentResults
. - Finalmente y no menos importante, un agradecimiento por el valioso aporte que hacen a la comunidad Stefan Djokic y Milan Jovanović
Dependencias
"Asp.Versioning.Http" Version="8.1.0"
"Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0"
"AspNetCore.HealthChecks.MongoDb" Version="8.0.1"
"FluentResults" Version="3.16.0"
"Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8"
"Microsoft.Extensions.Configuration" Version="8.0.0"
"Microsoft.Extensions.Configuration.Binder" Version="8.0.2"
"Microsoft.Extensions.DependencyInjection" Version="8.0.0"
"Microsoft.AspNetCore.OpenApi" Version="8.0.4"
"MongoDB.Driver" Version="2.27.0"
"MongoDB.Driver.Linq.AsyncEnumerable" Version="2.15.4"
"Swashbuckle.AspNetCore" Version="6.7.0"
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- Asp.Versioning.Http (>= 8.1.0)
- Asp.Versioning.Mvc.ApiExplorer (>= 8.1.0)
- AspNetCore.HealthChecks.MongoDb (>= 8.0.1)
- FluentResults (>= 3.16.0)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 8.0.8)
- Microsoft.AspNetCore.OpenApi (>= 8.0.4)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- MongoDB.Driver (>= 2.27.0)
- MongoDB.Driver.Linq.AsyncEnumerable (>= 2.15.4)
- Swashbuckle.AspNetCore (>= 6.7.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.