Advanced Tutorial
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 that 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.
Please note
- This is the advanced section. For topics like requesting data, query options, basic data modification, operations and etc, please refer to Basic Section.
- All these are based on OData V4 sample service TripPin, please just replace the serviceRootbelow with the URLhttps://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 https://services.odata.org/V4/(S(flat4rgegiueineatspfdku1))/TripPinServiceRW)
- You may use Fiddler to run the request (especially the complex ones of data modification) and get the JSON response.
- In TripPin service, ETag is currently enabled on entity Person. We omit the ETag related headers in request headers for short, please go to the ETag Section for detailed information.
- We will keep improving this by adding contents and fixing bugs. You can provide your feedbacks and ask questions using OData Mailling List.
Singleton
Singletons are single entities which are accessed as children of the entity container.
Requesting singleton
 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": [
              "April@example.com",
              "April@contoso.com"
            ],
            "AddressInfo": [
                {
                "Address": "P.O. Box 555",
                "City": 
                    {
                        "CountryRegion": "United States",
                        "Name": "Lander",
                        "Region": "WY"
                    }
                }
            ],
            "Gender": "Female",
            "Concurrency": 635404810447326000
            }
            Requesting property of Singleton
 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"
                        }
                    }
                ]
            }
            
Update Singleton
 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.0
            Derived Entity Type
OData 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.
Requesting a Derived Entity
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"
            }
            Requesting a Derived Entity Collection
 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"
            }
            ]
            }
            Filter on Derived Type
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"
            }
            ]
            }
            Create a Derived Entity
 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"
            }
            }
            Update a Derived Entity
 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 Content
            Delete a Derived Entity
The 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 Content
            Containment Navigation Property
Containment 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.
Requesting a Contained Entity Set
 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": "https://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"
            ]
            }
            ]
            }
            Create a Contained Entity
 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"]
            }
            Filter on a Contained Entity Set
 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"
            ]
            }
            ]
            }
            Update Contained Entity
 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 Content
            Delete Contained Entity
The request below deletes a contained Entity Trip.
 DELETE serviceRoot/People('russellwhyte')/Trips(1001)
               
               Response Payload
            
            HTTP/1.1 204 No Content
            Open Type
OData V4 supports entity or complex types which allow clients to persist additional undeclared properties. Such entities and complex types are called open types.
Open Entity Type
 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" : ["teresa@example.com", "teresa@contoso.com"],
               "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":["teresa@example.com","teresa@contoso.com"],
            "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
               
Open Complex Type
 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",
               "AddressInfo@odata.type": "#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,
               "Emails@odata.type": "#Collection(String)",
               "Emails": [
               "Russell@example.com",
               "Russell@contoso.com"
               ],
               "FirstName": "Russell",
               "Gender@odata.type": "#Microsoft.OData.SampleService.Models.TripPin.PersonGender",
               "Gender": "Male",
               "LastName": "Whyte",
               "UserName": "russellwhyte"
               }
               
               
               Response Payload
            
            HTTP/1.1 204 No Content
            The 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
 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--