2
votes

I'm currently in the early stages of building a RESTful API and have been going back and forth on the correct way to handle business rule validation.

I am using Web API 2 and currently use IValidatableObject to handle validating the model. If, for example, a required field is missing, I am returning "400 Bad Request" and the ModelState.

I began to add business rule validation to IValidatableObject's Public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) method and continued to return "400 Bad Request" with a message describing the business rule that didn't pass validation. Then I took a step back and thought "Business rules are different from model validation, the request is perfectly valid, and I should not be returning 400."

Now I plan on moving the business rule validation out of model validation and into domain logic. This has left me thinking about how I should return not only the correct status code but how the client will determine the proper message to display.

I'm torn between 403 Forbidden and 422 Unprocessable Entity, leaning toward 422. Any suggestions welcome.

Now let us say that I make a request that fails multiple business rules, and I return a 422 and a collection of error messages. I want the client to be able to understand the error and present the message how they see fit, not just display the message in my response.

  1. Which HTTP status code is most appropriate for failed business?
  2. What is the best practice around returning error messages?

Is it acceptable to return 422.x and document each .x, so the client knows what to do? That seems to leave me with the limitation of only returning one error per request.

Should I define Error codes and return them with the error message? For example:

{
  "Errors": [
    { "Error": { "Code": "E0001", "Message": "You failed business rule 1" } },
    { "Error": { "Code": "E0002", "Message": "You failed business rule 2" } }
   ]  
}

Any feedback would be awesome! Thanks!

1

1 Answers

2
votes

Take a look at this answer here

I wouldn't send a 403 because your case has nothing to do with authorization.

I would send 400 if your model came back as null. i.e the model binder doesn't know what to do with what you posted.

Send the status as 422 with the errors as content.