Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Microsoft.Extensions.Validation поддерживает сложную валидацию модели в проектах Blazor и Minimal API.
Хотя API в Microsoft.Extensions.Validation пакете NuGet можно использовать в сценариях вне ASP.NET Core, эта статья посвящена ASP.NET Core. API не поддерживается для MVC или Razor Pages. Рекомендации по проверке, применимые к MVC и Razor Pages, см. в разделе "Проверка модели" в ASP.NET Core MVC.
Чтобы включить проверку, вызовите AddValidation для WebApplicationBuilder.Services в файле Program приложения:
builder.Services.AddValidation();
Для минимальных API реализация автоматически обнаруживает типы, определенные в обработчиках или выступающие в качестве базовых типов для типов, определенных в обработчиках. Фильтр конечной точки выполняет проверку этих типов и добавляется для каждой конечной точки.
Проверка использует генератор источника, который обнаруживает только допустимые типы в сборке, где AddValidation вызывается. Если конечные точки Minimal API определены в сборке, на которую есть ссылка, а не в сборке, где вызывается AddValidation, зарегистрируйте валидацию, как показано в разделе Регистрация валидации в приложениях с несколькими сборками.
Регистрация проверки в приложениях с несколькими сборками
Чтобы проверить типы из отдельных сборок, выполните следующие действия.
- Если сборка является обычной библиотекой классов (она не основана на SDK
Microsoft.NET.Sdk.WebилиMicrosoft.NET.Sdk.Razor), добавьте в проект ссылку на пакет NuGetMicrosoft.Extensions.Validation. - Создайте в каждой внешней сборке метод расширения, который вызывает AddValidation.
- Вызовите каждый из этих методов расширения в главном приложении.
Минимальный пример API
Если типы обработчиков конечных точек определяются для конечных точек в отдельной сборке API, но AddValidation вызываются только из сборки ведущего приложения, проверка не выполняется: недопустимые запросы обрабатываются и возвращают 200 - OK ответ вместо ожидаемого 400 - Bad Request ответа, даже если AddValidation зарегистрированы и типы запросов используют атрибуты проверки.
Создайте метод расширения коллекции служб в сборке, которая определяет минимальные конечные точки API и вызывает его из ведущего приложения.
ServiceCollectionExtensions.cs в сборке, определяющей конечные точки, в которой используется пространство имён из примера MinimalApisAssembly.Extensions:
namespace MinimalApisAssembly.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddApiValidation(
this IServiceCollection services)
{
return services.AddValidation();
}
}
В файле ведущего приложения Program вызовите метод расширения вместо вызова AddValidation напрямую:
using MinimalApisAssembly.Extensions;
...
builder.Services.AddApiValidation();
...
var app = builder.Build();
app.MapApi();
В предыдущем примере MapApi — это метод расширения, определённый в сборке endpoints и сопоставляющий конечные точки Minimal API. Определите его вместе с AddApiValidation тем, чтобы сопоставления конечных точек и проверка регистрировались из одной сборки.
Blazor Web App пример
Если типы моделей форм определены в отдельной библиотеке или в проекте Blazor Web App компонента .Client, но AddValidation вызывается только из сборки серверного приложения, проверка форм не учитывает атрибуты валидации моделей.
Создайте метод расширения коллекции служб в сборке, которая определяет допустимые типы и вызывает его из ведущего приложения.
Для проверки модели, определённой в проекте .ClientBlazor Web App:
- Создайте в проекте IServiceCollection метод, который принимает экземпляр
.Clientв качестве аргумента и вызывает для него AddValidation. - В приложении вызовите как метод, так и AddValidation.
Предыдущий подход приводит к проверке типов из обеих сборок.
В следующем примере метод AddValidationForClientTypes создается для проекта .Client валидации с использованием типов, определяемых в проекте Blazor Web App.
ServiceCollectionExtensions.cs в проекте .Client, который определяет типы, подлежащие проверке, и использует пример пространства имен BlazorSample.Client.Extensions:
namespace BlazorSample.Client.Extensions;
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddValidationForClientTypes(
this IServiceCollection services)
{
return services.AddValidation();
}
}
В файле Program серверного проекта:
- Вызовите метод расширения коллекции служб проекта
.Client, чтобы проверить типы в проекте.Client. - Вызов AddValidation для проверки типов в серверном проекте.
using BlazorSample.Client.Extensions;
...
builder.Services.AddValidationForClientTypes();
builder.Services.AddValidation();
Экспериментальный API в приложениях, предназначенных для .NET 10
Атрибуты из Microsoft.Extensions.Validation пакета NuGet ( и SkipValidationAttribute) помечены как ValidatableTypeAttribute в .NET 10. Пакет предназначен для предоставления новой общей инфраструктуры для функций проверки в разных платформах, а публикация экспериментальных типов обеспечивает большую гибкость для окончательного проектирования общедоступного API для повышения поддержки в использовании платформ. По состоянию на .NET 11 атрибуты больше не экспериментальны, поэтому рекомендации в этом разделе не применяются к приложениям, предназначенным для .NET 11 или более поздней версии.
В Blazor приложениях типы становятся доступными с помощью созданного внедренного атрибута. Если веб-приложение project, использующее пакет SDK [ValidatableType]/[SkipValidation] атрибуты для своих классов без беспокойства по поводу их источника.
Однако приведенный выше подход не подходит в библиотеках обычных классов, использующих пакет SDK Microsoft.NET.Sdk (<Project Sdk="Microsoft.NET.Sdk">). Использование типов в обычной библиотеке классов приводит к предупреждению анализа кода:
ASP0029: "Microsoft.Extensions.Validation.ValidatableTypeAttribute" предназначен только для оценки и подлежит изменению или удалению в будущих обновлениях. Отключайте эту диагностику, чтобы продолжить.
Предупреждение можно отключить с помощью любого из следующих подходов:
Свойство
<NoWarn>в файле проекта:<PropertyGroup> <NoWarn>$(NoWarn);ASP0029</NoWarn> </PropertyGroup>Директива
pragma, в которой используется атрибут:#pragma warning disable ASP0029 [Microsoft.Extensions.Validation.ValidatableType] #pragma warning restore ASP0029Правило для файла EditorConfig (
.editorconfig)dotnet_diagnostic.ASP0029.severity = none
Если отключение предупреждения неприемлемо, вручную создайте встраиваемый атрибут в библиотеке, которую веб-библиотеки и Razor пакеты SDK генерируют автоматически.
ValidatableTypeAttribute.cs:
namespace Microsoft.Extensions.Validation.Embedded
{
[AttributeUsage(AttributeTargets.Class)]
internal sealed class ValidatableTypeAttribute : Attribute
{
}
}
Используйте точное пространство имен (Microsoft.Extensions.Validation.Embedded) и имя класса (ValidatableTypeAttribute), чтобы генератор источника проверки обнаружил и использовал тип. Вы можете объявить глобальную инструкцию using для пространства имен с помощью инструкции global using Microsoft.Extensions.Validation.Embedded; или элемента <Using Include="Microsoft.Extensions.Validation.Embedded" /> в файле проекта библиотеки.
Какой бы подход ни был принят, укажите наличие обходного решения для будущего обновления кода, когда приложение может использовать .NET 11 или более поздней версии. В то время вы можете удалить обходные пути из приложения.
Проверяемые сущности
Можно проверить три типа сущностей:
- Параметры (относящиеся к минимальным параметрам конечной точки API)
- Типы
- Properties
Проверка параметров
Проверка параметров — это первый шаг в конвейере проверки для минимальных конечных точек API. Для этого необходимо выполнить следующие действия.
- Проверяйте экземпляры ValidationAttribute, применяемые к параметру Minimal API.
- Если тип параметра —
IEnumerable, проверьте тип для всех элементов, кромеnull. В противном случае проверьте тип значения.
Note
До выпуска .NET 11 существует известное ограничение, в котором типы значений null, объявленные как минимальные параметры API, не проверяются. Дополнительные сведения см. в разделе Атрибуты проверки игнорируются для типов значений, допускающих значение null, при передаче значения null (dotnet/aspnetcore #67033).
Проверка типов
Проверка типа является следующим шагом после проверки параметров (и является первым шагом в Blazor). Для этого необходимо выполнить следующие действия.
- Проверьте свойства типа. Если обнаружены ошибки, процесс проверки останавливается.
- Проверьте экземпляры на уровне типа ValidationAttribute. Если обнаружены ошибки, процесс проверки останавливается.
- Проверьте реализации IValidatableObject.
Проверка свойств
Проверка свойств выполняется как часть проверки типа, как описано в предыдущем разделе. Для этого необходимо выполнить следующие действия.
- Проверить экземпляры ValidationAttribute, примененные к свойству.
- Если значение свойства равно
IEnumerable, выполните проверку типа для всех элементов, кромеnull. В противном случае выполните однократную проверку типа для значения.
Явный пропуск проверки
При необходимости можно пропустить проверку для определенного параметра, типа или свойства, применяя его SkipValidationAttribute.
Принудительно создать сведения о типе, поддающемся проверке на корректность
Microsoft.Extensions.Validation работает через генератор исходного кода Roslyn, который определяет граф объектов и типы для параметров конечных точек Minimal API.
В некоторых случаях во время компиляции можно определить не все типы, которые являются частью графа объектов. В таких случаях можно заставить генератор исходного кода учитывать тип при проверке, применив ValidatableTypeAttribute к этому типу.
Поддержка асинхронной проверки
Microsoft.Extensions.Validation поддерживает асинхронную проверку. Пользовательские реализации AsyncValidationAttribute можно применять к параметрам, типам и свойствам, и они вызываются асинхронно. Кроме того, типы также могут реализовывать IAsyncValidatableObject.
При проверке свойств типа все задачи проверки запускаются одновременно. Аналогичным образом элементы коллекций IEnumerable проверяются одновременно.
IAsyncValidatableObject и AsyncValidationAttribute требуют синхронной и асинхронной логики валидации. Например, для объектов ValidateAsync, использующих этот интерфейс, должны быть реализованы методы Validate и IAsyncValidatableObject. Однако проверка никогда не вызывает оба метода. Если проверка вызывается через асинхронный путь кода, вызывается только ValidateAsync . Если проверка вызывается через синхронный путь кода, вызывается только Validate .
При валидации в Minimal API Microsoft.Extensions.Validation всегда использует асинхронный код и никогда — синхронный.
BlazorПроверка формы использует синхронный путь выполнения через метод EditContext.Validate, устаревший начиная с .NET 11.
Если реализация не поддерживает синхронный путь, вызовите InvalidOperationException.
В следующем примере показан класс проверки, реализующий IAsyncValidatableObject интерфейс. В следующем сценарии проверка требует асинхронного пути вызова для проверки базы данных допустимого имени пользователя электронной почты с помощью гипотетической IUserService службы. Поскольку в этом сценарии для проверки требуется асинхронный вызов базы данных, синхронный метод Validate, который предусмотрен контрактом интерфейса, не должен вызываться кодом разработчика в других местах и, если это всё же происходит, генерирует исключение InvalidOperationException.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
public class ValidateUser : IAsyncValidatableObject
{
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
// Asynchronous validation path
public async IAsyncEnumerable<ValidationResult> ValidateAsync(
ValidationContext validationContext,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var userService = validationContext.GetService<IUserService>();
if (userService is not null)
{
// Asynchronous call that checks a database via a service
if (await userService.IsEmailExistsAsync(Email, cancellationToken))
{
yield return new ValidationResult(
"Email is already registered.", new[] { nameof(Email) });
}
}
}
// Synchronous validation path that throws InvalidOperationException
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
throw new InvalidOperationException("Synchronous validation isn't supported.");
}
}
Дополнительные ресурсы
ASP.NET Core