When creating a website my pattern often is the following:
- Controllers (application services)
- Services (domain services, infrastructure services)
- Repositories
Controllers talk to domain services or infrastructure services, and domain services may talk to repositories, infrastructure services will wrap things like smtp etc.
Currently I handle identity as an infrastructure service, if an infrastructure service or domain service needs to find out 'who the invoker is', it will request an identity service at construction, the identity service will have methods / properties to identity the invoker, this way I have for example, a HttpIdentityService, that determines the identity by session / cookie data.
However I'm a little stuck about how to handle results of service calls, for example.. I may have a service 'ArticleService', that has a method 'CreateComment' that simply takes a string comment text, and an identifier for the target Article.
My application service (controller), calls this service perhaps like so:
public ActionResult AddComment(int articleId)
{
string commentText = ...;
articleService.CreateComment(articleId, commentText);
...
}
However, this method may fail if the current identity isn't authorized, or doesn't pass policy that the ArticleService checks (such as being able to comment every 30 seconds perhaps), throwing and catching exceptions from service calls like this seems very wrong, because my calling code has no way of checking if it can actually invoke this action successfully (bar fatal app exceptions)..
So initially I started to make the services return a 'result', the result would be uniquely identifiable so the caller would know if the comment was indeed made (and additionally I would return the comment entity in the result), the results would also identify things like 'could not post as user is not authenticated', or 'could not post as specified cool-down period has not been respected' (I don't actually return strings but you get the idea).
My reasoning behind this is that the application service shouldn't be in control of if an action should invoke, imagine say I moved all of the user identity checks and everything out of the domain service and into the application service, I'd have tons of replicated code, as well as giving the application services completely power over what can happen..
I guess my question is basically, given that domain, infrastructure services will enforce additionally policy, what is the best way to inform the calling code the action did or didn't succeed, and why.
Thanks in advance, steve.