Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ValidatableModel should accept custom validation #12

Open
MartinJSoles opened this issue Dec 18, 2019 · 2 comments
Open

ValidatableModel should accept custom validation #12

MartinJSoles opened this issue Dec 18, 2019 · 2 comments
Labels
area-Waf Win Application Framework (WAF) enhancement

Comments

@MartinJSoles
Copy link

Let users inject an iValidator object in an alternate constructor that can perform the same operations as the ComponentModel.DataAnnotations.Validator class. This would allow someone to hook in some other validation framework such as FluentValidation. The default constructor could use a static implementation that simply delegates the validation methods to the DataAnnotations.Validator static methods.

    public interface IValidator
    {
        bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults);
        bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, bool validateAllProperties);
        bool TryValidateProperty(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults);
        bool TryValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes);
        void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext);
        void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, bool validateAllProperties);
        void ValidateProperty(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext);
        void ValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes);


    }

    public class DefaultValidator : IValidator
    {
        public bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults)
        {
            return Validator.TryValidateObject(instance, validationContext, validationResults);
        }

        public bool TryValidateObject(object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults, bool validateAllProperties)
        {
            return Validator.TryValidateObject(instance, validationContext, validationResults, validateAllProperties);
        }

        public bool TryValidateProperty(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults)
        {
            return Validator.TryValidateProperty(value, validationContext, validationResults);
        }

        public bool TryValidateValue(object value, ValidationContext validationContext, ICollection<ValidationResult> validationResults, IEnumerable<ValidationAttribute> validationAttributes)
        {
            return Validator.TryValidateValue(value, validationContext, validationResults, validationAttributes);
        }

        public void ValidateObject(object instance, ValidationContext validationContext)
        {
            Validator.ValidateObject(instance, validationContext);
        }

        public void ValidateObject(object instance, ValidationContext validationContext, bool validateAllProperties)
        {
            Validator.ValidateObject(instance, validationContext, validateAllProperties);
        }

        public void ValidateProperty(object value, ValidationContext validationContext)
        {
            Validator.ValidateProperty(value, validationContext);
        }

        public void ValidateValue(object value, ValidationContext validationContext, IEnumerable<ValidationAttribute> validationAttributes)
        {
            Validator.ValidateValue(value, validationContext, validationAttributes);
        }
    }

In the ValidatableModel class, make these additions / changes:

        private IValidator validator;
        private static DefaultValidator _defaultValidator = new DefaultValidator();

        public void ctor()
            {
            this.validator = _defaultValidator;
            }

        public void ctor(IValidator validator)
        {
            this.validator = validator;
        }

        public bool Validate()
        {
            var validationResults = new List<ValidationResult>();

            this.validator.TryValidateObject(this, new ValidationContext(this), validationResults, true);

            UpdateErrors(validationResults);

            return !HasErrors;
        }

This puts the onus on those of us that need to use an alternate validation framework to add a class that implements this new interface while still allowing for a default implementation that uses the built-in functionality.

@jbe2277
Copy link
Owner

jbe2277 commented Dec 20, 2019

Thanks for proposing you idea.

My design idea is that ValidatableModel provides a basic implementation of the INotifyDataErrorInfo interface for the .NET integrated DataAnnotations.Validator. I prefer to keep it that way just to keep it simple.

If any other validation framework is used then I recommend to use another base class. WAF does not require that you are using the base classes Model or ValidatableModel. Just implement INotifyDataErrorInfo yourself. Alternatively, the validation framework might provide an implementation for this interface.

@jbe2277 jbe2277 added area-Waf Win Application Framework (WAF) enhancement labels Dec 20, 2019
@MartinJSoles
Copy link
Author

I understand. It was just nice having everything baked into the base classes, similar to SetProperty and SetPropertyAndValidate. How about allowing the Validate method to be overridden? I was trying to avoid having to implement the INotidyDataErrorInfo and INotifyPropertyChanged in my own base model and then pull in everything that your framework class provides as niceties. But, I suppose that I can always redo it all in a custom implementation that just happens to follow yours. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Waf Win Application Framework (WAF) enhancement
Projects
None yet
Development

No branches or pull requests

2 participants