Les valeurs nulles sont conservées dans la configuration

Le classeur de configuration .NET récupère les valeurs de configuration via des fournisseurs de configuration et tente de lier ces valeurs aux propriétés d’objet. Auparavant, lorsqu’une valeur de configuration était null, le binder la traitait comme si la valeur n’existait pas du tout et ignorait donc le binding. En d’autres termes, il n’a pas fait la distinction entre les valeurs null et les valeurs manquantes. Ce comportement a provoqué une confusion significative pour les utilisateurs qui s'attendaient à ce que des valeurs définies explicitement dans leur configuration soient respectées et correctement liées.

En outre, le fournisseur de configuration JSON a précédemment converti null des valeurs dans la configuration en chaînes vides. Cela a également contribué à la confusion, car les propriétés liées à ces valeurs recevaient une chaîne vide plutôt que la valeur null attendue.

Cette modification résout les deux problèmes. Le fournisseur de configuration JSON signale désormais correctement les valeurs null sans les modifier, et le classeur traite les valeurs null comme des entrées valides, les liant comme n'importe quelle autre valeur.

La mise à jour inclut aussi des améliorations pour faciliter la liaison des valeurs null dans les tableaux et autorise désormais la liaison de tableaux vides.

Version introduite

.NET 10

Comportement précédent

Auparavant, lorsqu’une valeur de configuration était null, le binder la traitait comme si la valeur n’existait pas du tout et ignorait donc le binding. Le système n’a pas fait de distinction entre les valeurs null et les valeurs manquantes.

En outre, le fournisseur de configuration JSON a converti null les valeurs de la configuration en chaînes vides. Les propriétés liées à ces valeurs recevaient une chaîne vide plutôt que la chaîne attendue null.

Tenez compte du contenu du fichier appsettings.json de configuration suivant :

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

Et le code de liaison correspondant :

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)}'")))}");

Sortie:

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

Explication de la sortie :

  • StringProperty: la null valeur du JSON a été convertie par le fournisseur JSON en chaîne vide («  »), en remplaçant la valeur initiale.
  • IntProperty: est resté inchangé (123) car le fournisseur a converti null en une chaîne vide, qui n’a pas pu être analysée comme un int?, donc la valeur d’origine a été conservée.
  • Array1: lié à un tableau contenant deux chaînes vides, car chaque null élément de tableau a été traité comme une chaîne vide.
  • Array2: resté null depuis qu’un tableau [] vide dans le JSON a été ignoré par le classeur.

Nouveau comportement

À compter de .NET 10, null les valeurs sont désormais correctement liées à leurs propriétés correspondantes, y compris les éléments de tableau. Même les tableaux vides sont correctement reconnus et liés en tant que tableaux vides plutôt que d’être ignorés.

L’exécution de l’exemple de code produit les résultats suivants à l’aide du fournisseur de configuration JSON :

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

Types de valeurs non nullables

Le binder lie désormais également null aux propriétés de type valeur non nullable (par exemple, int, bool ou une énumération) en leur attribuant la valeur par défaut du type (default(T)).

Auparavant, avec le fournisseur de configuration JSON, la liaison d’un null à une telle propriété générait un(e) InvalidOperationException semblable à ce qui suit, car le fournisseur avait converti le null en chaîne vide, et une chaîne vide ne peut pas être convertie dans le type de valeur cible :

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

À compter de .NET 10, la même liaison réussit et la propriété est définie sur sa valeur par défaut. Par exemple, une null liaison à une DayOfWeek propriété entraîne DayOfWeek.Sunday (0) et une null liaison à une int propriété entraîne 0. Aucune exception n’est générée.

Les fournisseurs qui stockent une valeur réelle null, comme le fournisseur en mémoire, liaient déjà null aux propriétés de type valeur non nullables en définissant la valeur par défaut, et ce même avant .NET 10, et le générateur source de configuration reproduit également ce comportement. La modification rend le fournisseur JSON et le binder basé sur la réflexion cohérent avec ce comportement.

Type de changement cassant

Il s’agit d’un changement comportemental.

Raison de la modification

Le comportement précédent était confus et a souvent conduit à des plaintes des utilisateurs. En traitant ce problème, le processus de liaison de configuration est désormais plus intuitif et cohérent, ce qui réduit la confusion et aligne le comportement avec les attentes des utilisateurs.

Si vous préférez le comportement précédent, vous pouvez ajuster votre configuration en conséquence :

  • Lorsque vous utilisez le fournisseur de configuration JSON, remplacez null les valeurs par des chaînes vides ("") pour restaurer le comportement d’origine, où les chaînes vides sont liées au lieu de null.
  • Pour les autres fournisseurs qui prennent en charge les valeurs null, supprimez les entrées null de la configuration pour répliquer le comportement antérieur, où les valeurs manquantes sont ignorées et les valeurs de propriété existantes restent inchangées.
  • Si vous vous appuyiez précédemment sur une exception lorsqu’une null valeur était liée à une propriété de type valeur non nullable, notez que le classeur définit maintenant la propriété sur sa valeur par défaut à la place. Pour distinguer une valeur absente ou null d’une valeur réelle, rendez la propriété de type nullable (par exemple, int? ou DayOfWeek?) et vérifiez si elle vaut null après la liaison, ou validez explicitement la configuration.

API affectées