Важную роль при разработке приложений играет валидация (проверка) данных, вводимых пользователями. Любая модель, используемая в нашем приложении содержит определенный набор данных и эти данные должны соответствовать каким-либо критериям. Например, если мы запрашиваем у пользователя возраст, то мы ожидаем, что будет введено число из какого-либо диапазона, например, от 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. В следующей части мы более подробно рассмотрим атрибуты валидации и работу с классами, рассмотренными в этой статье.