A custom validation attribute allows you to create metadata, that you can use in the data model to validate data fields. In order to validate when a collection is null or empty, you may create a custom validation attribute, which returns false in case the object is null or empty.

public class NotNullOrEmptyCollectionAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var collection = value as ICollection;
        if (collection != null)
        {
            return collection.Count != 0;
        }

        var enumerable = value as IEnumerable;
        return enumerable != null && enumerable.GetEnumerator().MoveNext();
    }
}

You can now decorate classes using this attribute, i.e.:

public class CustomModel
{
    [NotNullOrEmptyCollection]
    public IEnumerable<string> Recipients { get; set; }
}

Let’s assume that you have a WebAPI method `test/validation`, which:

  • accepts an input of our CustomModel object
  • returns this object if it’s valid
[AllowAnonymous, HttpPost, Route("validation")]
        public IHttpActionResult TestCustomValidation(CustomModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            return Ok(model);
        }

Responses on different input

Sending an empty object:

curl -X POST -H "Content-Type: application/json" -d '{}' "http://localhost:5000/api/test/validation"

Result:

{
  "message": "The request is invalid.",
  "modelState": {
    "model.Recipients": [
      "The field Recipients is invalid."
    ]
  }
}

Sending an object with an empty `recipients` array:

curl -X POST -H "Content-Type: application/json" -d '{
    "recipients": []
}' "http://localhost:5000/api/test/validation"

Result:

{
  "message": "The request is invalid.",
  "modelState": {
    "model.Recipients": [
      "The field Recipients is invalid."
    ]
  }
}

Sending an object with an item in `recipients` array:

curl -X POST -H "Content-Type: application/json" -d '{
    "recipients": ["test-recipient"]
}' "http://localhost:5000/api/test/validation"

Result:

{
  "recipients": [
    "test-recipient"
  ]
}

 

Categorized in:

Tagged in: