Odata v4.0 Part1 Protocol
Odata v4.0 Part1 Protocol
1.1 Terminology
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD
NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described
in [RFC2119].
3.1 Annotations
Model and instance elements can be decorated with Annotations.
Annotations can be used to specify an individual fact about an element, such as whether it is read-only, or
to define a common concept, such as a person or a movie.
Prefer: odata.include-annotations="*"
Prefer: odata.include-annotations="-*"
Example 5: a Prefer header requesting that all annotations defined under the "display" namespace (recursively) be
returned
Prefer: odata.include-annotations="display.*"
Example 6: a Prefer header requesting that the annotation with the term name subject within the display
namespace be returned if applied
Prefer: odata.include-annotations="display.subject"
The odata.include-annotations preference is only a hint to the service. The service MAY ignore
the preference and is free to decide whether or not to return annotations not specified in the
odata.include-annotations preference.
In the case that the client has specified the odata.include-annotations preference in the request,
the service SHOULD include a Preference-Applied response header containing the
odata.include-annotations preference to specify the annotations actually included, where
applicable, in the response. This value may differ from the annotations requested in the Prefer header
of the request.
odata-v4.0-errata02-os-part1-protocol-complete 30 October 2014
Standards Track Work Product Copyright © OASIS Open 2014. All Rights Reserved. Page 24 of 74
8.2.8.5 Preference odata.maxpagesize
The odata.maxpagesize preference is used to request that each collection within the response contain
no more than the number of items specified as the positive integer value of this preference. The syntax of
the odata.maxpagesize preference is specified in [OData-ABNF].
Example 7: a request for customers and their orders would result in a response containing one collection with
customer entities and for every customer a separate collection with order entities. The client could specify
odata.maxpagesize=50 in order to request that each page of results contain a maximum of 50 customers, each
with a maximum of 50 orders.
If a collection within the result contains more than the specified odata.maxpagesize, the collection
SHOULD be a partial set of the results with a next link to the next page of results. The client MAY specify
a different value for this preference with every request following a next link.
In the example given above, the result page should include a next link for the customer collection, if there are more
than 50 customers, and additional next links for all returned orders collections with more than 50 entities.
If the client has specified the odata.maxpagesize preference in the request, and the service limits the
number of items in collections within the response through server-driven paging, the service MAY include
a Preference-Applied response header containing the odata.maxpagesize preference and the
maximum page size applied. This value may differ from the value requested by the client.
http://host/service/
http://host/service/$metadata
http://host/service/Customers
http://host/service/$metadata#Customers
If the entities are contained, then entity-set is the top-level entity set followed by the path to the
containment navigation property of the containing entity.
Example 11: resource URL and corresponding context URL for contained entities
If the entities in the response are not bound to a single entity set, such as from a function or action with
no entity set path, a function import or action import with no specified entity set, or a navigation property
with no navigation property binding, the context URL specifies the type of the returned entity collection.
10.3 Entity
Context URL template:
{context-url}#{entity-set}/$entity
{context-url}#{type-name}
If a response or response part is a single entity of the declared type of an entity set, /$entity is
appended to the context URL.
Example 12: resource URL and corresponding context URL
http://host/service/Customers(1)
http://host/service/$metadata#Customers/$entity
If the entity is contained, then entity-set is the canonical URL for the containment navigation property
of the containing entity, e.g. Orders(4711)/Items.
Example 13: resource URL and corresponding context URL for contained entity
http://host/service/Orders(4711)/Items(1)
http://host/service/$metadata#Orders(4711)/Items/$entity
If the response is not bound to a single entity set, such as an entity returned from a function or action with
no entity set path, a function import or action import with no specified entity set, or a navigation property
with no navigation property binding, the context URL specifies the type of the returned entity.
10.4 Singleton
Context URL template:
{context-url}#{singleton}
If a response or response part is a singleton, its name is the context URL fragment.
Example 14: resource URL and corresponding context URL
http://host/service/Contoso
http://host/service/$metadata#Contoso
http://host/service/Customers/Model.VipCustomer
http://host/service/$metadata#Customers/Model.VipCustomer
http://host/service/Customers(2)/Model.VipCustomer
http://host/service/$metadata#Customers/Model.VipCustomer/$entity
http://host/service/Customers?$select=Address,Orders
http://host/service/$metadata#Customers(Address,Orders)
http://host/service/Customers(1)?$select=Name,Rating
http://host/service/$metadata#Customers(Name,Rating)/$entity
http://host/service/Customers$select=Name&$expand=Address/Country
http://host/service/$metadata#Customers(Name,Address/Country)
http://host/service/Employees/Sales.Manager?$select=DirectReports
&$expand=DirectReports($select=FirstName,LastName;$levels=4)
http://host/service/$metadata
#Employees/Sales.Manager(DirectReports,
DirectReports+(FirstName,LastName))
http://host/service/Employees(1)/Sales.Manager?
$expand=DirectReports($select=FirstName,LastName;$levels=4)
http://host/service/$metadata
#Employees/Sales.Manager(DirectReports+(FirstName,LastName))/$entity
http://host/service/Customers('ALFKI')/Orders/$ref
http://host/service/$metadata#Collection($ref)
http://host/service/Orders(10643)/Customer/$ref
http://host/service/$metadata#$ref
http://host/service/Customers(1)/Addresses
http://host/service/$metadata#Customers(1)/Addresses
http://host/service/TopFiveHobbies()
http://host/service/$metadata#Collection(Edm.String)
http://host/service/MostPopularName()
http://host/service/$metadata#Edm.String
http://host/service/TopFiveCustomers{}
http://host/service/$metadata#Customers
http://host/service/Customers?$deltaToken=1234
http://host/service/$metadata#Customers/$delta
http://host/service/Products(1)/Name
http://host/service/Products(1)/Name/$value
http://host/service/Products?$select=Rating,ReleaseDate
It is also possible to request all structural properties, including any dynamic properties, using the star
operator. The star operator SHOULD NOT introduce navigation properties, actions or functions not
otherwise requested.
Example 32:
http://host/service/Products?$select=*
Properties of related entities can be specified by including the $select query option within the $expand.
Example 33:
http://host/service/Products?$expand=Category($select=Name)
http://host/service/Categories?$select=CategoryName&$expand=Products
http://host/service/Categories?$select=CategoryName,Products&$expand=Products
It is also possible to request all actions or functions available for each returned entity.
Example 35:
http://host/service/Products?$select=DemoService.*
If the $select query option is not specified, the service returns the full set of properties or a default set
of properties. The default set of properties MUST include all key properties .
If the service returns less than the full set of properties, either because the client specified a select or
because the service returned a subset of properties in the absence of a select, the context URL MUST
reflect the set of selected properties and expanded navigation properties.
http://host/service.svc/Customers?$expand=Orders
Example 37: for each customer entity within the Customers entity set the references to the related Orders will be
represented inline
http://host/service.svc/Customers?$expand=Orders/$ref
http://host/service.svc/Customers?$expand=Orders($filter=Amount gt 100)
Example 39: for each order within the Orders entity set, the following will be represented inline:
The Items related to the Orders identified by the resource path section of the URL and the
products related to each order item.
The Customer related to each order returned.
http://host/service.svc/Orders?$expand=Items($expand=Product),Customer
Example 40: for each customer entity in the Customers entity set, the value of all related InHouseStaff will be
represented inline if the entity is of type VipCustomer or a subtype of that. For entities that are not of type
http://host/service.svc/Customers?$expand=SampleModel.VipCustomer/InHouseStaff
http://contoso.com/HR/Employees?$expand=Model.Manager/DirectReports($levels=4)
http://host/service/Products?$filter=Price lt 10.00
The $count segment may be used within a $filter expression to limit the items returned based on
the exact count of related entities or items within a collection-valued property.
Example 43: return all Categories with less than 10 products
http://host/service/Categories?$filter=Products/$count lt 10
Comparison Operators
eq Equal Address/City eq 'Redmond'
Logical Operators
and Logical and Price le 200 and Price gt 3.5
Arithmetic Operators
add Addition Price add 5 gt 10
Grouping Operators
( ) Precedence grouping (Price sub 5) gt 10
Function Example
String Functions
contains contains(CompanyName,'freds')
endswith endswith(CompanyName,'Futterkiste')
startswith startswith(CompanyName,'Alfr')
length length(CompanyName) eq 19
indexof indexof(CompanyName,'lfreds') eq 1
Date Functions
year year(BirthDate) eq 0
month month(BirthDate) eq 12
day day(StartTime) eq 8
hour hour(StartTime) eq 1
minute minute(StartTime) eq 0
second second(StartTime) eq 0
fractionalseconds second(StartTime) eq 0
totaloffsetminutes totaloffsetminutes(StartTime) eq 60
Math Functions
round round(Freight) eq 32
floor floor(Freight) eq 32
ceiling ceiling(Freight) eq 33
Type Functions
cast cast(ShipCountry,Edm.String)
isof isof(NorthwindModel.Order)
isof isof(ShipCountry,Edm.String)
Geo Functions
geo.distance geo.distance(CurrentPosition,TargetPosition)
geo.length geo.length(DirectRoute)
geo.intersects geo.intersects(Position,TargetArea)
http://host/service.svc/Employees?$filter=Region eq @p1&@p1='WA'
Parameter aliases allow the same value to be used multiple times in a request and may be used to
reference primitive values, complex, or collection values.
If a parameter alias is not given a value in the Query part of the request URL, the value MUST be
assumed to be null. A parameter alias can be used in multiple places within a request URL but its value
MUST NOT be specified more than once.
Related entities may be ordered by specifying $orderby within the $expand clause.
Example 46: return all Categories, and their Products ordered according to release date and in descending order of
rating
$count may be used within a $orderby expression to order the returned items according to the exact
count of related entities or items within a collection-valued property.
Example 47: return all Categories ordered by the number of Products within each category
http://host/service/Cateoriges?$orderby=Products/$count
http://host/service/Products?$top=5
If no unique ordering is imposed through an $orderby query option, the service MUST impose a stable
ordering across requests that include $top.
http://host/service/Products?$skip=5
Where $top and $skip are used together, $skip MUST be applied before $top, regardless of the
order in which they appear in the request.
Example 50: return the third through seventh products of the Products entity set
http://host/service/Products?$top=5&$skip=2
If no unique ordering is imposed through an $orderby query option, the service MUST impose a stable
ordering across requests that include $skip.
http://host/service/Products?$count=true
The count of related entities can be requested by specifying the $count query option within the
$expand clause.
Example 52:
http://host/service/Categories?$expand=Products($count=true)
A $count query option with a value of false (or not specified) hints that the service SHOULD NOT
return a count.
The service returns an HTTP Status code of 400 Bad Request if a value other than true or false is
specified.
http://host/service/Products?$search=bike
http://host/service/Products?$search="mountain bike"
The upper case keyword NOT restricts the set of entities to those that do not match the specified term.
Example 55: return all Products that do not match "clothing"
http://host/service/Products?$search=NOT clothing
Multiple terms within a search expression are separated by a space (implicit AND) or the upper-case
keyword AND, indicating that all such terms must be matched.
Example 56: return all Products that match both "mountain" and "bike"
The upper-case keyword OR is used to return entities that satisfy either the immediately preceding or
subsequent expression.
Example 57: return all Products that match either "mountain" or "bike"
http://host/service/Products?$search=mountain OR bike
The operations within a search expression MUST be evaluated in the following order: grouping operator,
NOT operator, AND operator, OR operator
If both $search and $filter are specified in the same request, only those entities satisfying both
criteria are returned.
The value of the $search option is a Boolean expression as defined in [OData-ABNF].
http://host/service/Products(1)/Supplier
http://host/service/Products(0)/Orders/$ref
http://host/service/$entity?$id=http://host/service/Products(0)
A type segment following the $entity resource casts the resource to the specified type. If the identified
entity is not of the specified type, or a type derived from the specified type, the service returns 404 Not
Found.
http://host/service/$entity/Model.Customer?
$id=http://host/service/Customers('ALFKI')
&$select=CompanyName,ContactName&$expand=Orders
http://host/service/Products/$count
Example 64: return the number of all products whose Price is less than $10.00
http://host/service/Products/$count?$filter=Price lt 10.00
The /$count segment can be used in combination with the $filter system query option.
Example 65: return all customers with more than five interests
http://host/service/Customers?$filter=Interests/$count gt 5
http://host/service/Orders?$format=application/json;odata.metadata=full
is equivalent to a request with an Accept header using the same media type; it requests the set of Order entities
represented using the JSON media type including full metadata, as specified in [OData-JSON].
Example 67: the request
http://host/service/Orders?$format=json
is equivalent to a request with the Accept header set to application/json; it requests the set of Order entities
represented using the JSON media type with minimal metadata, as specified in [OData-JSON].
The $format system query option MUST NOT be specified in batch requests as these always use the
media type multipart/mixed.
{
"@odata.type":"#Northwind.Manager",
"EmployeeID": 1,
"[email protected]": [
"http://host/service/Employees(5)",
"http://host/service/Employees(6)"
]
}
Example 69: using the Atom format the client can create a new manager entity with links to two existing employees
by including a navigation link element for each employee in the Atom entry representing the manager
<entry>
<id> http://host/service /Employees(1)</id>
<title type="text" />
<updated>2011-02-16T01:00:25Z</updated>
<author><name /></author>
<link rel="http://docs.oasis-open.org/odata/ns/related/DirectReports"
odata-v4.0-errata02-os-part1-protocol-complete 30 October 2014
Standards Track Work Product Copyright © OASIS Open 2014. All Rights Reserved. Page 50 of 74
href="http://host/service/Employees(5)"
type="application/atom+xml;type=entry"
title="Direct Reports" />
<link rel="http://docs.oasis-open.org/odata/ns/related/DirectReports"
href="http://host/service/Employees(6)"
type="application/atom+xml;type=entry"
title="Direct Reports" />
<category term="NorthwindModel.Manager"
scheme="http://odata.org/scheme"/>
<content type="application/xml">
<metadata:properties>
<data:EmployeeID>1</data:EmployeeID>
</metadata:properties>
</content>
</entry>
Upon successful completion of the operation, the service creates the requested entity and relates it to the
requested existing entities.
If the target URL for the collection the entity is created in and binding information provided in the POST
body contradicts the implicit binding information provided by the request URL, the request MUST fail and
the service respond with 400 Bad Request.
Upon failure of the operation, the service MUST NOT create the new entity. In particular, the service
MUST never create an entity in a partially-valid state (with the navigation property unset).
11.5 Operations
Custom operations (Actions and Functions) are represented as Action, ActionImport, Function,
and FunctionImport elements in [OData-CSDL].
Example 71: invoking the MostRecentOrder function with the value of the binding parameter customer being the
entity identified by http://host/service/Customers(6)
http://host/service/Customers(6)/SampleModel.MostRecentOrder()
{
"@odata.context": ...,
"#SampleEntities.MostRecentOrder": {
"title": "Most Recent Order",
"target": "Customers('ALFKI')/SampleEntities.MostRecentOrder()"
},
"CustomerID": "ALFKI",
"CompanyName": "Alfreds Futterkiste",
...
}
11.5.3 Functions
Functions are operations exposed by an OData service that MUST return data and MUST have no
observable side effects.
POST http://host/service/MyShoppingCart()/Items
...
Parameter values passed to functions MUST be specified either as a URL literal (for primitive types) or as
a JSON formatted OData object (for complex types or collections of primitive types or complex types).
If a collection-valued function has no result for a given parameter value combination, the response is the
format-specific representation of an empty collection. If a single-valued function with a nullable return-type
has no result, the service returns 204 No Content.
If a single-valued function with a non-nullable return type has no result, the service returns 4xx. For
functions that return a single entity 404 Not Found is the appropriate response code.
For a composable function the processing is stopped when the function result requires a 4xx response,
and continues otherwise.
Function imports MUST NOT be used inside either the $filter or $orderby system query options.
http://host/service/EmployeesByManager(ManagerID=3)
Example 75: return all Customers whose City property returns "Western" when passed to the
Sales.SalesRegion function
http://host/service/Customers?
$filter=Sales.SalesRegion(City=$it/City) eq 'Western'
A parameter alias can be used in place of an inline parameter to a function call. The value for the alias is
specified as a separate query option using the name of the parameter alias.
Example 76: invoke a Sales.EmployeesByManager function via the function import EmployeesByManager,
passing 3 for the ManagerID parameter
http://host/service/EmployeesByManager(ManagerID=@p1)?@p1=3
11.5.4 Actions
Actions are operations exposed by an OData service that MAY have side effects when invoked. Actions
MAY return data but MUST NOT be further composed with additional path segments.
POST http://host/service/Customers('ALFKI')/SampleEntities.CreateOrder
{
"quantity": 2,
"discountCode": "BLACKFRIDAY"
}
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: application/http
Content-Transfer-Encoding:binary
GET /service/Customers('ALFKI')
Host: host
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed;boundary=changeset_77162fcd-b8da-41ac-a9f8-
9357efbbd
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed;boundary=changeset_77162fcd-b8da-41ac-a9f8-
9357efbbd
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
HTTP/1.1 200 Ok
OData-Version: 4.0
Content-Length: ####
Content-Type: multipart/mixed;boundary=b_243234_25424_ef_892u748
--b_243234_25424_ef_892u748
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 200 Ok
Content-Type: application/atom+xml;type=entry
Content-Length: ###
--cs_12u7hdkin252452345eknd_383673037
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
--cs_12u7hdkin252452345eknd_383673037--
--b_243234_25424_ef_892u748
Content-Type: application/http
Content-Transfer-Encoding: binary
<Error message>
--b_243234_25424_ef_892u748--
HTTP/1.1 200 Ok
OData-Version: 4.0
Content-Length: ####
Content-Type: multipart/mixed;boundary=b_243234_25424_ef_892u748
--b_243234_25424_ef_892u748
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 200 Ok
Content-Type: application/atom+xml;type=entry
Content-Length: ###
HTTP/1.1 200 Ok
OData-Version: 4.0
Content-Length: ####
Content-Type: multipart/mixed;boundary=b_243234_25424_ef_892u748
--b_243234_25424_ef_892u748
Content-Type: multipart/mixed;boundary=cs_12u7hdkin252452345eknd_383673037
--cs_12u7hdkin252452345eknd_383673037
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
--cs_12u7hdkin252452345eknd_383673037--
--b_243234_25424_ef_892u748
Content-Type: application/http
Content-Transfer-Encoding: binary
<Error message>
--b_243234_25424_ef_892u748—
12.1 Authentication
OData Services requiring authentication SHOULD consider supporting basic authentication as specified
in [RFC2617] over HTTPS for the highest level of interoperability with generic clients. They MAY support
other authentication methods.
Committee 2013-07-01 Michael Pizzo, Cleaned up action and function overloads and
Specification Ralf Handl, binding, removed old-style function parameter
Draft 02 Martin Zurmuehl syntax
Improved asynchronous processing and added
callback notifications
Improved context URL (formerly: metadata
URL)
Improved handling of empty results
Improved description of rules for processing
PUT and POST requests, especially deep
inserts
Harmonized $count and $inlinecount
Committee 2013-07-30 Michael Pizzo, Non-Material Changes
Specification 01 Ralf Handl,
Martin Zurmuehl