简体   繁体   中英

How to prevent the repetition of the same error message text when validating using DataAnnotations in C#?

I'm developing an application where I use DataAnnotations to validate the values passed to the class properties. As I have several different classes with many properties that have similar validation rules, I would like to define for the ErrorMessage argument a method that returns a formatted string. The problem is that when I use this method in the validation attribute I get the following error:

“An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type PrototypeValidationData”

Reading this post I understood that the attribute doesn't support a method as argument, but I would like to know if there is any way of preventing to repeat the same error message in all the properties definitions. Is there any alternative?

Follows an example of what I'm trying to do:

    public class Foo
    {
        public string Id { get; set; }

        [Range(double.Epsilon, double.MaxValue, ErrorMessage = ErrorMessages.MustBeGreaterThanZero(Bar.ToString(), "Foo", Id, "Bar"))]
        public double Bar { get; set; }
    }

    public static class ErrorMessages
    {
        public static string MustBeGreaterThanZero(string str,
                                                   string senderClass,
                                                   string senderId,
                                                   string senderField)
        {
            return String.Format("The value {0} assigned to the field {1} in {2} ID {3} must be greater than ZERO.",
                                 str, senderField, senderClass, senderId);
        }

You can create custom Validation attibute inherited from RangeAttribute .

public class RangeCustomAttribute : System.ComponentModel.DataAnnotations.RangeAttribute
{
    public RangeCustomAttribute(double minimum, 
                                double maximum,
                                string senderClass,
                                string senderId,
                                string senderField) : base(minimum, maximum)
    {
        SenderClass = senderClass;
        SenderId = senderId;
        SenderField = senderField;
    }

    public string SenderClass { get; }
    public string SenderId { get; }
    public string SenderField { get; }

    protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
    {
        var result = base.IsValid(value, validationContext);

        if (result != ValidationResult.Success)
        {
            var instance = validationContext.ObjectInstance;
            Type type = instance.GetType();

            var idValue = type.GetProperty(SenderId)?.GetValue(instance, null);

            var err = $"The value {value} assigned to the field {SenderField} in {SenderClass} ID {idValue} must be greater than ZERO.";

            result = new ValidationResult(err, new List<string> { validationContext.DisplayName });
        }

        return result;
    }
}

By the way SenderClass and SenderField can be read from reflection, so you perhaps this parameter is redurant. Like this:

public class RangeCustom2Attribute : System.ComponentModel.DataAnnotations.RangeAttribute
{
    public RangeCustom2Attribute(double minimum,
                                double maximum,
                                string senderId) : base(minimum, maximum)
    {
        SenderId = senderId;
    }

    public string SenderId { get; }

    protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
    {
        var result = base.IsValid(value, validationContext);

        if (result != ValidationResult.Success)
        {
            var instance = validationContext.ObjectInstance;
            Type type = instance.GetType();

            var senderClass = type.Name;

            var senderField = validationContext.MemberName;

            var idValue = type.GetProperty(SenderId)?.GetValue(instance, null);

            var err = $"The value {value} assigned to the field {senderField} in {senderClass} ID {idValue} must be greater than ZERO.";

            result = new ValidationResult(err, new List<string> { validationContext.DisplayName });
        }

        return result;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM