I know that with openapi 3 I can use oneOf/anyOf but currently we can't upgrade to openapi 3. In one of definitions I need to use many response types which doesn't have common attributes (basically response is interface without any method/attribute and has multiple different implementations). Can I somehow define multiple response types with openapi 2? Is it possible to use for example headers/content-types/... to distinguish between this reponse types and have valid openapi2 definition?
thanks
Update:
Turns out there can be multiple responses as long as they have different HTTP status code as a "key". default keyword is just that, user of API is supposed to expect that if HTTP status is not on the list of responses default should be used. (e.g. if somebody uses switch to handle responses default maps to default case in switch).
As for single HTTP status code signaling multiple possible types of response, that's not supported explicitly. One ugly workaround would be to create type that contain all the fields, and it would be up to a client to discriminate based on which fields hold values.
Related
I have the problem that our backend uses an OData-"like"-Processor which has some special functions. It is oriented at OData_2.0
So the question will be:
What is the most OData like approach for this kind of the following requests
Our backend Data-Model has no single-attribute-keys. But it's recommended to be OData-Like if possible.
First: I need to delete several objects via one OData Request. My first idea is to use filters to define which objects should be deleted. But I', not sure if this is the right approach.
For Example: I want to delete all Items which have a price greater than 10.00
http://.../<oDataServiceX>/Item?$filter=ItemPrice gt 10.00
Second: When I want to delete an object which is not identifiable by one single key-attribute. How can I define that in the classical OData-Delete-Request-Syntax.
Is the following OData-like?
http://.../<oDataServiceX>/Item(1,54,2) //3 Attributes which define the key for the Item
Or should I do a filter again? (If filter is a proper way of doing this).
http://.../<oDataServiceX>/Item?$filter=keyAttr1 eq 1 and keyAttr2 eq 54 and keyAttr 3 eq 2
You can't delete multiple entries in a single OData query, you need first to retrieve their keys and then send multiple delete requests. There are two ways to improve this process:
Use OData batch to send all delete request in a single HTTP call.
Use some of libraries that can simulate deletion using filter (internally they will issue multiple requests but for the application it will look like a single call). One of such libraries is Simple.OData.Client.
Hope this helps.
Odata v4 supports the format DELETE /entity(key1='', key2='') and so on.
However, for oData v2, one option could be to use the request body to pass some data over. DELETE /entity, with data in the body.
The documentation states that the convention is to delete an entity by key. However, this was the approach followed when we had to delete by multiple keys for an odata v2 service. Also while implementing this using oData v2 libraries, we had to add a routing convention to support Delete without a key.
Is it possible to map the different objects to the same url and use different post params to differentiate between the return types?
My API isn't really rest. Everything flows through the same URL but has a parameter "Type" that differentiates the result that should be returned.
'Probably' - it would be nice it you added a few examples to the question (requests and associated responses).
Sending the requests is fine, though you will need to explicitly specify the path / route name to use.
For the response, you will most likely need to use an RKDynamicMapping which will inspect the incoming data and return the appropriate mapping to use.
If you can't tell the 'type' from the response data (instead, you can only tell because of the URL that was requested) then you may need to try mapping into all types and rejecting invalid content using KVC validation, or you might want to change your data model (not enough information in the question to determine which...).
Based on the information here http://docs.valence.desire2learn.com/res/course.html#actions I would expect that to 'update' a courseOffering I would specify a PUT with a CourseOfferingInfo block, which only contains a few attributes. Every time I try this, I get a 404, not found - even using the same route for a successful GET (404 says org doesn't exist OR org is not an offering - neither is true). However, if I specify a CreateCourseOffering block (directly from a previous GET), the PUT works fine. Is this correct and the documentation not? Or are there other things I should look for in this scenario? The documentation says use CreateCourseOffering for the POST to create an offering… I simply want to update one attribute of that offering and as such thought the PUT was the way to go.
If you use the "create" POST route with a CreateCourseOffering block, this will create a new course offering, and send back the CourseOffering block for the newly created course offering (this will include the org unit ID value for the new org unit you've built).
If you want to update an existing course offering, you should, as you suspected, use the "update" PUT route with a CourseOfferingInfo block. Note that you must provide valid information for all the fields in this block, since when used successfully, the LMS will use all the properties you specify in that block for new values for the org unit. The StartDate and EndDate fields are particularly finicky: you must provide either a valid UTCDateTime value (notice that the three-digit millisecond specifier in these values is mandatory) or a JSON null value if the field is not applicable.
Why a 404? What you're seeing with the 404s and the data you're passing is likely down to the way the back-end service is doing data binding. It tries to de-serialize your provided JSON data (and query parameters) into data objects it can read/manipulate -- if you provide a JSON block that contains a superset of the properties it's expecting, then this may work (for example, if you provide a CourseOffering block when you're expected to provide a CourseOfferingInfo) as the binding layer may ignore fields it doesn't need. If the binding process fails, because you provide a value for a property that can't be bound to the data type expected, or because you fail to provide a JSON property field it expects, then this can cause the service to return a 404 (because binding/de-serializing incoming parameterized data happens at the same time as matching the URL route to an underlying service handler).
If you provide a JSON structure (and query parameters) that the web-service can bind to its expected data objects, but the values you provide are invalid or nonsensical, then this can cause the underlying service handler to respond with a 400 (signalling an Invalid Request). But in order to get this far, your parameterized data still needs to get properly deserialized and bound into data objects for the underlying service to examine.
We'll be updating the documentation to more explicitly draw out this fact. The safest policy from the calling client perspective is to pass valid JSON structures that are exactly what's expected by the individual routes, especially since the underlying back-end service implementation might change how it handles incoming requests.
In most examples I saw the incoming data (for example for creating new entity) data is POST'ed as form encoded. This is great for 'flat' objects, but I need to transfer more complex objects (2-3 levels of nesting). Is it acceptable to transfer them in the body of POST request as JSON-encoded string?
As long as you set the proper header to application/json and generally use the HTTP mechanisms of content negotiation: yes, this is acceptable.
json and form-data are media types. Pick what you want and be sure to set the content-type to the one you've chosen.
I believe JSON is commonly used to communicate arrays within the body of a document. I am using it here to transfer this array of mapped points and associated attributes http://ageara.com/test/map-service.php?action=listpoints ... albeit not with REST style ;-)
I'm getting up to speed with the WCF Web API. I want to expose an endpoint that can accept notes, via the POST method. My issue is, I want to support multiple representations for notes. For example, I might want to accept a note using a custom XML serialization that we're using elsewhere, or as an atom:entry element. I already have formatters that can deserialize these into a Note class (our own custom class) or as a SyndicationItem.
The question comes though, how do I define the method? I've currently got this:
[WebInvoke(UriTemplate = GetNotesUriRoot,Method="POST")]
public HttpResponseMessage PostNote(ObjectContent item,HttpRequestMessage request)
Which fails when starting up:
The service operation 'PostNote' will never receive a value for the input parameter 'item' of type 'ObjectContent'. Ensure that a request HttpOperationHandler has an output parameter with a type assignable to 'ObjectContent'.
I initially tried having two separate methods (with appropriately typed parameters), but they can't share the same endpoint name. The current effort (using ObjectContent) was based on other posts I could find that suggested that it could be a parameter. There is no common base type or interface between Note and SyndicationItem
We're using v0.6.0 of the WCF Web API
You need to have a parameter / return type of type Note and your formatters will (de-)serialize it to / from the required representation.
[WebInvoke(UriTemplate = GetNotesUriRoot,Method="POST")]
public HttpResponseMessage PostNote(Note note)
then in your request the content-type header will determine how the object is deserialised. You don't need to worry about deciding how to deserialise, the decision is made for you, as long as the relevant formatter exists (I've not delved in to formatters yet as json/xml have been enough for me so far)