3

I have a large WebApi project with a few dozen controllers. Each controller represents an endpoint prefix, just as a normal MVC project would. For example:

CarsController.cs represents http://api.example.com/api/Cars

In the above example, the first role of that controller is to provide CRUD actions for the Car entity. As the application has grown, we find that for a car with a given ID, we might want to operate on it's AccidentHistory like such:

http://api.example.com/api/Cars/77/AccidentHistory

Now, this endpoint serves as CRUD actions for the accident history of car with ID 77. This can go on for any arbitrary number of levels. The hierarchy of REST endpoints is great, everyone loves it. But this poses a problem in the world of MVC-based routing. We like to have a [Entity]Controller.cs for each top-level entity. Each descended entity must then reside within it's greatest ancestor's controller file. So far, we've been giving each descendant entity their own #Region inside Visual Studio, but it doesn't feel like a good solution.

My first idea was to move each sub-entity's actions into a partial class. For example:

CarsController.AccidentHistory.cs would contain the actions for the previous example's endpoint.

This seems like a good idea, but there are many people in the community who believe that using partial classes is a huge code smell, and are quick to point out that partials were implemented as a work-around for WinForms classes that were auto-generated, but needed to be edited by the developer.

Another nail in the partial class coffin, for me at least, is that we're using CodeDom to generate TypeScript methods for each top-level endpoint, so there's one class in TypeScript that can be used to access all actions for a given endpoint. With the partial class approach, there are major problems getting generation to do what we want. (Seeing as all partials appear as their full implementation, you get duplicate class definitions generated in multiple files.

So, is there a better way to organize controller code for RESTful API routes in WebApi? One where we can quickly know where the code for a given endpoint is based simply on URL and method? Without having one controller per entity? Thoughts?

  • I may be way off base, and am surely rusty/noobie with asp.net, but it seems I remember seeing something related to this. It sounds like you need a server script to handle responses to url patterns. This may not be what you want, but maybe will point you in the right direction. – Nolo Sep 13 '16 at 6:59
  • 1
    I suspect you could handle this with a custom router that, for example, turned http://api.example.com/api/Cars/77/AccidentHistory into a call into a CarsAccidentHistoryController.Index(77) call. You'd be far better off asking on Stack Overflow though, as there's plenty of folk there that can likely give you a proper answer on how to do this. – David Arno Sep 13 '16 at 8:14
  • Have you got an answer on this from SO? I was not able to locate a similar question. – MichelZ Feb 12 '18 at 17:03
  • Do not be deterred by blanket rules such as avoiding partials. If it works for you it's good. – usr May 22 '18 at 12:06
3

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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