Валидация модели в C#

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

  1. Required — означает, что свойство является обязательным для определения
  2. Range — означает, что число, введенное пользователем, должно находиться в заданном диапазоне (в нашем случае — от 15 до 100)
  3. 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. В следующей части мы более подробно рассмотрим атрибуты валидации и работу с классами, рассмотренными в этой статье.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии