I have a lighweight setup where I am using Web API 2 with OData but do not create an "/odata" endpoint with its accompanying "/odata/$metadata" but instead just use standard ApiController's with attribute routing and Get methods marked with an override of [Queryable]: [InlineCountQueryable] detailed here Web API, OData, $inlinecount and testing.
It all works very well except that I can only expose dedicated model classes without any collections or object properties because the JSON serializer serializes the whole object graph. My ideal behavior would be to just have all collections ignored completely and object properties only included on $expand.
I believe this can be made to work because an OData Web Api 2 scaffold VS 2013 creates over an entity framework context has similar behavior, but I would like to keep this as lean as possible and avoid going that route as I found it to be a bit brittle and this service does not need to expose a $metadata description.
Update
I did some digging in the aspnet samples and found the "CustomODataFormatter" sample which seems to expose the machinery I would need to modify.. however the ODataSerializerProvider/ODataSerializer setup outlined there does not work with with attribute routing at all (any method defined with [Route("Some/Url")]).
Given that this seems to be what I need, does anyone know if attribute routing and the odata serializer provider mechanism should work together?
[JsonIgnore] or [DataMember] can be used to ignore properties for json.net serializer. webapi.odata 5.2 supports ODataRouteAttribute, an example is here.
Related
Assuming an application with a traditional UI based on Spring MVC and Thymeleaf, it seems like there are a few ways to expose a REST API...
Add a completely separate set of Controllers using #RestController - Feels like a lot of duplication, but allows complete separation of UI vs REST logic
Use a single Controller for each entity, with a mix of both #ResponseBody methods and ModelAndView methods - Keeps all logic for a given entity in a single place, but requires mixing different concepts
Use a single Controller for each entity, use only ModelAndView, and use content negotiation with a JSON view resolver like the MappingJackson2JsonView (https://spring.io/blog/2013/06/03/content-negotiation-using-views/)
I'm particularly interested in #3 as it feels similar to how Ruby on Rails Controllers work with the respond_to for different content types.
Is this a common approach / best-practice in Spring applications?
Would POST and DELETE requests still require separate methods since they may work differently between a REST API vs the UI? (i.e. posting a form vs posting a json entity)
Would it require separate Exception handling based on whether it was a UI request or API request?
I'd go with option 1. Having a separate set of #Controller and #RestController avoids mixing MVC pattern with your REST api. To avoid code duplication, you should add a service layer and have the REST endpoint and the MVC controller to make use of that service layer.
I'm attempting to use Swashbuckle to generate a swagger inteface for our API, we're returning HttpResponseMessage in our controller methods.
The docs indicate to use the [ResponseType(…)] attribute to indicate the actual return type. But that attribute is restricted to .net 4.5 (I believe, will gladly be proven wrong), and won't work in a .net4 project.
There are the XML comments, however I couldn't see how to use them the generate the schema information (I've taken a look through the unit tests in the project, but couldn't figure out if it's supported)
I have written a apicontroller class that supports ODATA by using the EnableQuery attribute on the methods and returning the data asQueryable. It alls works fine for me.
What use is the ODataConventionModelBuilder? Do I still need to use it?
The using of ODataConventionModelBuilder enables
The mapping from your POCO classes to the OData model including handling primitive types, complex types, entities types and relationships between them, actions, function, and so on.
It also helps validate if you have a correct OData model.
It helps set up the metadata document and service document.
If you really want to expose an OData service that conforms the OData protocol, you would need to do a lot yourselves without the ODataConventionModelBuilder. But if you don't care about things like conforming model conventions or exposing the service model to the service consumers, you may not use it.
I’m thinking of using OData for my web service (based on Web API). Unfortunately, my datasource is NOT IQueryable. Instead of implementing my own IQueryable I pretty much followed this blog post.
What I don’t understand is how to get to my entity data model (EDM)? Do I have to model an EDM for example in the Designer? Or is this for EF only and I can use „plain“ classes instead and set relation-attributes? I don’t want to expose my internal data structures therefore my EDM is more like DTOs...
In an example I’ve seen that I‘m supposed to derive from EntitySetController in order to get the OData-compliant HTTP response. I believe I can’t use EntitySetController as I don’t support IQueryable. What am I supposed to do in order to get a proper response anyway?
You can build an EDM model yourself. You can use the ODataConventionModelBuilder class to build your EDM model. This tutorial has some sample code.
Also, checkout the samples on OData from here, especially the ODataServiceSample and ODataCompositeKeySample. They should get you started.
Also, if you do not have an IQueryable, you could derive from ODataController instead of EntitySetController.
I will start to code a new Web application soon. The application will be built using ASP.Net MVC 3 and Entity Framework 4.1 (Database First approach). Instead of using the default EntityObject classes, I will create POCO classes using the ADO.NET POCO Entity Generator.
When I create POCOs using this tool, it automatically adds the Virtual keyword to all properties for change tracking and navigation properties for lazy loading.
I have however read and seen from demonstrations, that Julie Lerman (EF Guru!) seems to turn off lazy loading and also modifies her POCO template so that the Virtual keyword is removed from her POCO classes. Julie states the reason why she does this is because she is writing applications for WCF services and using the Virtual keyword with this causes a Serialization issue. She says, as an object is getting serialized, the serializer is touching the navigation properties which then triggers lazy loading, and before you know it you are pulling the whole database across the wire.
I think Julie was perhaps exagarating when she said this could pull the whole database across the wire, however, even so, this thought scares me!
My question is (finally), should I also remove the Virtual keyword from my POCO classes for my MVC application and use DectectChanges for my change tracking and Eager Loading to request navigation properties.
Your help with this would be greatly appreciated.
Thanks as ever.
Serialization can indeed trigger lazy loading because the getter of the navigation property doesn't have a way to detect if the caller is the serializer or user code.
This is not the only issue: whether you have virtual navigation properties or all properties as virtual EF will create a proxy type at runtime for your entities, therefore entity instances the serializer will have to deal with at runtime will typically be of a type different from the one you defined.
Julie's recommendations are the simplest and most reasonable way to deal with the issues, but if you still want to work with the capabilities of proxies most of the time and only sometimes serialize them with WCF, there are other workarounds available:
You can use a DataContractResolver to map the proxy types to be serialized as the original types
You can also turn off lazy loading only when you are about to serialize a graph
More details are contained in this blog post: http://blogs.msdn.com/b/adonet/archive/2010/01/05/poco-proxies-part-2-serializing-poco-proxies.aspx
Besides this, my recommendation would be that you use the DbContext template and not the POCO template. DbContext is the new API we released as part of EF 4.1 with the goal of providing greater productivity. It has several advantages like the fact that it will automatically perform DetectChanges so that you won't need in general to care about calling the method yourself. Also the POCO entities we generate for DbContext are simpler than the ones that we generate with the POCO templates. You should be able to find lots of MVC exampels using DbContext.
Well it depends on your need, if you are going to serialize your POCO classes than yes you should remove them (For example: when using WCF services or basically anything that will serialize your entire object). But if you are just building a web app that needs to access your classes than I would leave them in your classes as you control the objects that you will access in your classes through your code.