Neu in .NET 8.0 [9]: Neue und erweiterte Datenannotationen
In .NET 8.0 hat Microsoft die Annotationsklassen im Namensraum System.ComponentModel.DataAnnotations erweitert.

(Bild: Pincasso/Shutterstock.com)
- Dr. Holger Schwichtenberg
Die Datenannotation im Namensraum System.ComponentModel.DataAnnotations
gibt es schon seit dem klassischen .NET Framework. Die ersten wie [RegularExpression]
, [Range]
oder [DataType]
wurden in .NET Framework 3.5 eingefĂĽhrt. Weitere Datenannotation folgten in .NET Framework 4.0 (z. B. [Display]
und [Editable]
) und .NET Framework 4.5 (z. B. [MaxLength]
, [Compare]
, [CreditCard]
und [Phone]
). Diese Datenannotation lassen sich auf Klassen oder Properties beziehungsweise Fields verwenden. Sie dienen der Spezifikation der Darstellung (z. B. [Display]
und [Editable]
) oder der Validierung von Werten (z.B. [RegularExpression]
, [Compare]
, [Range]
, [Phone]
und [CreditCard]
). GUI-Steuerelemente mĂĽssen die entsprechenden Annotationen berĂĽcksichtigen.
Es gibt nur wenige Steuerelemente, die die Darstellungsannotationen berücksichtigen – meist schaffen sich .NET-Entwicklerinnen und -Entwickler hier selbst Steuerelemente, die auf Basis der in den Annotationen abgelegten Metadaten eine grafische Benutzeroberfläche on the fly zur Laufzeit erzeugen. Bei den Validierungsannotationen gibt es mehr Steuerelemente, die die Annotationen berücksichtigen, darunter <InputText>
, <InputNumber>
und <InputDate>
in Blazor. Eine Validierung kann man auch unabhängig von einem Steuerelement im Programmcode ausführen. Dazu gibt es die Klassen ValidationContext
, Validator
, ValidationResult
und ValidationException
.
Neue Eigenschaften in .NET 8.0
Die [Range]
-Annotation besitzt in .NET 8.0 die zusätzlichen Eigenschaften MinimumIsExclusive
und MaximumIsExclusive
, um die genannte Unter- und Obergrenze selbst als gĂĽltigen Werte auszuschlieĂźen. Standard ist wie bisher, dass die Grenzen eingeschlossen sind.
Neue Annotationen in .NET 8.0
Zudem hat Microsoft drei neue Annotationsklassen ergänzt:
- Die neue Annotation
[Length]
kann verwendet werden, um die Mindest- und Maximallänge von Objektmengen und Zeichenketten zu setzen. - Mit der neuen Annotation
[Base64String]
prĂĽft man, ob eine Zeichenkette Base64-codiert ist. - Mit
[AllowedValues]
und[DeniedValues]
kann man eine Liste erlaubter Werte fĂĽr Properties eines Objekts angeben. Das funktioniert allerdings nur den Werten in einzelnen Properties oder Fields; auf Objektmengen angewendet wirken diese beiden Annotationen leider nicht.
Das nächste Listing zeigt ein aussagekräftiges Beispiel zu allen neuen Annotationsfeatures anhand der Klasse SoftwareArchitect
mit einigen annotierten Eigenschaften. Die Validierung wird durchgefĂĽhrt mit den Klassen ValidationContext
und Validator
.
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using ITVisions;
using NET8_Console.CustomAnnotations;
namespace NET8_Console.FCL_Annotations;
/// <summary>
/// Neue und erweiterte Annotationen zur Validierung
/// </summary>
public class SoftwareArchitect
{
// Neu in .NET 8.0 --> Nicht als Anrede erlaubt:
[DeniedValues("", "Dr.", "Prof. Dr.")]
public string? Anrede { get; set; }
// Neu in .NET 8.0 --> Erlaubte Titel:
[AllowedValues("", "Dr.", "Prof. Dr.")]
public string? Titel { get; set; }
// funktioniert hier nicht, da es sich um eine Liste handelt:
[AllowedValues("C#", "Java", "JavaScript")]
public List<string> Sprachen { get; set; } = new();
// Neu in .NET 8.0: Unter- und Obergrenze für Zeichenkettenlänge:
[Length(2, 50)]
public string? Name { get; set; }
// Neu in .NET 8.0: Unter- und Obergrenze für Mengenlänge:
[Length(0, 3)]
public List<string> Websites { get; set; } = new();
// Neu in .NET 8.0:
[Base64String]
public string? Token { get; set; }
// MinimumIsExclusive und MaximumIsExclusive
// sind neu seit .NET 8.0
// > 0 und < 120 statt >= und <=:
[Range(0d, 120d, MinimumIsExclusive = true,
MaximumIsExclusive = true)]
public double Alter { get; set; }
#endregion
}
public class FCL_Annotations_Demo
{
public void Run()
{
CUI.H2(nameof(FCL_Annotations_Demo));
// Das zu validierende Objekt erstellen
SoftwareArchitect hs = new()
{
Name = "Holger Schwichtenberg",
Titel = "Doktor",
Anrede = "",
Token = "unsinn"
};
hs.Websites.Add("www.IT-Visions.de");
hs.Websites.Add("www.dotnet-doktor.de");
hs.Websites.Add("www.entwickler-lexikon.de");
hs.Websites.Add("www.dotnet7.de");
hs.Websites.Add("www.dotnet8.de");
hs.Sprachen.Add("C#");
hs.Sprachen.Add("JavaScript");
hs.Sprachen.Add("TypeScript");
// Validierung vorbereiten
var ctx = new ValidationContext(hs);
var results = new List<ValidationResult>();
// Validierung durchfĂĽhren
if (!Validator.TryValidateObject(hs, ctx, results, true))
{
CUI.Error($"{results.Count} errors validating the objects:");
// Fehler ausgeben
foreach (var validationResult in results)
{
CUI.LI(validationResult.ErrorMessage, ConsoleColor.Red);
}
}
else
{
// Es war alles OK
CUI.Success("Validation succeeded!");
}
}
}
(Bild:Â Screenshot von Holger Schwichtenberg)
(rme)