Validación de la Configuración en ASP.NET Core Mediante el Patrón de Opciones
ASP.NET Core permite validar los valores de configuración de clases de opciones de tres formas:
- Atributos de anotaciones de datos o
DataAnnotations. - Delegados.
- Interfaz
IValidateOptions, que permite implementar validaciones complejas.
Atributos de Anotación de Datos
Como su nombre lo indica, permite realizar validaciones por medio de atributos anotaciones de datos. Las mismas que son listadas a continuación:
| Atributo | Descripción |
|---|---|
| AllowedValues | Especifica una lista de valores que se deben permitir en una propiedad . |
| Association | Especifica que un miembro de entidad representa una relación de datos, como una relación de clave externa. |
| Base64String | Especifica que un valor de campo de datos es una cadena Base64 bien formada. |
| Compare | Proporciona un atributo que compara dos propiedades. |
| ConcurrencyCheck | Especifica que una propiedad participa en las comprobaciones de simultaneidad optimista. |
| CreditCard | Especifica que el valor de un campo de datos es un número de tarjeta de crédito. |
| CustomValidation | Especifica un método de validación personalizado que se usa para validar una instancia de clase o propiedad. |
| DataType | Especifica el nombre de un tipo adicional para asociar con un campo de datos. |
| DeniedValues | Especifica una lista de valores que no se deben permitir en una propiedad . |
| Display | Proporciona un atributo de uso general que permite especificar cadenas localizables para tipos y miembros de clases parciales de entidad. |
| DisplayColumn | Especifica la columna que se muestra en la tabla a la que se hizo referencia como una columna de clave externa. |
| DisplayFormat | Especifica el modo en que los datos dinámicos de ASP.NET muestran y dan formato a los campos de datos. |
| Editable | Indica si un campo de datos es editable. |
| EmailAddress | Valida una dirección de correo electrónico. |
| EnumDataType | Permite que se asigne una enumeración .NET a una columna de datos. |
| FileExtensions | Valida las extensiones de nombre de archivo. |
| FilterUIHint | Representa un atributo que se usa para especificar el comportamiento de filtrado de una columna. |
| Key | Denota una o varias propiedades que identifican una entidad de forma única. |
| Length | Especifica la longitud mínima y máxima de los datos de colección o cadena permitidos en una propiedad . |
| MaxLength | Especifica la longitud máxima de los datos de matriz o de cadena permitida en una propiedad. |
| MetadataType | Especifica la clase de metadatos que debe asociarse a una clase de modelo de datos. |
| MinLength | Especifica la longitud mínima de los datos de matriz o de cadena permitida en una propiedad. |
| Phone | Especifica que un valor de campo de datos es un número de teléfono con formato correcto. |
| Range | Especifica las restricciones de intervalo numérico para el valor de un campo de datos. |
| RegularExpression | Especifica que un valor de campo de datos en los datos dinámicos de ASP.NET debe coincidir con la expresión regular especificada. |
| Required | Especifica que se requiere un valor de campo de datos. |
| ScaffoldColumn | Especifica si una clase o una columna de datos usan la técnica scaffolding. |
| StringLength | Especifica la longitud mínima y máxima de caracteres que se permite en un campo de datos. |
| Timestamp | Especifica el tipo de datos de la columna como una versión de fila. |
| UIHint | Especifica la plantilla o el control de usuario que los datos dinámicos usan para mostrar un campo de datos. |
| Url | Proporciona la validación de la dirección URL. |
Considere el siguiente archivo appsettings.json:
{
"MongoDbSettings": {
"Host": "localhost",
"Port": 27017
}
}
El siguiente código implementa atributos de anotación de datos en la clase de opciones MongoDbSettings
using System.ComponentModel.DataAnnotations;
public class MongoDbSettings
{
[Required, Url]
public string? Host { get; set; }
[Required]
[Range(0,
65535,
ErrorMessage = "Valor de {0} debe estar entre {1} y {2}.")]
public int Port { get; set; }
}
El código C# anterior:
- Las propiedades
HostyPortse marcan como necesarias. - La propiedad
Hostdebe tener formato URL. - La propiedad
Portdebe contener un valor entre 0 y 65535.
Mediante el siguiente código, se configura la validación de la clase de opciones MongoDbSettings
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOptions()
.BindConfiguration(nameof(MongoDbSettings))
.ValidateDataAnnotations()
.ValidateOnStart();
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.WriteIndented = true;
});
var app = builder.Build();
app.MapGet("/", () => app.Configuration.AsEnumerable());
app.Run();
El código C# anterior:
- Se llama a
AddOptionspara obtener un elementoOptionsBuilder<TOptions>que enlaza a la claseMongoDbSettings. - Se llama a
ValidateDataAnnotationspara habilitar la validación conDataAnnotations. - Se llama a
ValidateOnStartpara que la validación se produzca al iniciar la aplicación.
Resultados de la validación de la propiedad Host:
Microsoft.Extensions.Options.OptionsValidationException
HResult=0x80131500
Message=DataAnnotation validation failed for 'MongoDbSettings' members: 'Host' with the error: 'The Host field is required.'.
Source=Microsoft.Extensions.Options
StackTrace... //Omitido por razones de brevedad.
Microsoft.Extensions.Options.OptionsValidationException
HResult=0x80131500
Message=DataAnnotation validation failed for 'MongoDbSettings' members: 'Host' with the error: 'The Host field is not a valid fully-qualified http, https, or ftp URL.'.
Source=Microsoft.Extensions.Options
StackTrace... //Omitido por razones de brevedad.
Resultado de la validación de la propiedad Port:
Microsoft.Extensions.Options.OptionsValidationException
HResult=0x80131500
Message=DataAnnotation validation failed for 'MongoDbSettings' members: 'Port' with the error: 'Valor de Port debe estar entre 0 y 65535.'.
Source=Microsoft.Extensions.Options
StackTrace... //Omitido por razones de brevedad.
A partir de .NET 8 puede usar un método alternativo a ValidateOnStart; AddOptionsWithValidateOnStart, que habilita la validación al iniciarse para un tipo de opciones específico.
Delegado
Se pueden agregar una o más reglas de validación mediante el método Validate, el cual registra una acción de validación más compleja para un tipo de opciones.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOptions()
.BindConfiguration(nameof(MongoDbSettings))
.ValidateDataAnnotations()
.Validate(config =>
{
if (config.Host == "http://localhost/")
{
return config.Port == 27017;
}
return true;
}, "Si el Host es http://localhost/, el puerto debe ser 27017")
.Validate(mongoDbSettings =>
{
return mongoDbSettings.Host.StartsWith("https://");
}, "El host debe iniciar con https://")
.ValidateOnStart();
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.WriteIndented = true;
});
var app = builder.Build();
app.MapGet("/", () => app.Configuration.AsEnumerable());
app.Run();
El código C# anterior:
- Se agregan dos validaciones anidadas mediante el metodo
Validate.
Resultado de la validación 1:
Microsoft.Extensions.Options.OptionsValidationException
HResult=0x80131500
Message=Si el Host es http://localhost/, el puerto debe ser 27017
Source=Microsoft.Extensions.Options
StackTrace... //Omitido por razones de brevedad.
Resultado de la validación 2:
Microsoft.Extensions.Options.OptionsValidationException
HResult=0x80131500
Message=El host debe iniciar con https://
Source=Microsoft.Extensions.Options
StackTrace... //Omitido por razones de brevedad.
Interfaz IValidateOptions
La interfaz IValidateOptions permite implementar las reglas de validación dentro de una clase.
La siguiente clase ValidateMongoDbSettings implementa la interfaz IValidateOptions:
using Microsoft.Extensions.Options;
using System.Text;
public class ValidateMongoDbSettings : IValidateOptions
{
public ValidateOptionsResult Validate(string? name,
MongoDbSettings options)
{
StringBuilder? error = null;
if (options.Port is < 0 or > 65535)
{
(error ??= new()).AppendLine($"Valor de puerto {options.Port} debe estar entre 0 y 65535.");
}
if (options.Host == "http://localhost/")
{
if (options.Port != 27017)
{
(error ??= new()).AppendLine($"Número de puerto incorrecto: {options.Port}. Si el Host es http://localhost/, el puerto debe ser 27017");
}
}
return error is not null
? ValidateOptionsResult.Fail(error.ToString())
: ValidateOptionsResult.Success;
}
}
Que es configurada mediante el siguiente código de la clase Program.cs:
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOptions<MongoDbSettings>()
.BindConfiguration(nameof(MongoDbSettings))
.ValidateOnStart();
builder.Services.AddSingleton(serviceType =>
serviceType.GetRequiredService<IOptions<MongoDbSettings>>().Value);
builder.Services.TryAddEnumerable(
ServiceDescriptor.Singleton<IValidateOptions<MongoDbSettings>, ValidateMongoDbSettings>());
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.WriteIndented = true;
});
var app = builder.Build();
app.MapGet("/", () => app.Configuration.AsEnumerable());
app.Run();
Resultado de la validación:
Microsoft.Extensions.Options.OptionsValidationException
HResult=0x80131500
Message=Número de puerto incorrecto: 37017. Si el Host es http://localhost/, el puerto debe ser 27017
Source=Microsoft.Extensions.Options
StackTrace... //Omitido por razones de brevedad.
Artículos Relacionados
- Acceso a la Configuración de ASP.NET Core Mediante el Patrón de Opciones.
- Configuración Posterior en ASP.NET Core Mediante el Patrón de Opciones.
- Acceso a la Configuración de ASP.NET Core Mediante IConfiguration.
Recursos Adicionales
- Patrón de opciones en .NET.
- Atributos de Anotación de Datos.
- Interfaz IValidateOptions.
- Código Fuente de la Interfaz IValidateOptions.
- Método AddOptions.
- Código Fuente del Método AddOptions.
- Método BindConfiguration.
- Código Fuente del Método BindConfiguration.
- Método ValidateDataAnnotations.
- Código Fuente del Método ValidateDataAnnotations.
- Método ValidateOnStart.
- Código Fuente del Método ValidateOnStart.
- Método Validate.
- Código Fuente del Método Validate.