@Guy, I have a concrete "Api" class with a number of operation methods, all of which return Task<TResult>. The TResults are all "resource" classes, essentially DTOs. (My media type formatters export these resources in XML and JSON form,
but that's another story).
The Api class has an injected back-end service dependency, of type IService. This is where the interface aspect comes in. In production (i.e. in the integration case, not in the unit testing case), the binding of IService to the class that implements
it is done via Ninject. Ninject is set up in my MVC host's Global.asax.
The operation methods in the Api class are very, very thin. They basically call the corresponding methods in the IService interface (asynchronously). The Api class deals with HTTP responses, status codes, etc. IService and its implementation
do not know about these things: e.g. they return errors in the form of thrown .NET exceptions, which the Api class catches and deals with.
IService and the resource DTOs are defined in a separate assembly from the frontend Api class. The backend implementation of IService is in yet another assembly (plus I have a TestData assembly for implementing IService for test-harness data).
I think that this is a good separation of concerns. It's good enough for my needs.
So... you can separate out concerns using interfaces, but it's up to you to design your code this way. WCF Web API isn't going to impose this sort of thing on you. And for simplicity's sake, you probably won't see code samples from the WCF Web
API team that go to the above lengths.