ASP.NET Core - Validate that only one parameter is specified in contract

232 views Asked by At

I have the following contract:

public class UpdateUserRequest
{
    public string Id { get; set; }
    public string Email { get; set; }
    public string AccountId { get; set; }
}

I want to validate that only one update property of the three is set in this request. I used IValidtableObject to achieve this:

public class UpdateUserRequest : IValidatableObject
{
    public string Id { get; set; }
    public string Email { get; set; }
    public string AccountId { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if ((Id is null && Email is null && AccountId is null) || 
                (Id is not null && Email is not null && AccountId is not null))
            {
                yield return new ValidationResult("Exactly one parameter must be specified.",
                    new[] { nameof(Id), nameof(Email), nameof(AccountId) });
            }
        }
}

That works in stopping cases where all three are supplied or none. But what do I do if two are supplied? Is there an easier way to achieve validation that only one parameter is supplied, instead of multiple if checks?

1

There are 1 answers

1
Neil W On

Simplest way is to just count them:

if (((Id == default ? 0 : 1) 
    + (Email == default ? 0 : 1)
    + (AccountId == default ? 0 : 1)) != 1)
{
    yield return new ValidationResult(
        "Exactly one parameter must be specified.",
        new[] { nameof(Id), nameof(Email), nameof(AccountId) });
}

You could generalise it with a utility method that uses reflection to enumerate the properties on the request object and returns a count of non-default properties, but seems a little heavy handed.