I have tried replicating simple use-case that I am trying to achieve.
Here we have vehicles and vehicles can be two-wheeler or
four-wheeler or any other subtype in future.
We may have many cars or
bike in garage at any given point in time.
I want to expose REST API
which gives the status of vehicles in Garage irrespective of vehicle type (all vehicle should be returned)
This is single common
API. Only single rest API gives this status in response (may be
using Json Inheritance).
Problem: This single rest service will may have query parameters which would be specific to child classes:
http://hostname/vehicle?name=demovehicle&steeringwheel=tilt
http://hostname/vehicle?name=demovehicle&steeringwheel=tilt&steeringhandle=iron
I am trying to understand how this can be implemented since we have single service and query parameters will not be present in all tables since it is not common across all child tables.
One thought I had to maintain query parameter and type of vehicle catalog in backend to figure out what query parameter belong to which vehicle type.
Related
We need to manage static lookup tables with API, all tables have same structure so creating separate controller for each table or One generic Controller for all end points is better options?
Also We are getting all Lookup Data in one API Call with the Model for each Table in Response Model, so when we need to get the individual data should we create separate endpoint or we can manage this by providing a query parameter "type" to populate only specified Model. I was just wondering that can we use query parameter for this functionality? Any industry standard for this?
I am designing a rest api and I have some doubts about exposing and consuming children from relation.
Assuming I have an entity A with a one to many relation to entity B (so A can have some Bs attached) and I design an endpoint to create entity A and DTO for entity A includes a list for entity B and user provides a valid one, should it be saved too?
Example:
Doing a post to some endpoint e.g. /api/v1/As
{
entityAfield1: someValue,
entityAfield2: someOtherValue
Bs: [
{
HERE a valid B payload
}
]
}
should I also save B and create a relation between A and B? What if B also have some children? Should it be saved too?
Or should I just save A and create an endpoint like
/api/v1/As/{Aid}/Bs/{Bid}
to create a relation?
And same question about getting data. Should get always retrieve all children? I couldn't find a clear answer to this on the web.
The issue might be solved by means of returning the IDs of Bs. This way, a user of service will decide whether or not to retrieve the actual data of related resources.
To interact with those an endpoint like this
/api/v1/Bs/{Bid}
can be used, as well as a more verbose one
/api/v1/As/{Aid}/Bs/{Bid}
however, the too nested endpoints, like
/api/v1/As/{Aid}/Bs/{Bid}/Cs/{Cid}/Ds/{Did}
should be avoided and most likely indicate a design flaw.
For a tree structure or many to many relations in general, an intermediate resource that represents a linkage should be exposed. There is a good example of a REST API implementation by Google, its "Children" section would be especially helpful for such case.
I'm trying to get my head around NoSQL and Google Cloud Datastore, and I don't know how to chose between two different options for storing data.
I have a list of orders, and every order is for an unspecified number of products. What are the pros/cons of storing the product list as an array property for the order entity vs having product child entities for each order parent?
Firstly, be well aware of the distinction between the 2 possible approaches of implementing a relationship between entities:
one entity can contain a Key type property pointing to another entity (which might or might not exist!) - this is a functional relationship only, not one at the datastore level
having the 2 datastore entities in a parent-child (ancestry) relationship, inside the same datastore entity group.
Using the 2nd one has scalability implications, see also:
Ancestor relation in datastore
E-commerce Product Categories in Google App Engine (Python)
As for storing a list as an array property vs as separate entities, see Creating your own activity logging in GAE/P (where repeated properties is just how array properties are called in the ndb client library context).
We would like to create an OData REST API. Our data model is such that each customer has their own database. All database objects have the same definition across all customer databases, with the exception of a single table.
The customer specific table we will call Contact. When a customer adds a column the system creates a column with a standardised name with a definition translated from options selected by the user in the UI. The user only refers to the column data by a field name they have specified to enable the user to be able to generate friendly queries.
It seems to me that the following approaches could be used to enable OData for the model described:
1) Create an OData open type to cater for the dynamic properties. This has the disadvantage of user requests for a customer not providing an indication of the dynamic properties that can be queried against. Even though they will be known for the user (via token authentication). Also, because dynamic properties are a dictionary, some data pivoting and inefficient query writing would be required. Not sure how to implement the IQueryable handling of query options for the dynamic properties to enable our own custom field querying.
2) Create a POCO class with e.g. 50 properties; CustomField1, CustomField2... Then somehow control which fields are exposed for use in OData calls. We would then include a separate API call to expose the custom field mapping. E.g. custom field friendly name of MobileNumber = CustomField12.
3) At runtime, check to see if column definitions of table changed since last check. If have, generate class specific to customer using CodeDom and register it with OData. Aiming for a unique URL for each customer. E.g. http://domain.name/{customer guid}/odata
I think the ideal for us is option 2. However, the fact the CustomField1 could be an underlying SQL data type of nvarchar, int, decimal, datetime, etc, there are added complications.
Has anyone a working example of how to achieve what has been described, satisfactorily?
Thanks in advance for any help.
Rik
We have run into a similar situation but with our entire dataset being unknown until runtime. Using the ODataConventionModelBuilder and EdmModel classes, you can add properties dynamically to the model at runtime.
I'm not sure whether you will have to manually add all of the properties for this object type even though only some of them are unknown or whether you can add your main object and then add your dynamic ones afterwards, but I guess either would be workable.
If you can get hold of which type of user it is on the server, you could then add only the properties that you are interested in (like option 3 but not having to CodeDom).
There is an example of this kind of untyped OData server in the OData samples here that should get you started: https://github.com/OData/ODataSamples/tree/master/WebApi/v4/ODataUntypedSample
The research we carried out actually posed Option 1 as the most suitable approach for some operations. i.e. Create an SQL view that unpivots the data in a table to a key/value pair of column name/column value for each column in the table. This was suitable for queries returning small datasets. This was far less effort than Option 3 and less confusing for the user than Option 2. The unpivot query converted the field values to nvarchar (string) values and thus meant that filtering in the UI by column value data types was not simple to achieve. (If we decide to implement this ability, I believe this can be achieved by creating a custom attribute that derives from EnablQueryAttribute, marking the controller action with it and manipulate the IQueryable before execution).
However, we wanted to expose a /Contacts/Export endpoint that when called would output the columns from a table with a fixed schema joined on a table with a client specific schema and output to a CSV file. All the while utilising the OData supported filter syntax. One of our customer databases has more than 12 million rows of data and is made up of approximately 30 columns.
To achieve this it looks like our best bet would have been to work with the Microsoft.OData.Core.UriParser.UriQueryExpressionParser class, unfortunately Microsoft in their wisdom have declared this as internal, as well as many of it's dependants.
Walking an abstract syntax tree built from OData supported query options and applying our own visitor to each node to build some dynamic Linq query/SQL seems like a possible solution.
For the time-being we will simply implement a cut-down set of supported $filter criteria without the support for grouping parenthesis.
I am trying to get my head around how to handle relationships in REST.
I have read this question.
If I have Drivers and Cars in my api and a Driver can only exist if connected to a Car I would make Drivers a subresource in Cars. The relationship between a Car and a Driver contains a set of properties, say averageSpeed and timeOnTheRoad. One Car can have many Drivers, but a Driver can only have one Car.
How should I add a new driver? How should I add a relationship between a driver and a car?
If I add a resource Wunderbaums which is not a subresource to Cars, but a Car can contain Wunderbaums. How should I add a relationship between a Car and a Wunderbaum?
One way of adding a relationship between two entities is to POST to /entityA/{id}/entityB/{id} and send properties for the relationship in the body. This would work for my example with Cars and Wunderbaums since Wunderbaums is not a subresource of Cars, but it would not work in my example with Cars and Drivers since it would interfere with CRUD functionality for Drivers. The path cars/{id}/drivers{id} would be the same for creating a relationship between a Car and a Driver as for creating a Driver.
I also found this unanswered question on the subject.
Edit 1
#JB Nizet suggested that I put the relationship properties inside of the Driver, since its a one to many relationship. It would be a possible solution, but what if a Driver could have many Cars? Should we handle one to many relations different than many to many relations?
Edit 2
We could put relationship properties with the Driver in a many to many relationship scenario as well. The question then is if Driver has its own resource, is it ok that cars/2/drivers/4 returns a different set of properties than drivers/4? In the case where I get the Driver by its relation to Car I will include avrageSpeed and timeOnTheRoad in the response.
From a DDD perspective, I think perhaps you're asking the wrong question; the question is not 'how do Cars and Drivers relate in the database and thus how should they manifest in the API', but "what capabilities does my API expose and what behaviors does it support"?
In other words, what does the/each REST API call mean in the context of the business (or the user's mind)? If the request is "what cars have I driven?" then driver ->> car is the relationship for that API call. If the request is "assign Tim to drive the Minivan" then the relationship for that API call is Driving -> Driver,Car
Building a CRUD system out of REST can work fine, but it sounds like what you want is a step beyond that.