The Open Data Protocol (OData) is a data access protocol built on core protocols like HTTP and commonly accepted methodologies like REST for the web. There are various kinds of libraries and tools can be used to consume OData services. But for beginners and those who want to write their own libraries, the pure HTTP requests and responses are also very important. This documentation will not cover every feature details for OData V4 services but will try to cover various typical scenarios. If you want to have a more detailed understanding, please refer to OData Documentation.
serviceRoot below with the URL http://services.odata.org/V4/TripPinServiceRW. TripPin now supports ETag, so for data modification topics, you should first using GET on TripPin (eg. GET serviceRoot/People) to get the section information in the payload then use the URL with section for data modification examples. (something looks like http://services.odata.org/V4/(S(flat4rgegiueineatspfdku1))/TripPinServiceRW)Singletons are single entities which are accessed as children of the entity container.
The request below returns the singleton Me
GET serviceRoot/Me
Response Payload
{
"@odata.context": "serviceRoot/$metadata#Me",
"@odata.id": "serviceRoot/Me",
"@odata.etag": "W/"08D1694EFF498B20"",
"@odata.editLink": "serviceRoot/Me",
"UserName": "aprilcline",
"FirstName": "April",
"LastName": "Cline",
"EmailAddress": [
"[email protected]",
"[email protected]"
],
"AddressInfo": [
{
"Address": "P.O. Box 555",
"City": {
"CountryRegion": "United States",
"Name": "Lander",
"Region": "WY"
}
}
],
"Gender": "Female",
"Concurrency": 635404810447326000
} The request below returns the property AddressInfo of singleton Me.
GET serviceRoot/Me/AddressInfo
Response Payload
{
"@odata.context": "serviceRoot/$metadata#Me/AddressInfo",
"value": [
{
"Address": "P.O. Box 555",
"City": {
"CountryRegion": "United States",
"Name": "Lander",
"Region": "WY"
}
}
]
}}
The request below updates the UserName of Single Me.
PATCH serviceRoot/Me
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type" : "Microsoft.OData.SampleService.Models.TripPin.Person",
"UserName": "AprilTripPin"
}
Response Payload
HTTP/1.1 204 No Content
OData-Version: 4.0OData now supports derived entity type. Entity types may derived by single inheritance from other entity types. In the sample TripPin service, the entity type Event and Flight both derive from entity type PlanItem.
The request below returns the flight of with PlanItemId 21.
GET serviceRoot/People('russellwhyte')/Trips(1003)/PlanItems(21)/Microsoft.OData.SampleService.Models.TripPin.Flight
Response Payload
{
"@odata.context": "serviceRoot/$metadata#People('russellwhyte')/Trips(1003)/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/$entity",
"PlanItemId": 21,
"ConfirmationCode": "JH58494",
"StartsAt": "2014-02-01T08:00:00+08:00",
"EndsAt": "2014-02-01T09:20:00+08:00",
"Duration": "PT0S",
"SeatNumber": "B11",
"FlightNumber": "FM1930"
} The request below shows how to get the derived enity set Flights.
GET serviceRoot/People('russellwhyte')/Trips(1001)/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight
Response Payload
{
"@odata.context": "serviceRoot/$metadata#People('russellwhyte')/Trips(1001)/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight",
"value": [
{
"PlanItemId": 11,
"ConfirmationCode": "JH58493",
"StartsAt": "2014-01-01T08:00:00+08:00",
"EndsAt": "2014-01-01T09:20:00+08:00",
"Duration": "PT0S",
"SeatNumber": null,
"FlightNumber": "VA1930"
},
{
"PlanItemId": 13,
"ConfirmationCode": "JH58493",
"StartsAt": "2014-01-04T13:00:00+08:00",
"EndsAt": "2014-01-04T14:20:00+08:00",
"Duration": "PT0S",
"SeatNumber": null,
"FlightNumber": "VA1930"
}
]
}The two request below shows how to filter on derived entities. These requests return all Flight deriving from PlanItem which has FlightNumber as 'VA1930'.
serviceRoot/People('russellwhyte')/Trips(1001)/PlanItems?$filter=Microsoft.OData.SampleService.Models.TripPin.Flight/FlightNumber eq 'VA1930'
serviceRoot/People('russellwhyte')/Trips(1001)/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight?$filter=FlightNumber eq 'VA1930'
Response Payload
{
"@odata.context": "serviceRoot/$metadata#People('russellwhyte')/Trips(1001)/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight",
"value": [
{
"PlanItemId": 11,
"ConfirmationCode": "JH58493",
"StartsAt": "2014-01-01T08:00:00+08:00",
"EndsAt": "2014-01-01T09:20:00+08:00",
"Duration": "PT0S",
"SeatNumber": null,
"FlightNumber": "VA1930"
},
{
"PlanItemId": 13,
"ConfirmationCode": "JH58493",
"StartsAt": "2014-01-04T13:00:00+08:00",
"EndsAt": "2014-01-04T14:20:00+08:00",
"Duration": "PT0S",
"SeatNumber": null,
"FlightNumber": "VA1930"
}
]
} The request below creates an event entity in trips. Event derives from PlanItem.
POST serviceRoot/People("russellwhyte")/Trips(1003)/PlanItems
OData-Version: 4.0
Content-Type: application/json
;
odata.metadata=minimal
Accept: application/json
{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"ConfirmationCode": "4372899DD",
"Description": "Client Meeting",
"Duration": "PT3H",
"EndsAt": "2014-06-01T23:11:17.5479185-07:00",
"OccursAt": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.EventLocation",
"Address": "100 Church Street, 8th Floor, Manhattan, 10007",
"BuildingInfo": "Regus Business Center",
"City": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.City",
"CountryRegion": "United States",
"Name": "New York City",
"Region": "New York"
}
},
"PlanItemId": 33,
"StartsAt": "2014-05-25T23:11:17.5459178-07:00"
}
Response Payload
Response HTTP/1.1 201 Created
{
"@odata.context": "serviceRoot/$metadata#People('russellwhyte')/Trips(1003)/PlanItems/$entity",
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"PlanItemId": 33,
"ConfirmationCode": "4372899DD",
"StartsAt": "2014-05-25T23:11:17.5459178-07:00",
"EndsAt": "2014-06-01T23:11:17.5479185-07:00",
"Duration": "PT3H",
"Description": "Client Meeting",
"OccursAt": {
"Address": "100 Church Street, 8th Floor, Manhattan, 10007",
"City": {
"CountryRegion": "United States",
"Name": "New York City",
"Region": "New York"
},
"BuildingInfo": "Regus Business Center"
}
} The request below updates an event. Event derives from PlanItem.
PATCH serviceRoot/People('russellwhyte')/Trips(1003)/PlanItems(5)/Microsoft.OData.SampleService.Models.TripPin.Event
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"Description": "This is a new description"
}
Response Payload
HTTP/1.1 204 No ContentThe request below deletes the flight plan item with Id '21' from a trip of person. Flight derives from PlanItem.
DELETE serviceRoot/People('russellwhyte')/Trips(1003)/PlanItems(21)/Microsoft.OData.SampleService.Models.TripPin.Flight
Response Payload
HTTP/1.1 204 No ContentContainment navigation properties define an implicit entity set for each instance of its declaring entity type. This implicit entity set if identified by the read URL of the navigation property for that entity. The request below returns the contained navigation property Trips of entity set People.
The request below returns Trips for a person where Trips is a containment navigation property for Person.
GET serviceRoot/People('russellwhyte')/Trips
Response Payload
{
"@odata.context": "http://services.odata.org/V4/(S(mmobft3g4aut3krzqrxxip4w))/TripPinServiceRW/$metadata#People('russellwhyte')/Trips",
"value": [
{
"TripId": 1001,
"ShareId": "9d9b2fa0-efbf-490e-a5e3-bac8f7d47354",
"Description": "Trip from San Francisco to New York City",
"Name": "Trip in US",
"Budget": 3000,
"StartsAt": "2014-01-01T00:00:00Z",
"EndsAt": "2014-01-04T00:00:00Z",
"Tags": [
"business",
"New York meeting"
]
},
......
,
{
"TripId": 1007,
"ShareId": "9ce142c3-5fd6-4a71-848e-5220ebf1e9f3",
"Description": "Happy honeymoon trip",
"Name": "Honeymoon",
"Budget": 2650,
"StartsAt": "2014-02-01T00:00:00Z",
"EndsAt": "2014-02-04T00:00:00Z",
"Tags": [
"Travel",
"honeymoon"
]
}
]
} The request below creates a Trip for Person with UserName 'russellwhyte'. Trips is a contained navigation property for Person.
POST serviceRoot/People('russellwhyte')/Trips
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type" : "Microsoft.OData.SampleService.Models.TripPin.Trip",
"TripId" : 3,
"ShareId" : null,
"Description" : "Create Containment",
"Name" : "Test Trip",
"StartsAt" : "2014-01-01T00:00:00+08:00",
"EndsAt" : "2014-02-01T00:00:00+08:00",
"Budget" : 1000,
"Tags" : [
"Test Tag 1",
"Test Tag 2"
]
}
Response Payload
HTTP/1.1 201 Created
Content-Length: 344
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Location: serviceRoot/People('russellwhyte')/Trips(3)
OData-Version: 4.0
{
"@odata.context":"serviceRoot/$metadata#People('russellwhyte')/Trips/$entity",
"TripId":3,
"ShareId":"00000000-0000-0000-0000-000000000000",
"Description":"Create Containment",
"Name":"Test Trip",
"Budget":1000,
"StartsAt":"2014-01-01T00:00:00+08:00",
"EndsAt":"2014-02-01T00:00:00+08:00",
"Tags":["Test Tag 1","Test Tag 2"]
} The request below returns Trips that contains 'New York' in its description of Person with UserName 'russellwhyte'.
GET serviceRoot/People('russellwhyte')/Trips?$filter=contains(Description, 'New York')
Response Payload
{
"@odata.context": "serviceRoot/$metadata#People('russellwhyte')/Trips",
"value": [
{
"TripId": 1001,
"ShareId": "9d9b2fa0-efbf-490e-a5e3-bac8f7d47354",
"Description": "Trip from San Francisco to New York City",
"Name": "Trip in US",
"Budget": 3000,
"StartsAt": "2014-01-01T00:00:00+08:00",
"EndsAt": "2014-01-04T00:00:00+08:00",
"Tags": [
"business",
"New York meeting"
]
}
]
} The request below updates the contained Entity Trip.
PATCH serviceRoot/People('russellwhyte')/Trips(1001)
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Trip",
"Description": "This is a new description"
}
Response Payload
HTTP/1.1 204 No ContentThe request below deletes a contained Entity Trip.
DELETE serviceRoot/People('russellwhyte')/Trips(1001)
Response Payload
HTTP/1.1 204 No ContentOData V4 supports entity or complex types which allow clients to persist additional undeclared properties. Such entities and complex types are called open types.
When create or update an open entity, undeclared properties can be added.
The request below shows how to add an undeclared property Description when create the open entity Person.
POST serviceRoot/People
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
ETag: W/"08D15F3DD9126D84"
{
"@odata.type" : "Microsoft.OData.SampleService.Models.TripPin.Person",
"UserName": "teresa",
"FirstName" : "Teresa",
"LastName" : "Gilbert",
"Gender" : "Female",
"Description": "Big fan for travelling",
"Emails" : ["[email protected]", "[email protected]"],
"AddressInfo" : [
{
"Address" : "1 Suffolk Ln.",
"City" :
{
"CountryRegion" : "United States",
"Name" : "Boise",
"Region" : "ID"
}
}]
}
Response Payload
HTTP/1.1 201 Created
{
"@odata.context":"serviceRoot/$metadata#People/$entity",
"@odata.id":"serviceRoot/People('teresa')",
"@odata.editLink":"serviceRoot/People('teresa')",
"UserName":"teresa",
"FirstName":"Teresa",
"LastName":"Gilbert",
"Description": "Big fan for travelling",
"Emails":["[email protected]","[email protected]"],
"AddressInfo":[{"Address":"1 Suffolk Ln.","City":{"CountryRegion":"United States","Name":"Boise","Region":"ID"}}],
"Gender":"Female"
}
The request below shows how to add an undeclared property Description when update the open entity Person.
PATCH serviceRoot/People('keithpinckney')
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Person",
"Description": "Big fan for travelling"
}
Response Payload
HTTP/1.1 204 No Content
OData V4 also supports open type for complex types.
The request below show how to add undeclared property Description when create new instance with AddressInfo of open complex type Location.
PATCH serviceRoot/People('russellwhyte')
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Person",
"[email protected]": "#Collection(Microsoft.OData.SampleService.Models.TripPin.Location)",
"AddressInfo": [
{
"Address": "187 Suffolk Ln.",
"City": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.City",
"CountryRegion": "United States",
"Name": "Boise",
"Region": "ID"
},
"Description": null
},
{
"Address": "XuanWu Load 555",
"City": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.City",
"CountryRegion": "China",
"Name": "NanJing",
"Region": "JiangSu"
},
"Description": "Nice Location"
}
],
"Concurrency": 635393824693486800,
"Description": null,
"[email protected]": "#Collection(String)",
"Emails": [
"[email protected]",
"[email protected]"
],
"FirstName": "Russell",
"[email protected]": "#Microsoft.OData.SampleService.Models.TripPin.PersonGender",
"Gender": "Male",
"LastName": "Whyte",
"UserName": "russellwhyte"
}
Response Payload
HTTP/1.1 204 No ContentThe request below show how to add undeclared property Description when update an instance with OccursAt of open complex type EventLocation.
PATCH serviceRoot/People('russellwhyte')/Trips(1003)/PlanItems(5)/Microsoft.OData.SampleService.Models.TripPin.Event
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json
{
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.Event",
"OccursAt": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.EventLocation",
"Address": "10 Beijing Street, 100000",
"BuildingInfo": "Beijing Restaurant",
"City": {
"@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.City",
"CountryRegion": "China",
"Name": "Beijing",
"Region": "Beijing"
},
"Description": "Beautiful City."
}
}
Response Payload
HTTP/1.1 204 No Content Batch requests allow grouping multiple operations into a single HTTP request payload. The Batch request below contains the following operations in order listed:
1. A query request, returns all Airlines.
2. Create an entity, a new Airline.
3. A second query request Airlines.
POST serviceRoot/$batch
OData-Version: 4.0
Content-Type: multipart/mixed;boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET serviceRoot/Airlines HTTP/1.1
Accept: application/json;odata.metadata=minimal
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
Content-ID: 1
POST serviceRoot/Airlines HTTP/1.1
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal
Accept: application/json;odata.metadata=minimal
{
"@odata.type" : "Microsoft.OData.SampleService.Models.TripPin.Airline",
"AirlineCode" : "EK",
"Name" : "Emirates Airline"
}
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET serviceRoot/Airlines HTTP/1.1
Accept: application/json;odata.metadata=minimal
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--
Response Payload
HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Length: 3100
Content-Type: multipart/mixed; boundary=batchresponse_3e4cf86f-ab02-46e1-9631-b08a787abc35
OData-Version: 4.0
--batchresponse_3e4cf86f-ab02-46e1-9631-b08a787abc35
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 200 OK
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
{
"@odata.context":"serviceRoot/$metadata#Airlines",
"value":
[{
"AirlineCode":"AA",
"Name":"American Airlines"
},
{
"AirlineCode":"FM",
"Name":"Shanghai Airline"
},
{
"AirlineCode":"MU",
"Name":"China Eastern Airlines"
}
]}
--batchresponse_3e4cf86f-ab02-46e1-9631-b08a787abc35
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 201 Created
Location: serviceRoot/Airlines('EK')
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
{
"@odata.context":"serviceRoot/$metadata#Airlines/$entity",
"@odata.id":"serviceRoot/Airlines('EK')",
"@odata.editLink":"serviceRoot/Airlines('EK')",
"AirlineCode":"EK","Name":"Emirates Airline"
}
--batchresponse_3e4cf86f-ab02-46e1-9631-b08a787abc35
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 200 OK
OData-Version: 4.0
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
{
"@odata.context":"serviceRoot/$metadata#Airlines",
"value":
[{
"AirlineCode":"AA",
"Name":"American Airlines"},
{
"AirlineCode":"FM",
"Name":"Shanghai Airline"
},
{
"AirlineCode":"MU",
"Name":"China Eastern Airlines"
},
{
"AirlineCode":"EK",
"Name":"Emirates Airline"
}]
}
--batchresponse_3e4cf86f-ab02-46e1-9631-b08a787abc35--