File: ModelBinding\ObjectModelValidator.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 Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
 
namespace Microsoft.AspNetCore.Mvc.ModelBinding;
 
/// <summary>
/// Provides a base <see cref="IObjectModelValidator"/> implementation for validating an object graph.
/// </summary>
public abstract class ObjectModelValidator : IObjectModelValidator
{
    private readonly IModelMetadataProvider _modelMetadataProvider;
    private readonly ValidatorCache _validatorCache;
    private readonly CompositeModelValidatorProvider _validatorProvider;
 
    /// <summary>
    /// Initializes a new instance of <see cref="ObjectModelValidator"/>.
    /// </summary>
    /// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
    /// <param name="validatorProviders">The list of <see cref="IModelValidatorProvider"/>.</param>
    public ObjectModelValidator(
        IModelMetadataProvider modelMetadataProvider,
        IList<IModelValidatorProvider> validatorProviders)
    {
        ArgumentNullException.ThrowIfNull(modelMetadataProvider);
        ArgumentNullException.ThrowIfNull(validatorProviders);
 
        _modelMetadataProvider = modelMetadataProvider;
        _validatorCache = new ValidatorCache();
 
        _validatorProvider = new CompositeModelValidatorProvider(validatorProviders);
    }
 
    /// <inheritdoc />
    public virtual void Validate(
        ActionContext actionContext,
        ValidationStateDictionary? validationState,
        string? prefix,
        object? model)
    {
        var visitor = GetValidationVisitor(
            actionContext,
            _validatorProvider,
            _validatorCache,
            _modelMetadataProvider,
            validationState);
 
        var metadata = model == null ? null : _modelMetadataProvider.GetMetadataForType(model.GetType());
        visitor.Validate(metadata, prefix, model, alwaysValidateAtTopLevel: false);
    }
 
    /// <summary>
    /// Validates the provided object model.
    /// If <paramref name="model"/> is <see langword="null"/> and the <paramref name="metadata"/>'s
    /// <see cref="ModelMetadata.IsRequired"/> is <see langword="true"/>, will add one or more
    /// model state errors that <see cref="Validate(ActionContext, ValidationStateDictionary, string, object)"/>
    /// would not.
    /// </summary>
    /// <param name="actionContext">The <see cref="ActionContext"/>.</param>
    /// <param name="validationState">The <see cref="ValidationStateDictionary"/>.</param>
    /// <param name="prefix">The model prefix key.</param>
    /// <param name="model">The model object.</param>
    /// <param name="metadata">The <see cref="ModelMetadata"/>.</param>
    public virtual void Validate(
        ActionContext actionContext,
        ValidationStateDictionary? validationState,
        string? prefix,
        object? model,
        ModelMetadata metadata)
        => Validate(actionContext, validationState, prefix, model, metadata, container: null);
 
    /// <summary>
    /// Validates the provided object model.
    /// If <paramref name="model"/> is <see langword="null"/> and the <paramref name="metadata"/>'s
    /// <see cref="ModelMetadata.IsRequired"/> is <see langword="true"/>, will add one or more
    /// model state errors that <see cref="Validate(ActionContext, ValidationStateDictionary, string, object)"/>
    /// would not.
    /// </summary>
    /// <param name="actionContext">The <see cref="ActionContext"/>.</param>
    /// <param name="validationState">The <see cref="ValidationStateDictionary"/>.</param>
    /// <param name="prefix">The model prefix key.</param>
    /// <param name="model">The model object.</param>
    /// <param name="metadata">The <see cref="ModelMetadata"/>.</param>
    /// <param name="container">The model container</param>
    public virtual void Validate(
        ActionContext actionContext,
        ValidationStateDictionary? validationState,
        string? prefix,
        object? model,
        ModelMetadata metadata,
        object? container)
    {
        var visitor = GetValidationVisitor(
            actionContext,
            _validatorProvider,
            _validatorCache,
            _modelMetadataProvider,
            validationState);
 
        visitor.Validate(metadata, prefix, model, alwaysValidateAtTopLevel: metadata.IsRequired, container);
    }
 
    /// <summary>
    /// Gets a <see cref="ValidationVisitor"/> that traverses the object model graph and performs validation.
    /// </summary>
    /// <param name="actionContext">The <see cref="ActionContext"/>.</param>
    /// <param name="validatorProvider">The <see cref="IModelValidatorProvider"/>.</param>
    /// <param name="validatorCache">The <see cref="ValidatorCache"/>.</param>
    /// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
    /// <param name="validationState">The <see cref="ValidationStateDictionary"/>.</param>
    /// <returns>A <see cref="ValidationVisitor"/> which traverses the object model graph.</returns>
    public abstract ValidationVisitor GetValidationVisitor(
        ActionContext actionContext,
        IModelValidatorProvider validatorProvider,
        ValidatorCache validatorCache,
        IModelMetadataProvider metadataProvider,
        ValidationStateDictionary? validationState);
}