ASP.NET 4.5 has three different class which we can inherits to implements the controllers: Controller, ApiController and ODataController.
In the latest applications that I implemented, because they were SPA, I used rarely the classic Controller (know as MVC controllers) and I developed a huge number of ApiController and ODataController.
The first ones are used to implements the WEB APIs and the second ones if we want a controller that implements OData protocol.
In this post I want to talk about the main architectural differences between these two typologies and the different behaviour inside the source code.
The first difference between them is that the ODataController class has the ApiExplorer setting IgnoreApi=true; this is useful to disable the inspection and don’t retrieve the list of the action to the clients that request it:
[ApiExplorerSettings(IgnoreApi = true)]
This is correct when we talk about of libraries like Swagger, that inspect the entire list of the Web APIs in the application and exposes the documentation about those.
With this default setting, the program by default won’t show the documentation for these controllers.
All the OData Controllers has a custom ODataFormattingAttribute applied by default.
This attribute deal with the parsing of the url parameters and send the results in the correct format.
For example, it’s able to parse the OData $format query option (used to specify the format of the results), format the results like xml, json or raw as well as read the OData Metadata header parameter in the request and define the data to be send.
This attribute override the default action value binder with a PerRequestActionValueBinder and the default negotiator with a PerRequestContentNegotiator as well; these actions have a specific action selector for the OData requests and a negotiator that uses a per-request formatter for the content negotiation.
This selector retrieves the path of the request by using a class ODataPath, that represents the path with additional informations about the Edm type and the entity set.
It retrieves the odata routing conventions from the request as well.
Then, with the path and the conventions it retrieves the action to execute in the controller context.
The last duty is instantiate an ODataProviderValueFactory, a custom class that extendes the ProviderValueFactory that parse and retrieves the routing conventions from the OData url.
The last two stuff added to the ODataController are two methods that send the results to the client.
These methods uses a CreatedODataResult class that format the response according with the OData standards.
Then the header with the location informations is added and the content with the informations about EntitySet, Model, Url is created.