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
Host
yPort
se marcan como necesarias. - La propiedad
Host
debe tener formato URL. - La propiedad
Port
debe 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
AddOptions
para obtener un elementoOptionsBuilder<TOptions>
que enlaza a la claseMongoDbSettings
. - Se llama a
ValidateDataAnnotations
para habilitar la validación conDataAnnotations
. - Se llama a
ValidateOnStart
para 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.