Содержание
В целом, тех атрибутов валидации модели, которые уже имеются в ASP.NET Core MVC вполне достаточно для работы, однако, если этих возможностей по каким-либо причинам недостаточно, то мы можем создать свой атрибут валидации и использовать его в приложении.
Приложение для тестирования
Для работы будем использовать приложение из предыдущей части. На данный момент, в приложении изменено представление Views/Home/Index.cshtml следующим образом:
@model Person @{ ViewData["Title"] = "Home Page"; } <form method="post"> <div asp-validation-summary="All"></div> <div> <p> <label asp-for="Name">Name</label><br /> <input type="text" asp-for="Name" /> <span asp-validation-for="Name" /> </p> <p> <label asp-for="Age">Age</label><br /> <input asp-for="Age" /> <span asp-validation-for="Age" /> </p> <p> <label asp-for="Email">Email</label><br /> <input asp-for="Email" /> <span asp-validation-for="Email" /> </p> <p> <input type="submit" value="Send" /> </p> </div> </form> <div class="text-center"> <h1 class="display-4">Welcome</h1> <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.3/jquery.validate.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.12/jquery.validate.unobtrusive.js"></script>
Модель Person
выглядит следующим образом:
using Microsoft.AspNetCore.Mvc; using System.ComponentModel.DataAnnotations; namespace ASpValidationClientSide.Models { public class Person { [Required(ErrorMessage = "Поле Name обязательно к заполнению")] public string Name { get; set; } [EmailAddress] [Remote(action: "CheckMail", controller:"Home", ErrorMessage ="Ошибка: такой email нельзя использовать")] public string Email { get; set; } [Range(1, 100, ErrorMessage = "Возраст должен находится в пределах от 1 до 100 лет")] public int Age { get; set; } } }
Контроллер HomeController
содержит следующие действия:
using ASpValidationClientSide.Models; using Microsoft.AspNetCore.Mvc; using System.Diagnostics; namespace ASpValidationClientSide.Controllers { public class HomeController : Controller { private readonly ILogger<HomeController> _logger; public HomeController(ILogger<HomeController> logger) { _logger = logger; } public IActionResult CheckMail(string email) { if (email == "admin@mail.ru") return Json(false); return Json(true); } [HttpPost] public IActionResult Index(Person person) { if (person.Name == "admin") { ModelState.AddModelError("", "Имя admin запрещено использовать"); } if (ModelState.IsValid) return Ok(person); return View(); } [HttpGet] public IActionResult Index() { return View(); } public IActionResult Privacy() { return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } }
Создание собственного атрибута валидации
Атрибуты валидации на уровне свойства
Класс атрибута валидации должен наследоваться от базового класса ValidationAttribute
. Чтобы добавить свою логику проверки мы должны переопределить в своем классе атрибута метод IsValid()
. Например, создадим следующий атрибут валидации для проверки имени пользователя:
public class NameAttribute: ValidationAttribute { public override bool IsValid(object? value) { if (value == null) { ErrorMessage = "Значение свойства не должно быть равным null"; return false; } string name = (string)value; return char.IsUpper(name[0]); } }
Теперь применим этот атрибут к свойству модели Name
:
public class Person { [Required(ErrorMessage = "Поле Name обязательно к заполнению")] [Name(ErrorMessage ="Имя должно начинаться с прописной буквы")] public string Name { get; set; } ..... }
и проверим действие атрибута:
Атрибуты валидации на уровне модели
Атрибуты валидации на уровне модели применяются для валидации сразу нескольких свойств модели. Например, создадим атрибут, который будет обязывать заполнять все свойства модели:
public class AllRequiredAttribute: ValidationAttribute { public AllRequiredAttribute() { ErrorMessage = "Все поля формы обязательны к заполнению"; } public override bool IsValid(object? value) { if (value == null) return false; Person model = value as Person; return (model.Age > 0) && (model.Email.Length > 0) && (model.Name.Length > 0); } }
теперь этот атрибут можно применить ко всей модели:
[AllRequired] public class Person { public string Name { get; set; } public string Email { get; set; } public int Age { get; set; } }
Итого
При необходимости мы можем создавать собственные атрибуты валидации и применять их как на уровне отдельных свойств, так и на уровне модели в целом. Класс атрибута должен быть унаследован от класса ValidationAttribute
и переопределять метод IsValid()
.