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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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.:
1 2 3 4 5 | 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
1 2 3 4 5 6 7 8 9 10 | [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:
1 | curl -X POST -H "Content-Type: application/json" -d '{}' "http://localhost:5000/api/test/validation" |
Result:
1 2 3 4 5 6 7 8 | { "message": "The request is invalid.", "modelState": { "model.Recipients": [ "The field Recipients is invalid." ] } } |
Sending an object with an empty recipients
array:
1 2 3 | curl -X POST -H "Content-Type: application/json" -d '{ "recipients": [] }' "http://localhost:5000/api/test/validation" |
Result:
1 2 3 4 5 6 7 8 | { "message": "The request is invalid.", "modelState": { "model.Recipients": [ "The field Recipients is invalid." ] } } |
Sending an object with an item in recipients
array:
1 2 3 | curl -X POST -H "Content-Type: application/json" -d '{ "recipients": ["test-recipient"] }' "http://localhost:5000/api/test/validation" |
Result:
1 2 3 4 5 | { "recipients": [ "test-recipient" ] } |