2

I have a .net core api trying to implement it according to domain drive design principles.

In the domain layer there is a public Create method that contains all validation and business rules. If one fails it will throw an exception. So basically you can not create an invalid entity or an invalid value type. For example:

public class Adult
{
   private Adult(string name,int age)
   {
       this.Name = name;
       this.Age = age;
   }

   public string Name { get; }

   public int Age { get; }

   public static Adult Create(string name, int age)
   {
      if (string.IsNullOrWhiteSpace(name))
          throw new ArgumentException(nameof(name));

      if (age < 18)
         throw new ArgumentException("age should not be less that 18");

     return new Adult(name, age);
 }

}

In the web layer my web dtos have the basic validation attributes. For example:

public class AdultWebDto
{
   [Required]
   public string Name {get; set; }

   public int Age {get; set; }
}

So basically if the user tries to create an adult with no name it will return a 400 Error but if he tries to create a user with an age less than 18 it will pass the dto validation and will return a 500 Error.

Of course if the user requests an Adult with either invalid name or invalid age it will return a 500 error since the data coming from the repository were invalid.

Is what I am doing right? So for simple validation rules to check that in the web layer and return a 400 error but in case of more complicated business rules to return a 500 error?

1

3 Answers 3

4

Is what I am doing right? So for simple validation rules to check that in the web layer and return a 400 error but in case of more complicated business rules to return a 500 error?

Probably not. See RFC 7231

The 4xx (Client Error) class of status code indicates that the client seems to have erred.

In your case, the client error is that it sent a message for something that it is not allowed to do right now.

Your basic "You aren't allowed to do that" status code is 403 Forbidden

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it.

In this case, you might be better served by 409 Conflict

The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request.

I can't think of any cases where 5xx makes sense for a domain error.

2
  • But what about in case that the data that coming from the database is corrupted in a GET request should I return 200 as @slepic says?
    – Stam
    Feb 15, 2020 at 16:35
  • @Stam you definitely should. Your database being corrupted is not the client's fault. If you fail to handle it the client Will probably get a 5xx but that only confirm that the server Is malfunctioning. Dont worry if client gets data that He wont be able to successfuly post back. It Will Force him to correct the data to fit new validation rules if He want to make any update. And if IT matters you really should create db migration that Will make sure no existing data will be in invalid state according to new validation rules.
    – slepic
    Feb 15, 2020 at 19:51
1

So basically if the user tries to create an adult with no name it will return a 400 Error but if he tries to create a user with an age less than 18 pass the dto validation and will return a 500 Error.

Such validation shouldn't be handled at the transprt layer (HTTP in this case) at all. You should shift such error messages to your API protocol (the payload).

Is what I am doing right? So for simple validation rules to check that in the web layer and return a 400 error but in case of more complicated business rules to return a 500 error?

Nope, that's fundamentally wrong.
The definition of your API protocol should include error responses, and these be presented in a concise manner for any requests.
Invalid data input isn't a failure at the transport level, but API specific.

1

5xx family codes are server errors. They imply server or transport layer malfunction. 4xx codes mean client did something wrong and the server refuses to process his request. None of the cases you described fit the 5xx code family.

You should not disallow your Adult class to contain invalid age (actualy You dont need two classes for this) . But rather make sure that such entity does not make it to the persistence layer (possibly a separate validator class between the controller And repository). Responding 400 (or other 4xx code) with some errors in the response body (maybe json) in such cases.

Likewise if the validation rules change in a way that existing entities becomes invalid (no migration was implemented). A GET request for them should not be influenced and return 200.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.