How large is your application? There's a good chance you're overthinking this. Unless the application is a large, enterprise-grade application, the high degree of loose coupling you are advocating is probably unnecessary.
If you decide that this level of loose coupling is still necessary, create a service layer that returns "service" objects. This fulfills a similar function to View Models in MVC. You will then write code in your service layer that maps objects from your domain model to your service model.
Note that part of your struggle may be due to the fact that, while your Data Repository is returning CRUD objects, your Service Layer should be returning the result of actions. For example:
public InvoiceView GetInvoice(int invoiceID);
returns a InvoiceView
object containing whatever data you wish to expose to the public, including Name, Address, Line Items and so forth, from several different tables/objects in your domain.
public class InvoiceView
{
public int InvoiceID;
public Address ShippingAddress;
public Address BillingAddress;
public List<LineItem> LineItems;
...
}
Similarly, there will be Service Layer methods that simply performs an action and returns an object indicating the result of the action:
public TransactionResult Transfer(
int sourceAccountID, int targetAccountID, Money amount, ValidationToken token);
IMPORTANT: You'll never be able to completely decouple from your data. Your consumer will always have to have some knowledge of the data, even if it's just an object ID or UUID.
One of the benefits of the routing model in web api is that it allows you to completely separate the organisation of your URI structure from the underlying code layout. All the routing engine is doing is deciding which method to run based on some criteria (usually the URI / query string).
Given this, i would resist the temptation of allowing your code structure to be decided by your URI scheme. In my experience one of the best tests for how to arrange code is 'things that change together should live together', that is, if a group of classes tend to all change together for the development of a given feature, they should all be under the same organisational parent (namespace, usually). I dont know how mature your existing code base is, but it can be difficult to determine this without a lot of existing code / code history to investigate.
In your particular case, AccidentHistory
sounds like a completely different domain to Car
, i would move it out from under the car organisation structure.
Best Answer
Its fairly common to use a custom BaseController from which your other controllers inherit rather than Controller. I dont think there is any particular danger here.
However! I have to agree that its not good practice. Your approach suggests that you will go all the way down to generic repositories.
But at some point you are going to have to deal with differing business logic, or input parameters between the different controllers.
Rather than bury that conditional in the inheritance tree, its best to have it up front in your controller or service layer. (do you have a service layer?)
Alternatively if you really are just exposing a generic repo with identical methods, then you could do that in a single controller, parsing the type out of the route
When I say a single controller I mean something like...
That single controller and action is called for all your http://myapi/myresource/123