24
votes

I just started learning about ASP.NET Web API and I have several things that are still unclear to me:

  • why should I use EntitySetController,which inherits from odata controller instead of ApiController
  • Why is EF frequently mentioned in the context of OData. I know it "represents" an Entity, but I don't see why the 2 are connected. The first is on Service Layer and EF is Model.
  • I have read and understood a lot of litereture written about the subject, yes I missed when its the best practice

Thanks a lot, David

2
This is not opinion-based. It didn't even smell like an opinion-based question. Can people voting to close do this: close after diverging opinions become apparent in the answers.Luke Puplett
This is an excellent question and it is NOT opinion-based in the slightest.David Tansey

2 Answers

44
votes

why should I use EntitySetController,which inherits from odata controller instead of ApiController

  • I agree that it is confusing and that documentation seems to be lacking (at least when I had the same question as you). The way I put my feelings at ease was by simply reading the code. I encourage you to do the same, as it really is very short (concentrate on the EntitySetController class and its helpers); shouldn't take more than 5-10 minutes tops (promise) and you won't have any questions after.

    The short story is that it eliminates some boilerplate for the common cases (but continue reading if you want more context and an opinion).

Why is EF frequently mentioned in the context of OData. I know it "represents" an Entity, but I don't see why the 2 are connected. The first is on Service Layer and EF is Model.

  • This one confused me endlessly too, until I gave up and looked at the origins of OData, the WCF Data Services (previously ADO.NET Data Services) and the OData specifications (the hint was that OData Core protocol versions are still specified with a header called "DataServicesVersion"). There you can find that OData uses EDM, the Entity Data Model, which is the same model specification used by EF, and serializes it in the same format as EF: CSDL (Conceptual Schema Definition Language). This is no coincidence, WCF Data Services has prime support for EF, and although it doesn't require it, one could say that its design was based on it.

    Note that WCF Data Services is still was the flagship implementation of OData.

Something that is potentially of high interest (at least it was to me): When using EF with ASP.NET Web API and OData extensions, there is no way (as far as I know) to share the model between the two.

You may skip to the next bullet point for the next answer if you didn't find this interesting.

For example, when using EF in a Code-First setup, you will typically build your model based largely on code conventions and the EF System.Data.Entity.DbModelBuilder ("fluid API"). You will then use the System.Web.Http.OData.Builder.ODataConventionModelBuilder that will do pretty much exactly the same thing to construct the OData model, and arrive pretty much at exactly the same result. In the past, I managed to dig up some random notes from a random meeting from either the EF team or the Web API team which mentioned this briefly, and as far as I can remember (I can't find this document anymore), there were no plans to improve the situation. Thus, they now have two different and incompatible implementations of EDM.

I admit I didn't take the time to go through the code extensively to verify this properly, but I know that Web API + OData extensions depend on EdmLib (which provides Microsoft.Data.Edm initially developed for WCF Data Services), while EF does not, and instead uses its own System.Data.Entity.Edm implementation. I also know that their convention-based model builders are different, as explained above. It becomes ridiculous when you use EF in a DB-First setup; you get a serialized EDM model in CSDL format in the EDMX file, and the OData extensions go on and generate their own serialized CSDL code at runtime from the CLR code (using separate code conventions) itself generated by EF from the initial CSDL via T4 templates. Your head spin much?


Update: This was largely improved a little under two weeks ago (July 19th), sorry I missed that. (Thanks RaghuRam Nadiminti.) I didn't reviewed the patch, but from the sample code it seems that the way it works is that one must serialize the model into CSDL using the EF EDMX serializer, then deserialize it using the EdmLib parser to be used by the OData extensions. It still feels a little bit like a hack in EF Code-First setups (at least the CLR code is only analyzed once, but I would prefer it if both components used the same in-memory model to begin with). A shortcut can probably be taken when using Model-First or Database-First scenarios however, by deserializing the EDMX file generated by VS directly. In this last scenario it actually feels less like a hack, but again, a single model would be best. I don't know that either EF would possibly switch to using EdmLib or that EdmLib would switch to using EF's EDM model, both projects are really strong now, and the blockers are probably not just technical issues. The ASP.NET team unfortunately can't do much about it AFAICT.



Update: Randomly stumbled upon those meeting notes again. They were indeed from the EF team and indicate that they don't plan to work on EdmLib.


However, I now believe this is all a good thing. The reason is that if they close all the gaps, and remove all the boilerplate, and make everything right, they'll essentially end up where WCF Data Services are, which is a fully integrated solution where the programmer injects code in the pipeline via "Interceptors". To me, the only reason to go there is because of open source requirements, but even then, I think it's more reasonable to try and advocate for an open source WCF-DS instead.

The question now becomes: "But what is Web API + OData extensions good for, then?". Well, it's a good fit when you really do want two different models for your data store and your web service. It's a good fit when the "interceptor" design is not flexible enough for you to translate between the two models.


Update: As of March 27th 2014, it's official, they are going to try to close those gaps, deprecating WCF Data Services in the process. Very early talks mention a "handler" to do this, most likely an ASP.NET HTTP handler (see comments on the announcement). It looks like very little planning has gone into this, as they're still brainstorming ideas to make ASP.NET Web API fill the use-cases of WCF Data Services. I mentioned those use-cases above, in a comment to the announcement and in this thread (started a few days before the announcement).

Many other people expressed close to identical concerns (again, see linked discussions), so it's good to see that I haven't been dreaming all this up.

There is some disbelief that ASP.NET Web API can be turned into something useful for the Data Services use-cases in a reasonable time, so some people suggested that MSFT reconsider their decision. The question of whether to use ASP.NET for open source requirements is also moot: WCF Data Services will soon be open-sourced if all goes "well", though not thanks to any advocacy efforts. (It's just a source dump, it's unknown if anyone would maintain it at this point.)

From what I can gather, everything points to a budget cut, and some people talk about it being the result of a company-wide "refocusing", though all of this should be taken with a grain of salt.

These things aside, there is now a possibility that with time, a new solution emerges -- even better that WCF Data Services or Web API when it comes to OData APIs. Although it looks a bit chaotic right now, the MSFT OData team did receive quite a bit of feedback from its customers relatively early, so there's hope (especially if the future solution, should there be one, is itself open-sourced). The transition is probably going to be painful, but be sure to watch discussions around this in the future.

I'm not sure I'll take the time to update this post anymore; I just wanted to highlight that things regarding Web API and Data Services are about to change a lot, since this answer is still being upvoted from time to time.



Update: RESTier (announcement) seems to be the result.


And finally, my (personal) opinion: OData, despite being technically a RESTful HTTP-based protocol, is very, very, very data-oriented. This is absolutely fine (we can define a lot different types of interfaces with HTTP) and I, for one, find all the ServiceStack vs OData debates irrelevant (I believe they operate at different layers in our current, common architectures). What I find worrying is people trying to make an OData-based API act like a behavior-centric (or "process-oriented", or "ServiceStack"-like) API. To me, OData URI conventions and resource representation formats (Atom and JSON) together replace SQL, WCF Data Services "Query Interceptors" and "Change Interceptors" replace DBMS triggers and OData Actions replace DBMS stored procedures. With this perspective, you immediately see that if the domain logic you need to put behind your OData API is too complex or not very data-oriented, you're gonna end up with convoluted "Actions" that don't respect REST principles, and entities that don't feel right. If you treat your OData API as a pure data layer, you're fine. You can stack a service on top of it just like you would put a "service layer" on top of a SQL database.

And thus, I'm not sure Web API + OData extensions is that great anymore. If you need fundamentally different models, it's likely that your application isn't too data-oriented (except if you're simply merging models from various sources or something), and OData is thus not a good fit. This is a sign you should at least consider Web API alone (with either SQL or OData below) or something like ServiceStack.

For better or for worse, Javascript clients can't talk SQL to a remote server. Maybe in the future via browser APIs, or maybe via variants of WebSockets, but right now, OData is the closest thing to a remote data layer anyone is going to get for rich JS clients that have thin or no server-side logic. OData is used by other types of clients of course, but I would say that it's especially useful on the client-side web platform, where things like Breeze.js or JayData are to OData what the Entity Framework is to SQL.

I have read and understood a lot of litereture written about the subject, yes I missed when its the best practice

  • Don't worry, I looked around, but I don't think anybody really knows what they're doing. Just pretend like everybody else while you make sense of this mess.
0
votes

Use EntitySetController if you want to create an OData endpoint. Use ApiController if you want to return generic JSON or XML, or some other format (e.g., using a custom formatter).

In Web API, EF and OData are not necessarily connected. You can write an OData endpoint that does not use EF. A lot of the Web API tutorials use EF, because EF code-first is relatively easy to show in a tutorial. :-)