You must not throw an exception if the result is not found, or if there is something with the data which is caused by some validation rules (active status for example). Without proper documentation, the consumer does not know which exception
to catch, and if they catch wrong exception (especially the general Exception
) they will dangers their system more.
There is exception though, if the the service and consumer made some agreement which exception will be thrown or handler from the service beforehand.
If you have the luxury of changing the DTO structure and the way they consume, I would suggest you to have a generic basic structure
which can determine the result. Such as (in C#):
public class GenericQueryResult<T>{
public string OperationMessage{ get; set; }
public bool HasValue{ get; set; }
public T Value{ get; set; } // or Result is fine
}
This way the consumer can understand without any documentation that the result from service will return an object which will never null
(you don't return null GenericQueryResult
object). The desired object, however, can be null because it has an HasValue
property to decide whether it is null or not, and the cause of result is known (by OperationMessage
).
Do not return a collection if you intend to return just one. It will confuse the consumer that they will think the method can return more than one result (so the duplicated data may be a correct case).
Also do not return empty object (null object pattern). Again it will confuse the consumer to decide whether the result is found or not.
If you do not have the luxury of changing the return value, just return null
and let the consumer handle it. Just make sure you document it in your code.
The way you handle the generic result with Collections
or arrays may be different though.
See Eric Lippert's article for vexing exception
.
EDIT:
Based on your design, I am unsure why you need the Response
to be different entity with DtoBase
and use Composition
. I think it is natural for the Response
to inherit DtoBase
since DtoBase
is actually just a response (unless it also has a Request
).
Second, currently you can use the BusinessWarnings
as the information to the user about the not found reason. I myself prefer to change it to OperationMessage
having status of Success
, Error
and Warning
(and maybe Logging
) instead of just warning. Later on for easier access you can expose the Messages
as SuccessMessages
, ErrorMessages
and WarningMessages
. This can be treated as client-side logging and has more usage rather than just BusinessWarnings
.
Moreover I think you will get better response if you posted your code to code review stack exchange.