Важную роль при разработке приложений играет валидация (проверка) данных, вводимых пользователями. Любая модель, используемая в нашем приложении содержит определенный набор данных и эти данные должны соответствовать каким-либо критериям. Например, если мы запрашиваем у пользователя возраст, то мы ожидаем, что будет введено число из какого-либо диапазона, например, от 15 до 99. Если пользователь введет значение 146, то, минимум, чо произойдет — это сохранение некорректного значения, например, в БД. В других случаях некорректный ввод данных в программу может спровоцировать ошибки в программе.
Пример простой валидации модели в C#
В C#, как и в любом другом современном языке программирования, любую задачу можно решить несколькими способами. Например, если вернуться к примеру с возрастом пользователя, то мы могли бы провести вот такую валидацию модели:
using System; namespace ConsoleApp1 { public class User { public int Age { get; set; } public string Name { get; set; } } internal class Program { static void Main(string[] args) { User user = new User(); Console.WriteLine("Имя:"); user.Name = Console.ReadLine(); Console.WriteLine("Возраст: "); user.Age = Convert.ToInt32(Console.ReadLine()); if ((user.Age < 15) || (user.Age > 100)) { Console.WriteLine("Введено некорректное значение возраста"); } else Console.WriteLine($"Добро пожаловать, {user.Name}"); } } }
Здесь мы, используя конструкцию if...else
проверяем возраст пользователя и, если возраст оказывается менее 15 или более 100 лет, то пользователю возвращается сообщение об ошибке, иначе — приветствие. Такая проверка вполне работоспособна, но имеет свои недостатки и самый главный из них — неуниверсальность такого подхода. Что, например, мы будем делать, если валидацию необходимо провести не одного, а, скажем, десяти свойств и по разным критериям? Мы, конечно, можем воспользоваться всё тем же старым и неуниверсальным подходом с использование if..else
и написать, в итоге, совершенно не читаемый, но, возможно, рабочий код. А можем использовать те инструменты и возможности валидации модели в C#, которые уже есть в языке программирования.
Использование атрибутов для валидации модели
С атрибутами в C# мы уже сталкивались, когда рассматривали тему работы с JSON в C#. Для того, чтобы использовать атрибуты валидации модели в C# необходимо в проект подключить пространство имен System.ComponentModel.DataAnnotations
. В этом пространстве имен содержатся различный классы атрибутов для валидации данных, некоторыми из которых мы сейчас воспользуется. Перепишем наш пример с пользователем следующим образом:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; namespace ConsoleApp1 { public class User { [Required] [Range(15,100)] public int Age { get; set; } [Required] [StringLength(50, MinimumLength = 3)] public string Name { get; set; } } internal class Program { static void Main(string[] args) { User user = new User(); Console.WriteLine("Имя:"); user.Name = Console.ReadLine(); Console.WriteLine("Возраст: "); user.Age = Convert.ToInt32(Console.ReadLine()); var results = new List<ValidationResult>(); var context = new ValidationContext(user); if (!Validator.TryValidateObject(user, context, results, true)) { foreach (var error in results) { Console.WriteLine(error.ErrorMessage); } } } } }
Посмотрим, что изменилось в нашем приложении. Во-первых, для свойств класса User
мы определили по два атрибута:
Required
— означает, что свойство является обязательным для определенияRange
— означает, что число, введенное пользователем, должно находиться в заданном диапазоне (в нашем случае — от 15 до 100)StringLength
— определяет длину строки (в нашем случае, строка с именем должна быть не менее трех и не более пятидесяти символов)
В методе Main
мы использовали три класса из пространства имен System.ComponentModel.DataAnnotations
: ValidationResult
, Validator
и ValidationContext
.
Используя класс ValidationContext
мы создаем т.н. контекст валидации и в конструкторе, в первом параметре, передаем объект, которые необходимо проверить. В нашем случае, это объект класса User
. Далее, мы передаем этот контекст в метод TryValidateObject
класса Validator
. Метод возвращает значение true
, если проверка объекта прошла успешно и все свойства заполнены корректно. Если же при валидации модели обнаружены какие-либо ошибки, то метод вернет значение false
, а обнаруженные ошибки будут сохранены в списке List<ValidationResult>
.
Результат работы программы в случае обнаружения ошибок может быть следующим:
Ю
Возраст:
12
The field Age must be between 15 and 100.
The field Name must be a string with a minimum length of 3 and a maximum length of 50.
Таким образом, вместо нагромождения различных конструкций типа if...else
в коде мы воспользовались классами валидации и проверили нашу модель пользователя на корректность введенных данных. Код приложения стал понятнее, а его поддержка — проще, так как все требования к модели мы описали с помощью атрибутов валидации в самом классе User
.
Итого
Сегодня мы рассмотрели основные моменты валидации модели в C# с использованием атрибутов валидации. Для валидации могут использоваться три класса ValidationResult
, Validator
и ValidationContext
из пространства имен System.ComponentModel.DataAnnotations
. В следующей части мы более подробно рассмотрим атрибуты валидации и работу с классами, рассмотренными в этой статье.