'Validation in Winform using Data Annotations

I create a validating class like so:

public interface IDataErrorInfo
{
    string this[string columnName] { get; }
    string Error { get; }
}

public class BaseModel : IDataErrorInfo
{
   [Browsable(false)]
   public string this[string property]
    {
        get
        {
            var propertyDescriptor = TypeDescriptor.GetProperties(this)[property];
            if (propertyDescriptor == null)
                return string.Empty;

            var results = new List<ValidationResult>();
            var result = Validator.TryValidateProperty(
                                      propertyDescriptor.GetValue(this),
                                      new ValidationContext(this, null, null)
                                      { MemberName = property },
                                      results);
            if (!result)
                return results.First().ErrorMessage;
            return string.Empty;
        }
    }

    [Browsable(false)]
    public string Error
    {
        get
        {
            var results = new List<ValidationResult>();
            var result = Validator.TryValidateObject(this,
                new ValidationContext(this, null, null), results, true);
            if (!result)
                return string.Join("\n", results.Select(x => x.ErrorMessage));
            else
                return null;
        }
    }
}

Then I created a class with data annotation like so

public class ReaderSetting : BaseModel
{
    [JsonPropertyName("RfidAddress")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "RFID Address is required.")]
    [StringLength(3, ErrorMessage = "Max Length is 3")]
    public string RfidAddress { get; set; }
}

Then I tried this out like this:

private void btnAddSetting_Click(object sender, EventArgs e)
{
    var readerSetting = new ReaderSetting();
    try
    {
        readerSetting.RfidAddress = txtRfidAddress.Text; // txtRfidAddress.Text is blank
    }
    catch (ValidationException ex)
    {
        Console.WriteLine(ex.Message);
    }
    _readerSettingList.Add(readerSetting);
    var source = new BindingSource();
    source.DataSource = _readerSettingList;
    dgRfidSettings.DataSource = source;
}

How come it doesn't pass through the ValidationException?



Solution 1:[1]

See if the following might work for you.

Try it out on .NET Fiddle.

public class ReaderSetting
{
    [JsonPropertyName("RfidAddress")]
    [Required(AllowEmptyStrings = false, ErrorMessage = "RFID Address is required.")]
    [StringLength(3, ErrorMessage = "Max Length is 3")]
    public string RfidAddress { get; set; }
}

public class EntityValidationResult
{
    public IList<ValidationResult> Errors { get; set; }
    public bool IsValid => Errors.Count == 0;
    public EntityValidationResult(IList<ValidationResult> errors = null)
    {
        Errors = errors ?? new List<ValidationResult>();
    }
}
public class EntityValidator<T> where T : class
{
    public EntityValidationResult Validate(T entity)
    {
        var validationResults = new List<ValidationResult>();
        var vc = new ValidationContext(entity, null, null);
        Validator.TryValidateObject(entity, vc, validationResults, true);

        return new EntityValidationResult(validationResults);
    }
}

Usage

ReaderSetting readerSetting = new() { RfidAddress = "abcd" };
EntityValidator<ReaderSetting> validator = new EntityValidator<ReaderSetting>();
EntityValidationResult result = validator.Validate(readerSetting);
if (result.IsValid)
{
    Console.WriteLine("Valid");
}
else
{
    result.Errors.ToList().ForEach(x => Console.WriteLine(x.ErrorMessage));
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Karen Payne