Pergunta

Summary of question: is it possible to clear the list of errors from the model state when a fluent validator is resolved for a particular model? That way fluent validation overrides the default behaviour in the data annotation model provider, rather than compliments it?

I am using fluent validation like this:

FluentValidationModelValidatorProvider.Configure(
    _ =>
        {
            // This does not seem to work, or i am misunderstanding it?
            _.AddImplicitRequiredValidator = false;
        });

I use autofac for a container, but fluent validation is not actually using the container yet. I have it configured as above.

I have a model like this:

[Validator(typeof(PartyModelValidator))]
public class PartyModel
{

The validator validates like this...

public class PartyModelValidator : AbstractValidator<PartyModel>
{
    /// <summary>
    /// Initialises a new instance of the <see cref="PartyModelValidator"/> class.
    /// </summary>
    public PartyModelValidator()
    {
        this.RuleFor(_ => _.Client)
            .SetValidator(new ClientValidator())
            .When(_ => _.SelectedPartyTab == PartyType.Person);
        this.RuleFor(_ => _.Organisation)
            .SetValidator(new OrganisationValidator())
            .When(_ => _.SelectedPartyTab == PartyType.Organisation);

The validation is working as it should, except that there are [Required] attributes on some of the person and organisation objects.

These [Required] attributes are appearing as validation errors. I get these errors even when the entire object is actually null.

How do I get fluent validation to ignore data annotation properties when a specific fluent validator is configured as above? I would prefer to leave the annotations on the objects, as they serve other purposes besides just view validation?

Foi útil?

Solução

This does the trick, in case anyone else needs the code, here it is.

/// <summary>
/// The fluent validation model validator provider ex.
/// </summary>
internal class FluentValidationModelValidatorProviderEx : FluentValidationModelValidatorProvider
{
    /// <summary>
    /// Initialises a new instance of the <see cref="FluentValidationModelValidatorProviderEx"/> class.
    /// </summary>
    /// <param name="validatorFactory">
    /// The validator factory.
    /// </param>
    public FluentValidationModelValidatorProviderEx(IValidatorFactory validatorFactory) : base(validatorFactory)
    {
    }

    /// <summary>
    /// get the fluent validators.
    /// </summary>
    /// <param name="metadata">The metadata.</param>
    /// <param name="context">The context.</param>
    /// <returns>the set of validators, if any validators are resolved.</returns>
    /// <remarks>If the fluent validator(s) are supplied, then clear the current set of model errors.</remarks>
    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
    {
        var validators = base.GetValidators(metadata, context);
        var modelValidators = validators as ModelValidator[] ?? validators.ToArray();
        if (modelValidators.Any())
            context.Controller.ViewData.ModelState.Clear();
        return modelValidators;
    }

    /// <summary>
    /// configure fluent validation.
    /// </summary>
    /// <param name="configurationExpression">The configuration expression.</param>
    internal static void ConfigureFluentValidation(Action<FluentValidationModelValidatorProvider> configurationExpression = null)
    {
        configurationExpression = configurationExpression ?? (Action<FluentValidationModelValidatorProvider>)(param0 => { });
        FluentValidationModelValidatorProvider validatorProvider = new FluentValidationModelValidatorProviderEx((IValidatorFactory)null);
        configurationExpression(validatorProvider);
        DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
        ModelValidatorProviders.Providers.Add((ModelValidatorProvider)validatorProvider);
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top