File: ModelBinding\Metadata\HasValidatorsValidationMetadataProvider.cs
Web Access
Project: src\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable enable
 
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
 
namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
 
internal sealed class HasValidatorsValidationMetadataProvider : IValidationMetadataProvider
{
    private readonly bool _hasOnlyMetadataBasedValidators;
    private readonly IMetadataBasedModelValidatorProvider[]? _validatorProviders;
 
    public HasValidatorsValidationMetadataProvider(IList<IModelValidatorProvider> modelValidatorProviders)
    {
        if (modelValidatorProviders.Count > 0 && modelValidatorProviders.All(p => p is IMetadataBasedModelValidatorProvider))
        {
            _hasOnlyMetadataBasedValidators = true;
            _validatorProviders = modelValidatorProviders.Cast<IMetadataBasedModelValidatorProvider>().ToArray();
        }
    }
 
    public void CreateValidationMetadata(ValidationMetadataProviderContext context)
    {
        ArgumentNullException.ThrowIfNull(context);
 
        if (!_hasOnlyMetadataBasedValidators)
        {
            return;
        }
 
        for (var i = 0; i < _validatorProviders!.Length; i++)
        {
            var provider = _validatorProviders[i];
            if (provider.HasValidators(context.Key.ModelType, context.ValidationMetadata.ValidatorMetadata))
            {
                context.ValidationMetadata.HasValidators = true;
 
                if (context.Key.MetadataKind == ModelMetadataKind.Property)
                {
                    // For properties, additionally determine that if there's validators defined exclusively
                    // from property attributes. This is later used to produce a error for record types
                    // where a record type property that is bound as a parameter defines validation attributes.
 
                    if (context.PropertyAttributes is not IList<object> propertyAttributes)
                    {
                        propertyAttributes = context.PropertyAttributes!.ToList();
                    }
 
                    if (provider.HasValidators(typeof(object), propertyAttributes))
                    {
                        context.ValidationMetadata.PropertyHasValidators = true;
                    }
                }
            }
        }
 
        if (context.ValidationMetadata.HasValidators == null)
        {
            context.ValidationMetadata.HasValidators = false;
        }
    }
}