OData or Queryable REST? - asp.net-core

Before embarking on API development, looking to choose the right foundation.
So...OData permits queryability over models. Great!
...but REST apis can be decorated with the [Queryable] ...
So... what is the remaining advantage of OData over such Queryable APIs?
Maybe the following are true?
OData routing relies primarily on convention based routing, so not sure one can craft if ever needed to (e.g.: to avoid legacy routes one has to implement?)
Suspect one cannot query REST APIs based on child entities?
Anything else that would come into play?
Thank you!

OData is a specific and standardized implementation of REST. If you make your standard API endpoint's queryable then those specific endpoints will follow most of the OData v4 response conventions but it is up to you to document this for the consumers.
When you choose to start from OData, you are choosing to implement the OData conventional standards for all of the controllers and Entities that you choose to include in the OData Entity Model. This in turn will generate the $metadata document that describes the model and the supported functions and actions.
You can add custom types, functions and actions to an OData controller if you follow the conventions correctly. You can also directly host standard API controller endpoints if you want to, but unless you register them with the OData model, they will not be included in the $metadata document.
You could choose to replicate or implement the entire OData specification in your API from first principals if you want to, including producing your own $metadata document... But if you were going to go to all that trouble then it would have been far easier to just use the ODataController and implement OData properly.
Making the decision to use OData over standard Web API is usually driven by your chosen documentation method and if you can accept the general OData query conventions and if the consumers of the API can understand OData. OData standards are clearly defined so that you don't have to worry as much about educating consumers on how to use your API and can focus more on the implementation itself.

Related

How to convert a LinqExpression into OData query URI

There are a lot of answers on how to convert ODataQuery into an Expression or into a Lambda, but what I need is quite the opposite, how to get from a Linq Expression the OData query string.
Basically what I want is to transcend the query to another service. For example, having 2 services, where your first service is not persisting anything and your second service is the one that will return the data from a database. Service1 sends the same odata request to Service2 and it can add more parameters to the original odata request to Service2
What I would like:
public IActionResult GetWeatherForecast([FromServices] IWeatherForcastService weatherForcastService)
{
//IQueryable here
var summaries = weatherForcastService.GetSummariesIQ();
var url = OdataMagicHelper.ConvertToUri(summaries);
var data = RestClient2.Get(url);
return data;
}
OP Clarified the request: generate OData query URLs from within the API itself.
Usually, the queries are so specific or simple, that it's not really necessary to try and generate OData urls from within the service, the whole point of the service configuration is to publish how the client could call anything, so it's a little bit redundant or counter-intuitive to return complex resource query URLs from within the service itself.
We can use Simple.OData.Client to build OData urls:
If the URL that we want to generate is:
{service2}/api/v1/weather_forecast?$select=Description
Then you could use Simple.OData.Client:
string service2Url = "http://localhost:11111/api/v1/";
var client = new ODataClient(service2Url);
var url = await client.For("weather_forecast")
.Select("Description")
.GetCommandTextAsync();
Background, for client-side solutions
If your OData service is a client for another OData Service, then this advice is still relevant
For full linq support you should be using OData Connected Services or Simple.OData.Client. You could roll your own, or use other derivatives of these two but why go to all that effort to re-create another wheel.
One of the main drivers for a OData Standard Compliant API is that the meta data is published in a standard format that clients can inspect and can generate consistent code and or dynamic queries to interact with the service.
How to choose:
Simple.OData.Client provides a lightweight framework for dynamically querying and submitting data to OData APIs. If you already have classes that model the structure of the API then you can use typed linq style query syntax, if you do not have a strongly typed model but you do know the structure of the API, then you can use either the untyped or dynamic expression syntax to query the API.
If you do not need full compile-time validation of your queries or you already have the classes that represent the resources served by the API then this is a simple enough interface to use.
This library is perfect for use inside your API logic if you have need of generating complex URLs in a strongly typed style of code without trying to generate a context to manage the connectivity to the server.
NOTE: Simple.OData.Client is sometimes less practical when developing against a large API that is rapidly evolving or that does not have a strict versioned route policy. If the API changes you will need to diligently refactor your code to match and will have to rely on extensive regression testing.
OData Connected Services follows a pattern where some or all of the API is modelled in the client with strongly typed client side proxy interfaces. These are POCO classes that have the structure necessary to send to and receive data from the server.
The major benefit to this method is that the POCO structures, requests and responses are validated against the schema of the API. This effectively gives you full intellisense support for the API and allows you to explor it's structure, the generated code becomes your documentation. It also gives you compile time checking and runtime safety.
The general development workflow after the API is deployed or updated is:
Download the $metadata document
Select the Operations and Types from the API that you want to model
Generate classes to represent the selected DTO Types as defined in the document, so all the inputs and outputs.
Now you can start using the code.
In VS 2022/19/17 the Connected Services interface provides a simple wizard for establishing the initial connection and for updating (or re-generating) when you need to.
The OData Connected Service or other client side proxy generation pattern suits projects under these criteria:
The API definition is relatively stable
The API definition is in a state of flux
You consume many endpoints
You don't want to manually code the types to serialize or deserialze payloads
Full disclosure, I prefer the connected service approach, but I have my own generation scripts. However if you are trying to generate OData query urls from inside your API, its not really an option, it creates a messy recursive dependency... just don't go there.
Connected services is the low-(manual)-code and lazy approach that is perfect for a stable API, generate once and never do it again. But the Connected Service architecture is perfect for a rapidly changing API because it will manage the minute changes to the classes for you, you just need to update your client side proxy classes more frequently.

OData with WCF Data Services / Entity Framework

Apologies in advance, this is a long question.
(TL;DR : Does anyone have any advice on using the EF with dynamic fields exposed using WCF Data Services/OData)
I am having some conceptual problems with WCF Data Services and EF, specifically pertaining to exposing some data as an OData service.
Basically my issue is this. The database I am exposing allows users to add fields dynamically (user-defined fields) and it uses a system whereby these fields are added directly to the underlying SQL tables. Furthermore, when you want to add data to the tables you cannot use direct SQL, you have to go via an API that they provide. (it's SAP Business One, fwiw).
I have already sucessfully built a system that exposes various objects via XML and allows a client to update or add new entities into SBO by sending in XML messages, and although it works well it's not really suited to mobile apps as it's very XML-heavy and the entry point is an old-skool asmx webservice. I want to try to jazz it up for mobile development and use Odata with WCF or Web API. (I know I could change up to a WCF service, allow handing of JSON-format requests, and start returning JSON data, but it just seems like there must be a more...native...way)
Initially I had discounted the possibility of using the EF for this because a)Dynamic fields and b)the EF could only be read-only; adding/updating entities would have to be intercepted and routed to the SBO DI Server. However, I am coming back to thinking about it and am looking for some advice (negative or otherwise!) on how to approach.
What I basically want to do is this
Expose the base tables from SBO (which don't change except when they themselves issue a patch) as EF Entities, with all the usual relationy goodness. In fact I actually will not be directly exposing the tables, I will use a set of filtered SQL Views as the data sources as this ties in with various other stuff we do to allow exposing only certain data to 3rd parties.
Expose any UDFs a particular user has added as some kind of EAV sub-collection per entity.
Intercept any requests to ADD or UPDATE an object, and route these through an existing engine I have for interfacing with the SAP Data import services.
I suppose my main question is this; suppose I implement an EF entity representing a Sales Order which comprises a Header and Details collection. To each of these classes I stick in an EAV type collection of user-defined fields and values. How much work is involved in allowing the OData filtering system to work directly on the EAV colleciton (e.g for a client to be able to ask for Service/Orders/$filter=SomeUdfField eq SomeValue where this request has to be passed down into the EAV collection of the Order header entity)
Or is it possible, for example, to generate an EF Model from some kind of metadata on the fly (I don't mind how - code generation or model building library) that would mean I could just expose each entity, dyanmic fields included, as a proper EF Model? Many thanks in advance if you read this far :)
For basic crud to an existing EF context, WCF Data Services works out great. As soon as you want to add some custom functionality, as you described above it takes a bit more work.
What you described is possible, but you would need to build out your own custom data provider to handle the dynamic generation of metadata as well as custom hooks into add/update/delete.
It may be worth looking into WCF Data Services Toolkit, it's a custom provider which slaps a repository pattern over WCF Data Services for ease of use, but it does not provide the custom metadata generation.

developing your own RESTful API

in developing your own RESTful API. does it necessarilly needed to use the four different http methods? GET POST PUT & DELETE?
i was checking the Twitter REST API and saw that they are just using the common methods (GET & POST)
Short answer: No
Long Answer:
REST is not specific to any one protocol, instead it is a style of programming. This is helpful to keep in mind because a RESTful endpoint should be thought of as having specific goals. Your job is to expose the web service in the most RESTful way possible.
When you're making a RESTful API you are not required to use any specific HTTP methods. Instead, REST can be embodied in this guiding principal: That you must expose individually identifiable resources; these resources must be manipulable in their exposed form. Oh and use self descriptive messages.
I'm sure this is a leaky explanation. Try to see, though, that REST becomes much more clear when you have the key idea in mind. RESTful practices expose resources in a way that allows us work with state in a sane manner. The technical details of how to implement a RESTful API can be learned by reading this:
http://en.wikipedia.org/wiki/Representational_state_transfer
After that, read something specific to your language. Fast track: find some RESTful API written in your language and clone it/play with it.
You should use whatever HTTP methods are appropriate for the operations you expose.
For example, you should accept HTTP DELETE requests only for operations that delete things.
If your API does not allow callers to delete things (eg, a traffic or weather API), you should not accept the DELETE verb.
Only if you are going to support those logical operations:
GET - fetch a resource
PUT - update (or create) a resource
DELETE - delete a resource
POST - several uses: create a new resource in a collection, perform some operation that will alter a resource in some one (as opposed to PUTting an entirely new version of a resource)
Most APIs will want to to provide those operations, and will use all those methods. And don't forget HEAD - fetch information about a resource (but not the resource itself).

Implementing REST hypermedia using WCF

I have a WCF-based REST service and I'm planning to add hypermedia support to it. Currently I'm relying on WCF to build the service response by serializing my data contracts. With hypermedia in the picture now, I need a way to instruct WCF to insert hypermedia links in the XML response that it builds. My question is, how do I do that?
One way could be that I modify my data contracts to include the said links as data members. Then WCF can automatically serialize them. But is that the best practice? Or is it better to intercept WCF's serialization process and add these links at that time? Or is there any other more suitable alternative?
You need to construct the hypermedia yourself. If you choose Atom there are some helpers. Basically you create a SyndicationFeed and add SyndicationItem items to it and use an Atom10FeedFormatter to turn the whole feed into an Atom document.

Where WCF and ADO.Net Data services stand?

I am bit confused about ADO.Net Data Services.
Is it just meant for creating RESTful web services? I know WCF started in the SOAP world but now I hear it has good support for REST. Same goes for ADO.Net data services where you can make it work in an RPC model if you cannot look at everything from a resource oriented view.
At least from the demos I saw recently, it looks like ADO.Net Data Services is built on WCF stack on the server. Please correct me if I am wrong.
I am not intending to start a REST vs SOAP debate but I guess things are not that crystal clear anymore.
Any suggestions or guidelines on what to use where?
In my view ADO.Net data services is for creating restful services that are closely aligned with your domain model, that is the models themselves are published rather then say some form of DTO etc.
Using it for RPC style services seems like a bad fit, though unfortunately even some very basic features like being able to perform a filtered counts etc. aren't available which often means you'll end up using some RPC just to meet the requirements of your customers i.e. so you can display a paged grid etc.
WCF 3.5 pre-SP1 was a fairly weak RESTful platform, with SP1 things have improved in both Uri templates and with the availability of ATOMPub support, such that it's becoming more capable, but they don't really provide any elegant solution for supporting say JSON, XML, ATOM or even something more esoteric like payload like CSV simultaneously, short of having to make use of URL rewriting and different extension, method name munging etc. - rather then just selecting a serializer/deserializer based on the headers of the request.
With WCF it's still difficult to create services that work in a more a natural restful manor i.e. where resources include urls, and you can transition state by navigating through them - it's a little clunky - ADO.Net data services does this quite well with it's AtomPub support though.
My recommendation would be use web services where they're naturally are services and strong service boundaries being enforced, use ADO.Net Data services for rich web-style clients (websites, ajax, silverlight) where the composability of the url queries can save a lot of plumbing and your domain model is pretty basic... and roll your own REST layer (perhaps using an MVC framework as a starting point) if you need complete control over the information i.e. if you're publishing an API for other developers to consume on a social platform etc.
My 2ΓΈ worth!
Using WCF's rest binding is very valid when working with code that doesn't interact with a database at all. The HTTP verbs don't always have to go against a data provider.
Actually, there are options to filter and skip to get the page like feature among others.
See here: