Valores NULL conservados en la configuración

El enlazador de configuración de .NET recupera los valores de configuración a través de proveedores de configuración e intenta enlazar esos valores a las propiedades del objeto. Anteriormente, cuando un valor de configuración era NULL, el enlazador lo trataba como si el valor no existiera en absoluto y, por tanto, omitía el enlace. En otras palabras, no distinguía entre null valores y valores que faltan. Este comportamiento provocó una confusión significativa para los usuarios que esperaban que los valores definidos null explícitamente en su configuración se respetaran y se enlazaran correctamente.

Además, el proveedor de configuración JSON convertía anteriormente los valores null de la configuración en cadenas vacías. Esto contribuyó aún más a confusión, ya que las propiedades enlazadas a estos valores recibirían una cadena vacía en lugar del valor NULL esperado.

Este cambio soluciona ambos problemas. El proveedor de configuración JSON ahora informa correctamente de los valores null sin modificarlos, y el vinculador trata los valores null como entradas válidas y los vincula como cualquier otro valor.

La actualización también incluye mejoras para admitir valores de enlace null dentro de matrices y permite el enlace de matrices vacías.

Versión introducida

.NET 10

Comportamiento anterior

Anteriormente, cuando un valor de configuración era null, el enlazador lo trataba como si el valor no existiera en absoluto y, por tanto, omitía el enlace. El sistema no distinguía entre null los valores y los valores que faltan.

Además, el proveedor de configuración JSON convirtió null los valores de la configuración en cadenas vacías. Esto provocó que las propiedades enlazadas a estos valores reciban una cadena vacía en lugar de la esperada null.

Tenga en cuenta el siguiente contenido del archivo appsettings.json de configuración:

{
    "NullConfiguration": {
        "StringProperty": null,
        "IntProperty": null,
        "Array1": [null, null],
        "Array2": []
    }
}

Y el código de enlace correspondiente:

public class NullConfiguration
{
    public NullConfiguration()
    {
        // Initialize with non-default value to
        // ensure binding overrides these values.
        StringProperty = "Initial Value";
        IntProperty = 123;
    }
    public string? StringProperty { get; set; }
    public int? IntProperty { get; set; }
    public string[]? Array1 { get; set; }
    public string[]? Array2 { get; set; }
}

var configuration = new ConfigurationBuilder()
                    .AddJsonFile("appsettings.json")
                    .Build().GetSection("NullConfiguration");

// Now bind the configuration.
NullConfiguration? result = configuration.Get<NullConfiguration>();

Console.WriteLine($"StringProperty: '{result!.StringProperty}', intProperty: {(result!.IntProperty.HasValue ? result!.IntProperty : "null")}");
Console.WriteLine($"Array1: {(result!.Array1 is null ?
    "null" : string.Join(", ", result!.Array1.Select(a => $"'{(a is null ? "null" : a)}'")))}");
Console.WriteLine($"Array2: {(result!.Array2 is null ?
    "null" : string.Join(", ", result!.Array2.Select(a => $"'{(a is null ? "null" : a)}'")))}");

Salida:

StringProperty: '', intProperty: 123
Array1: '', ''
Array2: null

Explicación de la salida:

  • StringProperty: El valor null del JSON fue convertido por el proveedor de JSON en una cadena vacía (""), sobrescribiendo el valor inicial.
  • IntProperty: permaneció sin cambios (123) porque el proveedor convirtió null en una cadena vacía, que no se pudo analizar como un int?, por lo que se conservó el valor original.
  • Array1: enlazado a una matriz que contiene dos cadenas vacías porque cada null elemento de matriz se ha tratado como una cadena vacía.
  • Array2: se mantuvo null desde que el enlazador omitió una matriz [] vacía en el json.

Nuevo comportamiento

A partir de .NET 10, null los valores ahora están enlazados correctamente a sus propiedades correspondientes, incluidos los elementos de matriz. Incluso las matrices vacías se reconocen correctamente y se enlazan como matrices vacías en lugar de omitirse.

Al ejecutar el mismo ejemplo de código se generan los siguientes resultados mediante el proveedor de configuración JSON:

StringProperty: 'null', intProperty: null
Array1: 'null', 'null'
Array2:

Tipos de valor no anulables

El enlazador ahora también enlaza null con propiedades de tipo de valor no anulables (por ejemplo, int, bool o una enumeración), estableciéndolas en el valor predeterminado del tipo (default(T)).

Anteriormente, con el proveedor de configuración JSON, al enlazar null a una propiedad de ese tipo se generaba una InvalidOperationException similar a la siguiente, porque el proveedor había convertido null en una cadena vacía y una cadena vacía no se puede convertir al tipo de valor de destino:

Failed to convert configuration value at 'SomeSection:DayOfWeekProperty' to type 'System.DayOfWeek'.

A partir de .NET 10, el mismo enlace se realiza correctamente y la propiedad se establece en su valor predeterminado. Por ejemplo, un null enlazado a una propiedad DayOfWeek da como resultado DayOfWeek.Sunday (0), y un null enlazado a una propiedad int da como resultado 0. No se inicia ninguna excepción.

Los proveedores que almacenan un valor real null, como el proveedor en memoria, ya vinculaban null a propiedades de tipo valor no anulables estableciendo el valor predeterminado, incluso antes de .NET 10, y el generador de código fuente de configuración también reproduce este comportamiento. El cambio hace que el proveedor JSON y el enlazador basado en la reflexión sean coherentes con ese comportamiento.

Tipo de cambio disruptivo

Se trata de un cambio de comportamiento .

Motivo del cambio

El comportamiento anterior era confuso y frecuentemente llevó a quejas del usuario. Al solucionar este problema, el proceso de enlace de configuración ahora es más intuitivo y coherente, lo que reduce la confusión y alinea el comportamiento con las expectativas del usuario.

Si prefiere el comportamiento anterior, puede ajustar la configuración en consecuencia:

  • Al usar el proveedor de configuración JSON, reemplace null los valores por cadenas vacías ("") para restaurar el comportamiento original, donde las cadenas vacías están enlazadas en lugar de null.
  • Para otros proveedores que admiten null valores, quite las null entradas de la configuración para replicar el comportamiento anterior, donde los valores que faltan se omiten y los valores de propiedad existentes permanecen sin cambios.
  • Si antes dependía de que se produjera una excepción cuando se enlazaba un valor null a una propiedad de tipo de valor no anulable, tenga en cuenta que el enlazador de datos ahora establece la propiedad en su valor predeterminado en su lugar. Para distinguir la ausencia de un valor o un valor null de un valor real, haga que la propiedad admita valores NULL (por ejemplo, int? o DayOfWeek?) y compruebe si es null después de la vinculación, o valide la configuración explícitamente.

Las APIs afectadas