0

I understand, this is how we develop our custom validation attribute in ASP.NET:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
public class GreaterThanZeroIntegerValidationAttribute : ValidationAttribute
{
    protected override ValidationResult? IsValid(Object? value, ValidationContext validationContext)
    {
        if (value is Int32 id && id > 0)
            return ValidationResult.Success;

        var memberNames = new List<String>{ validationContext.MemberName! };
        var errorMessage = String.Format("Invalid {0}.", validationContext.MemberName!);
        return new ValidationResult(errorMessage, memberNames);  //code in question
    }
}

In the code statement return new ValidationResult(errorMessage, memberNames);, I am passing a list of member names, even though it has only a single item.

I also, tried using this validation on 2 properties of a view-model:

public class OrderViewModel
{
    [GreaterThanZeroIntegerValidation]
    public Int32 Id { get; set; }

    [GreaterThanZeroIntegerValidation]
    public Int32 SomeOtherInt32Property { get; set; }

    //Other properties with different validation attributes
}

when the validation failed for both of them, this custom validation attribute was called twice, separately.

Here is the comment in the ValidationResult source code: This list of member names is meant to be used by presentation layers to indicate which fields are in error.

I understood the meaning of this statement but was unable to understand - why need a list of member names, when validation attribute is called every time for every property it is used on? Or I am interpreting the use of this parameter in a completely wrong way, I am not sure.

Question - What is the exact reason of having memberNames parameter of public ValidationResult(string? errorMessage, IEnumerable<string>? memberNames) as collection type and not singular/non-collection? Also, if possible, please provide a real world scenario that am I missing here.

phougatv
  • 881
  • 2
  • 12
  • 29
  • 1
    I usually use FluentValidation myself, but I wonder if perhaps there can be dependencies between properties (e.g. Id > SomeOtherInt32Property, etc.)? – ProgrammingLlama May 30 '23 at 05:48
  • @ProgrammingLlama so, if 2 properties of a class are related in some way, then we can have multiple member names in the validation attribute? – phougatv May 30 '23 at 05:53
  • Wouldn't it be useful in something like the CompareAttribute? https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.compareattribute?view=net-7.0 – nikstra May 30 '23 at 06:02
  • @nikstra not sure, never used the `CompareAttribute`, but will surely look into it. – phougatv May 30 '23 at 06:04
  • Because you can create a `ValidationAttribute` for a class and validate multiple members at once. – Alberto Jun 05 '23 at 09:40

1 Answers1

-1

The memberNames parameter in the ValidationResult constructor is designed to handle scenarios where a validation error is not specific to a single member but may apply to multiple members of an object. It allows you to indicate which members are in error when returning a ValidationResult object.

While a validation attribute is called for each property it is applied to, there are cases where a validation error may span across multiple properties. For example, imagine a scenario where you have a form with multiple fields, and you want to validate a combination of values across those fields. In such cases, you can use the memberNames parameter to indicate that the error is not specific to a single property but applies to multiple properties.

Here's an example to illustrate this:

public class CustomValidationAttribute : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        // Check if the values of two properties are valid together
        var property1Value = ...; // Get the value of property 1
        var property2Value = ...; // Get the value of property 2

        if (!IsValidCombination(property1Value, property2Value))
        {
            var memberNames = new[] { "Property1", "Property2" };
            return new ValidationResult("Invalid combination of values.", memberNames);
        }

        return ValidationResult.Success;
    }
}

In this example, the CustomValidationAttribute validates a combination of values from two properties (Property1 and Property2). If the combination is invalid, it creates a ValidationResult object with an error message and provides the names of both properties in the memberNames parameter.

Krishna Varma
  • 4,238
  • 2
  • 10
  • 25
  • 3
    It's really sad that AI generated answers have flooded SO recently. It's even more sad that such answers are sometimes accepted. And it's just simply mean and unfair that you committed it under a question with a bounty... :( – György Kőszeg Jun 05 '23 at 18:32