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" ] }