diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index bae8b6b8..4dbc9382 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2270,15 +2270,21 @@
If the target URL terminates in a type cast segment, then the segment MUST specify the type of, or a type derived from, the type of the collection, and the entity MUST be created as that specified type.
To create an open entity (an instance of an open type), additional property values beyond those specified in the metadata MAY be sent in the request body. The service MUST treat these as dynamic properties and add them to the created instance.
If the entity being created is not an open entity, additional property values beyond those specified in the metadata SHOULD NOT be sent in the request body. The service MUST fail if unable to persist all property values specified in the request.
-Non-insertable properties SHOULD be omitted from the request body. If they are provided, services MUST either ignore the values in the request body or fail the request if the provided values do not match the service-determined values.
+If non-insertable properties are included in the request body, services MUST either ignore them or fail the request if the provided values do not match the service-determined values.
Non-insertable properties include (and are not limited to)
Core.Computed
, see OData-VocCore,Core.Computed
, see OData-VocCore,NonInsertableProperties
of term Capabilities.InsertRestrictions
, see OData-VocCap,Core.Permissions
, see OData-VocCore, where the annotation value does not have the Write
flag.Services MUST return an error if the request body contains a value for a property that in principle can be specified on insert but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object. Properties with a default value, nullable properties, and collection-valued properties omitted from the request are set to the default value, null, or an empty collection, respectively.
+Properties tagged with Core.Computed
MAY additionally be tagged with the term Core.PostCondition
, see OData-VocCore, if the service does not ignore them. Based on this tag (or based on out-of-band knowledge about the service behavior) clients can provide these properties in an insert request and benefit from the certainty that, if the request succeeds, their service-determined values match the provided values. Providing such properties effectively imposes “post-conditions” that must be met for the request to succeed.
Otherwise, clients SHOULD omit non-insertable properties from the request body.
+Example 76: The entity SalesOrder
has a property ExportRegulationsState
which is tagged with Core.Computed
and Core.PostCondition
and which the service determines based on the product and destination country. Clients can specify it with value Allowed
to impose a “post-condition” that a sales order is created only if it meets export regulations.
Services MUST return an error if the request body contains a value for a property that in principle can be specified on insert but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object.
+Properties with a default value, nullable properties, and collection-valued properties omitted from the request are set to the default value, null, or an empty collection, respectively.
Services MAY add dynamic properties to the created entity as long as their names do not conflict with the names of declared properties and client-specified dynamic properties.
Upon successful creation of the entity, the service MUST respond with either 201 Created
and a representation of the created entity, or 204 No Content
if the request included a return=minimal
preference and did not include the system query options $select
and $expand
, or if a representation of the created entity could not be constructed. In either case, if the service is able to construct the edit URL or read URL of the created entity, the response MUST contain that URL in a Location
header.
Example 76: using the JSON format, 4.0 clients can create a new manager entity with links to an existing manager (of managers) and to two existing employees by applying the odata.bind
annotation to the Manager
and DirectReports
navigation properties
Example 77: using the JSON format, 4.0 clients can create a new manager entity with links to an existing manager (of managers) and to two existing employees by applying the odata.bind
annotation to the Manager
and DirectReports
navigation properties
Example 77: using the JSON format, 4.01 clients can create a new manager entity with links to an existing manager (of managers) and to two existing employees by including the entity-ids within the Manager
and DirectReports
navigation properties
Example 78: using the JSON format, 4.01 clients can create a new manager entity with links to an existing manager (of managers) and to two existing employees by including the entity-ids within the Manager
and DirectReports
navigation properties
{
"@type": "#Northwind.Manager",
"ID": 1,
@@ -2344,12 +2350,12 @@ 1
- key properties,
- dependent properties that are tied to non-key properties of the principal entity through a referential constraint OData-CSDL, section 8.5 (informally: “denormalized” properties),
-- properties annotated with the terms
Core.Computed
or Core.Immutable
, see OData-VocCore,
+- properties tagged with the terms
Core.Computed
or Core.Immutable
, see OData-VocCore,
- properties listed as
NonUpdatableProperties
of term Capabilities.UpdateRestrictions
, see OData-VocCap,
- properties annotated with term
Core.Permissions
, see OData-VocCore, where the annotation value does not have the Write
flag.
Services MUST return an error if the request body contains a value for a property that in principle can be specified on update but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object.
-Clients SHOULD use PATCH
and specify only those properties intended to be changed.
+Clients can provide non-updatable properties to impose “post-conditions” as explained for non-insertable properties. Otherwise, clients SHOULD use PATCH
and specify only those properties intended to be changed.
The entity-id cannot be changed when updating an entity. However, format-specific rules might in some cases require providing the entity-id in the payload when requesting the update.
For requests with an OData-Version
header with a value of 4.01
or greater, if the entity representation in the request body includes an ETag value, the update MUST NOT be performed and SHOULD return 412 Precondition Failed
if the supplied ETag value is not *
and does not match the current ETag value for the entity. ETag values in request bodies MUST be ignored for requests containing an OData-Version header with a value of 4.0
.
If an update specifies both a binding to a single-valued navigation property and a dependent property that is tied to a key property of the principal entity according to the same navigation property, then the dependent property is ignored, and the relationship is updated according to the value specified in the binding.
@@ -2362,7 +2368,7 @@ delta payload representing the related entities that have been added, removed, or changed. Such a request is referred to as a “deep update”. If the nested collection is represented identical to an expanded navigation property, then the set of nested entities and entity references specified in a successful update request represents the full set of entities to be related according to that relationship and MUST NOT include added links, deleted links, or deleted entities.
-Example 78: using the JSON format, a 4.01 PATCH
request can update a manager entity. Following the update, the manager has three direct reports; two existing employees and one new employee named Suzanne Brown
. The LastName
of employee 6 is updated to Smith
.
+Example 79: using the JSON format, a 4.01 PATCH
request can update a manager entity. Following the update, the manager has three direct reports; two existing employees and one new employee named Suzanne Brown
. The LastName
of employee 6 is updated to Smith
.
{
"@type": "#Northwind.Manager",
"FirstName": "Patricia",
@@ -2384,7 +2390,7 @@ delta payload format. If the deleted entity specifies a reason
as deleted
, then the entity is both removed from the collection and deleted, otherwise it is removed from the collection and only deleted if the relationship is contained. Non-key properties of the deleted entity are ignored. Nested collections MUST NOT contain added or deleted links. If the request contains nested delta collections, then the PATCH
verb must be specified.
If a nested entity has the same id or key fields as an existing entity, the existing entity is updated according to the semantics of the PUT
or PATCH
request. Nested entities that have no id or key fields, or for which the id or key fields do not match existing entities, are treated as inserts. If the nested collection does not represent a containment relationship and has no navigation property binding, then such entities MUST include a context URL specifying the entity set in which the new entity is to be created. If any nested entities contain both id and key fields, they MUST identify the same entity, or the request is invalid.
-Example 79: using the JSON format, a 4.01 PATCH
request can specify a nested delta representation to:
+Example 80: using the JSON format, a 4.01 PATCH
request can specify a nested delta representation to:
- delete employee 3 and remove link to it
- remove the link to employee 4 and do not delete it
@@ -2524,7 +2530,7 @@ An entity may have one or more stream properties. Stream properties are properties of type Edm.Stream
.
The values for stream properties do not usually appear in the entity payload unless explicitly requested with $expand
. Instead, the values are generally read or written through URLs.
-Example 80: read an entity and select a stream property
+Example 81: read an entity and select a stream property
GET http://host/service/Products(1)?$select=Thumbnail
would only include control information for the stream property, not the stream data itself
{
@@ -2539,7 +2545,7 @@
Services SHOULD support direct property access to a stream property’s canonical URL. The response MAY be a redirect to the media read link of the stream property if the media read link is different from the canonical URL.
-Example 81: directly read a stream property of an entity
+Example 82: directly read a stream property of an entity
GET http://host/service/Products(1)/Thumbnail
can return 200 OK
and the stream data (see section 11.2.4.1), or a 3xx Redirect
to the media read link of the stream property.
@@ -2559,7 +2565,7 @@
-Example 82: delete the stream value using the media edit link retrieved in example 80
+Example 83: delete the stream value using the media edit link retrieved in example 81
DELETE http://server/uploads/Thumbnail546.jpg
Attempting to request a stream property whose value is null results in 204 No Content
.
@@ -2621,7 +2627,7 @@ Core.PositionalInsert
term (see OData-VocCore) support inserting items at a specific location via POST
requests to the collection URL using the $index
system query option. The value of the $index
system query option is the zero-based ordinal position where the item is to be inserted. The ordinal positions of items within the collection greater than or equal to the inserted position are increased by one. A negative ordinal number indexes from the end of the collection, with -1 representing an insert as the last item in the collection.
-Example 83: Insert a new email address at the second position
+Example 84: Insert a new email address at the second position
POST /service/Customers('ALFKI')/EmailAddresses?$index=1
Content-Type: application/json
@@ -2682,7 +2688,7 @@ updated using PATCH
semantics. Structured types MAY include nested collections or delta collections, in which case the semantics described in Update a Collection of Entities applies.
-Example 84: change the color of all beige-brown products
+Example 85: change the color of all beige-brown products
PATCH /service/Products/$filter(@bar)/$each?@bar=Color eq 'beige-brown'
Content-Type: application/json
@@ -2701,7 +2707,7 @@
-Example 85: delete all products older than 3
+Example 86: delete all products older than 3
DELETE /service/Products/$filter(Age gt 3)/$each
If the path identifies a collection of entities and if the service returns a representation, then the response is a delta response containing a representation of a deleted entity for each deleted member.
@@ -2720,25 +2726,25 @@ Actions and Functions MAY be bound to any type or collection, similar to defining a method in a class in object-oriented programming. The first parameter of a bound operation is the binding parameter.
The namespace- or alias-qualified name of a bound operation may be appended to any URL that identifies a resource whose type matches, or is derived from, the type of the binding parameter. The resource identified by that URL is used as the binding parameter value. Only aliases defined in the metadata document of the service can be used in URLs.
-Example 86: the function MostRecentOrder
can be bound to any URL that identifies a SampleModel.Customer
+Example 87: the function MostRecentOrder
can be bound to any URL that identifies a SampleModel.Customer
Function Name="MostRecentOrder" IsBound="true">
<Parameter Name="customer" Type="SampleModel.Customer" />
<ReturnType Type="SampleModel.Order" />
<Function> </
-Example 87: invoke the MostRecentOrder
function with the value of the binding parameter customer
being the entity identified by http://host/service/Customers(6)
+Example 88: invoke the MostRecentOrder
function with the value of the binding parameter customer
being the entity identified by http://host/service/Customers(6)
GET http://host/service/Customers(6)/SampleModel.MostRecentOrder()
-Example 88: the function Comparison
can be bound to any URL that identifies a collection of entities
+Example 89: the function Comparison
can be bound to any URL that identifies a collection of entities
Function Name="Comparison" IsBound="true">
<Parameter Name="in" Type="Collection(Edm.EntityType)" />
<ReturnType Type="Diff.Overview" />
<Function> </
-Example 89: invoke the Comparison
function on the set of red products
+Example 90: invoke the Comparison
function on the set of red products
GET http://host/service/Products/$filter(Color eq 'Red')/Diff.Comparison()
@@ -2749,7 +2755,7 @@
-Example 90: invoke the MostRecentOrder
function on each entity in the entity set Customers
+Example 91: invoke the MostRecentOrder
function on each entity in the entity set Customers
GET http://host/service/Customers/$each/SampleModel.MostRecentOrder()
The client MAY specify the continue-on-error
preference, in which case the service MAY continue processing actions after a failure. In this case, the service MUST, regardless of the return
preference, return a response containing at least the members identified by the request for which the action failed. Such members MUST be annotated with the term Core.DataModificationException
with a failedOperation
value of invoke
.
@@ -2760,7 +2766,7 @@ format.
-Example 91: given a GET
request to http://host/service/Customers('ALFKI')
, the service might respond with a Customer that includes the SampleEntities.MostRecentOrder
function bound to the entity
+Example 92: given a GET
request to http://host/service/Customers('ALFKI')
, the service might respond with a Customer that includes the SampleEntities.MostRecentOrder
function bound to the entity
{
"@context": …,
"CustomerID": "ALFKI",
@@ -2775,7 +2781,7 @@ OData-URL.
Services can advertise that a function or action is not available for a particular instance by setting its value to null.
-Example 92: the SampleEntities.MostRecentOrder
function is not available for customer ALFKI
+Example 93: the SampleEntities.MostRecentOrder
function is not available for customer ALFKI
{
"@context": …,
"CustomerID": "ALFKI",
@@ -2800,7 +2806,7 @@ inline parameter syntax. The canonical URL for a function import is the service root, followed by the name of the function import. Services MAY support omitting the parentheses when invoking a function import with no parameters, but for maximum interoperability MUST also support invoking the function import with empty parentheses.
If the function is composable, additional path segments may be appended to the URL that identifies the composable function (or function import) as appropriate for the type returned by the function (or function import). The last path segment determines the system query options and HTTP verbs that can be used with this this URL, e.g. if the last path segment is a multi-valued navigation property, a POST
request may be used to create a new entity in the identified collection.
-Example 93: add a new item to the list of items of the shopping cart returned by the composable MyShoppingCart
function import
+Example 94: add a new item to the list of items of the shopping cart returned by the composable MyShoppingCart
function import
POST http://host/service/MyShoppingCart()/Items
…
@@ -2817,22 +2823,22 @@
-Example 94: invoke a Sales.EmployeesByManager
function which takes a single ManagerID
parameter via the function import EmployeesByManager
+Example 95: invoke a Sales.EmployeesByManager
function which takes a single ManagerID
parameter via the function import EmployeesByManager
GET http://host/service/EmployeesByManager(ManagerID=3)
-Example 95: return all Customers whose City
property returns Western
when passed to the Sales.SalesRegion
function
+Example 96: return all Customers whose City
property returns Western
when passed to the Sales.SalesRegion
function
GET http://host/service/Customers?
$filter=Sales.SalesRegion(City=$it/City) eq 'Western'
A parameter alias can be used in place of an inline parameter value. The value for the alias is specified as a separate query option using the name of the parameter alias.
-Example 96: invoke a Sales.EmployeesByManager
function via the function import EmployeesByManager
, passing 3 for the ManagerID
parameter
+Example 97: invoke a Sales.EmployeesByManager
function via the function import EmployeesByManager
, passing 3 for the ManagerID
parameter
GET http://host/service/EmployeesByManager(ManagerID=@p1)?@p1=3
Services MAY in addition allow implicit parameter aliases for function imports and for functions that are the last path segment of the URL. An implicit parameter alias is the parameter name, optionally preceded by an at (@
) sign. When using implicit parameter aliases, parentheses MUST NOT be appended to the function (import) name. The value for each parameter MUST be specified as a separate query option with the name of the parameter alias. If a parameter name is identical to a system query option name (without the optional $
prefix), the parameter name MUST be prefixed with an at (@
) sign.
-Example 97: invoke a Sales.EmployeesByManager
function via the function import EmployeesByManager
, passing 3 for the ManagerID
parameter using the implicit parameter alias
+Example 98: invoke a Sales.EmployeesByManager
function via the function import EmployeesByManager
, passing 3 for the ManagerID
parameter using the implicit parameter alias
GET http://host/service/EmployeesByManager?ManagerID=3
Non-binding parameters annotated with the term Core.OptionalParameter
defined in OData-VocCore MAY be omitted. If it is annotated and the annotation specifies a DefaultValue
, the omitted parameter is interpreted as having that default value. If omitted and the annotation does not specify a default value, the service is free on how to interpret the omitted parameter.
@@ -2872,7 +2878,7 @@ 204 No Content
on success.
To request processing of the action only if the binding parameter value, an entity or collection of entities, is unmodified, the client includes the If-Match
header with the latest known ETag value for the entity or collection of entities. The ETag value for a collection as a whole is transported in the ETag
header of a collection response.
-Example 98: invoke the SampleEntities.CreateOrder
action using Customers('ALFKI')
as the customer (or binding parameter). The values 2
for the quantity
parameter and BLACKFRIDAY
for the discountCode
parameter are passed in the body of the request. Invoke the action only if the customer’s ETag still matches.
+Example 99: invoke the SampleEntities.CreateOrder
action using Customers('ALFKI')
as the customer (or binding parameter). The values 2
for the quantity
parameter and BLACKFRIDAY
for the discountCode
parameter are passed in the body of the request. Invoke the action only if the customer’s ETag still matches.
POST http://host/service/Customers('ALFKI')/SampleEntities.CreateOrder
If-Match: W/"MjAxOS0wMy0yMVQxMzowNVo="
Content-Type: application/json
@@ -2923,7 +2929,7 @@ multipart batch format MUST contain a Content-Type
header specifying a content type of multipart/mixed
and a boundary
parameter as defined in RFC2046.
-Example 99: multipart batch request
+Example 100: multipart batch request
POST /service/$batch HTTP/1.1
Host: odata.org
OData-Version: 4.0
@@ -2933,7 +2939,7 @@
-Example 100: JSON batch request
+Example 101: JSON batch request
POST /service/$batch HTTP/1.1
Host: odata.org
OData-Version: 4.01
@@ -2960,7 +2966,7 @@ 11.7.4 Referencing Returned Entities
-Entities created by an insert request or an action can be referenced in the request URL of subsequent requests by using the request identifier prefixed with a $
character as the first segment of the request URL. Services MUST treat this segment like the URL in the Location
header of the response to the request identified by the segment. If the Location
header in the response to the subsequent request contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference. See example 105.
+Entities created by an insert request or an action can be referenced in the request URL of subsequent requests by using the request identifier prefixed with a $
character as the first segment of the request URL. Services MUST treat this segment like the URL in the Location
header of the response to the request identified by the segment. If the Location
header in the response to the subsequent request contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference. See example 106.
If the $
-prefixed request identifier is identical to the name of a top-level system resource ($batch
, $crossjoin
, $all
, $entity
, $root
, $id
, $metadata
, or other system resources defined according to the OData-Version
of the protocol specified in the request), then the reference to the top-level system resource is used. This collision can be avoided by e.g. using only numeric request identifiers.
Services MAY also support referencing within request bodies, in which case they SHOULD advertise this support by specifying the ReferencesInRequestBodiesSupported
property in the Capabilities.BatchSupport
term applied to the entity container, see OData-VocCap.
@@ -2994,14 +3000,14 @@ Absolute URI with schema, host, port, and absolute resource path.
-Example 101:
+Example 102:
GET https://host:1234/path/service/People(1) HTTP/1.1
- Absolute resource path and separate
Host
header
-Example 102:
+Example 103:
PATCH /path/service/People(1) HTTP/1.1
Host: myserver.mydomain.org:1234
Content-Type: application/json
@@ -3012,7 +3018,7 @@ Resource path relative to the batch request URI.
-Example 103:
+Example 104:
DELETE People(1) HTTP/1.1
Services MUST support all three formats for URLs of individual requests.
@@ -3024,7 +3030,7 @@
Processors of batch requests MAY choose to disallow additional HTTP constructs in HTTP requests serialized within body parts. For example, a processor may choose to disallow chunked encoding to be used by such HTTP requests.
-Example 104: a batch request that contains the following individual requests in the order listed
+Example 105: a batch request that contains the following individual requests in the order listed
- A query request
- A change set that contains the following requests:
@@ -3090,7 +3096,7 @@
insert request or an action can be referenced in the request URL of subsequent requests within the same change set. Services MAY also support referencing across change sets, in which case they SHOULD advertise this support by specifying the ReferencesAcrossChangeSetsSupported
property in the Capabilities.BatchSupport
term applied to the entity container, see OData-VocCap.
-Example 105: a batch request that contains the following operations in the order listed:
+Example 106: a batch request that contains the following operations in the order listed:
A change set that contains the following requests:
- Insert a new entity (with
Content-ID = 1
)
@@ -3150,14 +3156,14 @@ example 102). This gives the effective second request URL http://host/service/Customers('ALFKI')/Orders
as base URI for the second Location
URL, which therefore resolves to http://host/service/Customers('ALFKI')/Orders(1)
.
+
The second Location
URL Orders(1)
is relative with its base URI being the second request URL $1/Orders
. To get an absolute base URI, the client must replace the $1
with the first Location
URL Customers('ALFKI')
and resolve the resulting URL Customers('ALFKI')/Orders(1)
relative to its base URI, which is http://host/service/Customers
(determined from the first request URL /service/Customers
and the Host: host
header as in example 103). This gives the effective second request URL http://host/service/Customers('ALFKI')/Orders
as base URI for the second Location
URL, which therefore resolves to http://host/service/Customers('ALFKI')/Orders(1)
.
11.7.7.3 Referencing an ETag
-Example 106: a batch request that contains the following operations in the order listed:
+Example 107: a batch request that contains the following operations in the order listed:
- Get an employee (with
Content-ID = 1
)
- Update the salary only if the employee has not changed
@@ -3197,7 +3203,7 @@ 11.7.7.4 Referencing Response Body Values
-Example 107: a batch request that contains the following operations in the order listed:
+Example 108: a batch request that contains the following operations in the order listed:
- Get an employee (with
Content-ID = 1
)
- Get all employees residing in the same building
@@ -3246,9 +3252,9 @@ Asynchronously processed batch requests can return interim results and end with a 202 Accepted
as the last part of the multipart response. Therefore, the respond-async
preference MUST NOT be applied to individual requests within a batch if the batch response is a multipart response.
The body of a multipart response to a JSON batch request contains one body part for each processed or accepted request. The order of the body parts is insignificant as each body part MUST contain the Content-ID
header with the value of the id
name/value pair of the corresponding request object.
-A response to an operation in a batch MUST be formatted exactly as it would have appeared outside of a batch as described in the corresponding subsections of chapter Data Service Requests. Relative URLs in each individual response are relative to the request URL of the corresponding individual request (see example 105). URLs in responses MUST NOT contain $
-prefixed request identifiers.
+A response to an operation in a batch MUST be formatted exactly as it would have appeared outside of a batch as described in the corresponding subsections of chapter Data Service Requests. Relative URLs in each individual response are relative to the request URL of the corresponding individual request (see example 106). URLs in responses MUST NOT contain $
-prefixed request identifiers.
-Example 108: referencing the batch request example 104 above, assume all the requests except the final query request succeed. In this case the response would be
+Example 109: referencing the batch request example 105 above, assume all the requests except the final query request succeed. In this case the response would be
HTTP/1.1 200 OK
OData-Version: 4.0
Content-Length: ####
@@ -3302,7 +3308,7 @@ A service MAY return interim results to an asynchronously executing batch. It does this by responding with 200 OK
to a GET
request to the monitor resource and including a 202 Accepted
response as the last part of the multipart response. The client can use the monitor URL returned in this 202 Accepted
response to continue processing the batch response.
Since a change set is executed atomically, 202 Accepted
MUST NOT be returned within a change set.
-Example 109: referencing the example 104 above again, assume that
+Example 110: referencing the example 105 above again, assume that
HTTP/1.1 202 Accepted
Location: http://service-root/async-monitor-0
Retry-After: ###
diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md
index 8ac825c9..0adfc8ac 100644
--- a/docs/odata-protocol/odata-protocol.md
+++ b/docs/odata-protocol/odata-protocol.md
@@ -4180,20 +4180,40 @@ values beyond those specified in the metadata SHOULD NOT be sent in the
request body. The service MUST fail if unable to persist all property
values specified in the request.
-Non-insertable properties SHOULD be omitted from the request body.
-If they are provided, services MUST either ignore the values in the request body or fail the request
+If non-insertable properties are included in the request body,
+services MUST either ignore them or fail the request
if the provided values do not match the service-determined values.
Non-insertable properties include (and are not limited to)
- dependent properties that are tied to non-key properties of the principal entity through a referential constraint [OData-CSDL, section 8.5](#ODataCSDL) (informally: "denormalized" properties),
-- properties annotated with the term
+- properties tagged with the term
[`Core.Computed`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Computed), see [OData-VocCore](#ODataVocCore),
- properties listed as `NonInsertableProperties` of term [`Capabilities.InsertRestrictions`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Capabilities.V1.md#InsertRestrictions), see [OData-VocCap](#ODataVocCap),
- properties annotated with term
[`Core.Permissions`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Permissions), see [OData-VocCore](#ODataVocCore), where the annotation value does not have the `Write` flag.
+Properties tagged with `Core.Computed` MAY additionally be tagged with the term
+[`Core.PostCondition`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#PostCondition),
+see [OData-VocCore](#ODataVocCore), if the service does not ignore them.
+Based on this tag (or based on out-of-band knowledge about the service behavior)
+clients can provide these properties in an insert request
+and benefit from the certainty that, if the request succeeds, their service-determined values match
+the provided values. Providing such properties effectively imposes "post-conditions"
+that must be met for the request to succeed.
+
+Otherwise, clients SHOULD omit non-insertable properties from the request body.
+
+::: example
+Example 76: The entity `SalesOrder` has a property `ExportRegulationsState`
+which is tagged with `Core.Computed` and `Core.PostCondition` and which
+the service determines based on the product and destination country.
+Clients can specify it with value `Allowed` to impose a "post-condition" that a sales order is created
+only if it meets export regulations.
+:::
+
Services MUST return an error if the request body contains a value for a property that in principle can be specified on insert but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object.
+
Properties with a default value, nullable properties, and
collection-valued properties omitted from the request are set to the
default value, null, or an empty collection, respectively.
@@ -4220,7 +4240,7 @@ request body.
The representation for referencing related entities is format-specific.
::: example
-Example 76: using the JSON format, 4.0 clients can create a new manager
+Example 77: using the JSON format, 4.0 clients can create a new manager
entity with links to an existing manager (of managers) and to two existing employees by applying the `odata.bind`
annotation to the `Manager` and `DirectReports` navigation properties
@@ -4241,7 +4261,7 @@ annotation to the `Manager` and `DirectReports` navigation properties
:::
::: example
-Example 77: using the JSON format, 4.01 clients can create a new manager
+Example 78: using the JSON format, 4.01 clients can create a new manager
entity with links to an existing manager (of managers) and to two existing employees by including the entity-ids
within the `Manager` and `DirectReports` navigation properties
@@ -4378,7 +4398,7 @@ Non-updatable properties include (and are not limited to)
- key properties,
- dependent properties that are tied to non-key properties of the principal entity through a referential constraint [OData-CSDL, section 8.5](#ODataCSDL) (informally: "denormalized" properties),
-- properties annotated with the terms
+- properties tagged with the terms
[`Core.Computed`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Computed) or [`Core.Immutable`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Immutable), see [OData-VocCore](#ODataVocCore),
- properties listed as `NonUpdatableProperties` of term [`Capabilities.UpdateRestrictions`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Capabilities.V1.md#UpdateRestrictions), see [OData-VocCap](#ODataVocCap),
- properties annotated with term
@@ -4387,7 +4407,9 @@ Non-updatable properties include (and are not limited to)
Services MUST return an error if the request body contains a value for a
property that in principle can be specified on update but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object.
-Clients SHOULD use `PATCH` and specify only those properties intended to be changed.
+Clients can provide non-updatable properties to impose "post-conditions" as explained
+for [non-insertable properties](#CreateanEntity). Otherwise,
+clients SHOULD use `PATCH` and specify only those properties intended to be changed.
The entity-id cannot be changed when updating an entity.
However, format-specific rules might in some cases require providing
@@ -4451,7 +4473,7 @@ set of entities to be related according to that relationship and MUST
NOT include added links, deleted links, or deleted entities.
::: example
-Example 78: using the JSON format, a 4.01 `PATCH` request can update a
+Example 79: using the JSON format, a 4.01 `PATCH` request can update a
manager entity. Following the update, the manager has three direct
reports; two existing employees and one new employee named
`Suzanne Brown`. The `LastName` of employee 6 is updated to `Smith`.
@@ -4501,7 +4523,7 @@ entity is to be created. If any nested entities contain both id and key
fields, they MUST identify the same entity, or the request is invalid.
::: example
-Example 79: using the JSON format, a 4.01 `PATCH` request can specify a
+Example 80: using the JSON format, a 4.01 `PATCH` request can specify a
nested delta representation to:
- delete employee 3 and
@@ -4793,7 +4815,7 @@ payload unless explicitly requested with [`$expand`](#SystemQueryOptionexpand).
Instead, the values are generally read or written through URLs.
::: example
-Example 80: read an entity and select a stream property
+Example 81: read an entity and select a stream property
```
GET http://host/service/Products(1)?$select=Thumbnail
@@ -4824,7 +4846,7 @@ The response MAY be a redirect to the media read link of the stream property
if the media read link is different from the canonical URL.
::: example
-Example 81: directly read a stream property of an entity
+Example 82: directly read a stream property of an entity
```
GET http://host/service/Products(1)/Thumbnail
@@ -4875,7 +4897,7 @@ attempts to set the property to null and results in an error if the
property is non-nullable.
::: example
-Example 82: delete the stream value using the media edit link retrieved in [example 80](#entityWithStreamProperty)
+Example 83: delete the stream value using the media edit link retrieved in [example 81](#entityWithStreamProperty)
```
DELETE http://server/uploads/Thumbnail546.jpg
@@ -5029,7 +5051,7 @@ ordinal number indexes from the end of the collection, with -1
representing an insert as the last item in the collection.
::: example
-Example 83: Insert a new email address at the second position
+Example 84: Insert a new email address at the second position
```json
POST /service/Customers('ALFKI')/EmailAddresses?$index=1
@@ -5191,7 +5213,7 @@ semantics described in [Update a Collection of
Entities](#UpdateaCollectionofEntities) applies.
::: example
-Example 84: change the color of all beige-brown products
+Example 85: change the color of all beige-brown products
```json
PATCH /service/Products/$filter(@bar)/$each?@bar=Color eq 'beige-brown'
@@ -5237,7 +5259,7 @@ The request resource path of the collection MAY contain type-cast or
filter segments to subset the collection.
::: example
-Example 85: delete all products older than 3
+Example 86: delete all products older than 3
```
DELETE /service/Products/$filter(Age gt 3)/$each
@@ -5289,7 +5311,7 @@ by that URL is used as the *binding parameter value*. Only aliases
defined in the metadata document of the service can be used in URLs.
::: example
-Example 86: the function `MostRecentOrder` can be bound to any URL that
+Example 87: the function `MostRecentOrder` can be bound to any URL that
identifies a `SampleModel.Customer`
```xml
@@ -5300,7 +5322,7 @@ identifies a `SampleModel.Customer`
:::
::: example
-Example 87: invoke the `MostRecentOrder` function with the value of the
+Example 88: invoke the `MostRecentOrder` function with the value of the
binding parameter `customer` being the entity identified by
`http://host/service/Customers(6)`
```
@@ -5309,7 +5331,7 @@ GET http://host/service/Customers(6)/SampleModel.MostRecentOrder()
:::
::: example
-Example 88: the function `Comparison` can be bound to any URL that
+Example 89: the function `Comparison` can be bound to any URL that
identifies a collection of entities
```xml
@@ -5320,7 +5342,7 @@ identifies a collection of entities
:::
::: example
-Example 89: invoke the `Comparison` function on the set of red products
+Example 90: invoke the `Comparison` function on the set of red products
```
GET http://host/service/Products/$filter(Color eq 'Red')/Diff.Comparison()
```
@@ -5343,7 +5365,7 @@ result type of the bound operation. If the bound operation returns a
collection, the response is a collection of collections.
::: example
-Example 90: invoke the `MostRecentOrder` function on each entity in the
+Example 91: invoke the `MostRecentOrder` function on each entity in the
entity set `Customers`
```
GET http://host/service/Customers/$each/SampleModel.MostRecentOrder()
@@ -5371,7 +5393,7 @@ or entity collection within the payload. The representation of an action
or function depends on the [format](#Formats).
::: example
-Example 91: given a `GET` request to
+Example 92: given a `GET` request to
`http://host/service/Customers('ALFKI')`, the service might respond with
a Customer that includes the `SampleEntities.MostRecentOrder` function
bound to the entity
@@ -5398,7 +5420,7 @@ Services can advertise that a function or action is not available for a
particular instance by setting its value to null.
::: example
-Example 92: the `SampleEntities.MostRecentOrder` function is not
+Example 93: the `SampleEntities.MostRecentOrder` function is not
available for customer `ALFKI`
```json
{
@@ -5482,7 +5504,7 @@ segment is a multi-valued navigation property, a `POST` request may be
used to create a new entity in the identified collection.
::: example
-Example 93: add a new item to the list of items of the shopping cart
+Example 94: add a new item to the list of items of the shopping cart
returned by the composable `MyShoppingCart` function import
```
POST http://host/service/MyShoppingCart()/Items
@@ -5531,7 +5553,7 @@ Each parameter value is represented as a name/value pair in the format
and `Value` is the parameter value.
::: example
-Example 94: invoke a `Sales.EmployeesByManager` function which takes a
+Example 95: invoke a `Sales.EmployeesByManager` function which takes a
single `ManagerID` parameter via the function import
`EmployeesByManager`
```
@@ -5540,7 +5562,7 @@ GET http://host/service/EmployeesByManager(ManagerID=3)
:::
::: example
-Example 95: return all Customers whose `City` property returns
+Example 96: return all Customers whose `City` property returns
`Western` when passed to the `Sales.SalesRegion` function
```
GET http://host/service/Customers?
@@ -5553,7 +5575,7 @@ parameter value. The value for the alias is specified as a separate
query option using the name of the parameter alias.
::: example
-Example 96: invoke a `Sales.EmployeesByManager` function via the
+Example 97: invoke a `Sales.EmployeesByManager` function via the
function import `EmployeesByManager`, passing 3 for the `ManagerID`
parameter
```
@@ -5573,7 +5595,7 @@ optional `$` prefix), the parameter name MUST be prefixed with an at
(`@`) sign.
::: example
-Example 97: invoke a `Sales.EmployeesByManager` function via the
+Example 98: invoke a `Sales.EmployeesByManager` function via the
function import `EmployeesByManager`, passing 3 for the `ManagerID`
parameter using the implicit parameter alias
```
@@ -5713,7 +5735,7 @@ collection as a whole is transported in the [`ETag`](#HeaderETag) header of a
collection response.
::: example
-Example 98: invoke the `SampleEntities.CreateOrder` action using
+Example 99: invoke the `SampleEntities.CreateOrder` action using
`Customers('ALFKI')` as the customer (or binding parameter). The values
`2` for the `quantity` parameter and `BLACKFRIDAY` for the
`discountCode` parameter are passed in the body of the request. Invoke
@@ -5860,7 +5882,7 @@ format](#MultipartBatchFormat) MUST contain a
[RFC2046](#rfc2046).
::: example
-Example 99: multipart batch request
+Example 100: multipart batch request
```
POST /service/$batch HTTP/1.1
Host: odata.org
@@ -5875,7 +5897,7 @@ A batch request using the JSON batch format MUST contain a
`Content-Type` header specifying a content type of `application/json`.
::: example
-Example 100: JSON batch request
+Example 101: JSON batch request
```
POST /service/$batch HTTP/1.1
Host: odata.org
@@ -5930,7 +5952,7 @@ the request URL. Services MUST treat this segment like the URL in the
[`Location`](#HeaderLocation) header of the response to the request identified by the segment.
If the `Location` header in the response to the subsequent request contains a relative URL,
clients MUST be able to resolve it relative to the request's URL even if
-that contains such a reference. See [example 105](#batchcontentid).
+that contains such a reference. See [example 106](#batchcontentid).
If the `$`-prefixed request identifier is identical to the name of a
top-level system resource (`$batch`, `$crossjoin`, `$all`, `$entity`,
@@ -6031,7 +6053,7 @@ set can use one of the following three formats:
- Absolute URI with schema, host, port, and absolute resource path.
::: example
-Example 101:
+Example 102:
```
GET https://host:1234/path/service/People(1) HTTP/1.1
```
@@ -6040,7 +6062,7 @@ GET https://host:1234/path/service/People(1) HTTP/1.1
- Absolute resource path and separate `Host` header
::: example
-Example 102:
+Example 103:
```json
PATCH /path/service/People(1) HTTP/1.1
Host: myserver.mydomain.org:1234
@@ -6053,7 +6075,7 @@ Content-Type: application/json
- Resource path relative to the batch request URI.
::: example
-Example 103:
+Example 104:
```
DELETE People(1) HTTP/1.1
```
@@ -6078,7 +6100,7 @@ processor may choose to disallow chunked encoding to be used by such
HTTP requests.
::: example
-Example 104: a batch request that contains the following individual
+Example 105: a batch request that contains the following individual
requests in the order listed
1. A query request
@@ -6157,7 +6179,7 @@ which case they SHOULD advertise this support by specifying the
term applied to the entity container, see [OData-VocCap](#ODataVocCap).
::: example
-Example 105: a batch request that contains the following operations in
+Example 106: a batch request that contains the following operations in
the order listed:
A change set that contains the following requests:
@@ -6229,7 +6251,7 @@ request URL `$1/Orders`. To get an absolute base URI, the client must replace th
resulting URL `Customers('ALFKI')/Orders(1)` relative to its base URI, which is
`http://host/service/Customers` (determined from the
first request URL `/service/Customers` and the `Host: host` header
-as in [example 102](#batchhost)). This gives the effective second request URL
+as in [example 103](#batchhost)). This gives the effective second request URL
`http://host/service/Customers('ALFKI')/Orders` as base URI for the second `Location`
URL, which therefore resolves to `http://host/service/Customers('ALFKI')/Orders(1)`.
:::
@@ -6237,7 +6259,7 @@ URL, which therefore resolves to `http://host/service/Customers('ALFKI')/Orders(
#### 11.7.7.3 Referencing an ETag
::: example
-Example 106: a batch request that contains the following operations in
+Example 107: a batch request that contains the following operations in
the order listed:
- Get an employee (with `Content-ID = 1`)
@@ -6278,7 +6300,7 @@ If-Match: $1
#### 11.7.7.4 Referencing Response Body Values
::: example
-Example 107: a batch request that contains the following operations in
+Example 108: a batch request that contains the following operations in
the order listed:
- Get an employee (with `Content-ID = 1`)
@@ -6371,11 +6393,11 @@ A response to an operation in a batch MUST be formatted exactly as it
would have appeared outside of a batch as described in the corresponding
subsections of chapter [Data Service Requests](#DataServiceRequests).
Relative URLs in each individual response are relative to the request
-URL of the corresponding individual request (see [example 105](#batchcontentid)).
+URL of the corresponding individual request (see [example 106](#batchcontentid)).
URLs in responses MUST NOT contain `$`-prefixed request identifiers.
::: example
-Example 108: referencing the batch request [example 104](#batchRequest) above, assume all
+Example 109: referencing the batch request [example 105](#batchRequest) above, assume all
the requests except the final query request succeed. In this case the
response would be
```
@@ -6451,7 +6473,7 @@ Since a change set is executed atomically,
a change set.
::: example
-Example 109: referencing the [example 104](#batchRequest) above again, assume that
+Example 110: referencing the [example 105](#batchRequest) above again, assume that
```
HTTP/1.1 202 Accepted
Location: http://service-root/async-monitor-0
diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md
index cdcc419d..0450a48f 100644
--- a/odata-protocol/11.4 Data Modification.md
+++ b/odata-protocol/11.4 Data Modification.md
@@ -178,20 +178,40 @@ values beyond those specified in the metadata SHOULD NOT be sent in the
request body. The service MUST fail if unable to persist all property
values specified in the request.
-Non-insertable properties SHOULD be omitted from the request body.
-If they are provided, services MUST either ignore the values in the request body or fail the request
+If non-insertable properties are included in the request body,
+services MUST either ignore them or fail the request
if the provided values do not match the service-determined values.
Non-insertable properties include (and are not limited to)
- dependent properties that are tied to non-key properties of the principal entity through a referential constraint [OData-CSDL, section 8.5](#ODataCSDL) (informally: "denormalized" properties),
-- properties annotated with the term
+- properties tagged with the term
[`Core.Computed`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Computed), see [OData-VocCore](#ODataVocCore),
- properties listed as `NonInsertableProperties` of term [`Capabilities.InsertRestrictions`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Capabilities.V1.md#InsertRestrictions), see [OData-VocCap](#ODataVocCap),
- properties annotated with term
[`Core.Permissions`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Permissions), see [OData-VocCore](#ODataVocCore), where the annotation value does not have the `Write` flag.
+Properties tagged with `Core.Computed` MAY additionally be tagged with the term
+[`Core.PostCondition`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#PostCondition),
+see [OData-VocCore](#ODataVocCore), if the service does not ignore them.
+Based on this tag (or based on out-of-band knowledge about the service behavior)
+clients can provide these properties in an insert request
+and benefit from the certainty that, if the request succeeds, their service-determined values match
+the provided values. Providing such properties effectively imposes "post-conditions"
+that must be met for the request to succeed.
+
+Otherwise, clients SHOULD omit non-insertable properties from the request body.
+
+::: example
+Example ##ex: The entity `SalesOrder` has a property `ExportRegulationsState`
+which is tagged with `Core.Computed` and `Core.PostCondition` and which
+the service determines based on the product and destination country.
+Clients can specify it with value `Allowed` to impose a "post-condition" that a sales order is created
+only if it meets export regulations.
+:::
+
Services MUST return an error if the request body contains a value for a property that in principle can be specified on insert but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object.
+
Properties with a default value, nullable properties, and
collection-valued properties omitted from the request are set to the
default value, null, or an empty collection, respectively.
@@ -376,7 +396,7 @@ Non-updatable properties include (and are not limited to)
- key properties,
- dependent properties that are tied to non-key properties of the principal entity through a referential constraint [OData-CSDL, section 8.5](#ODataCSDL) (informally: "denormalized" properties),
-- properties annotated with the terms
+- properties tagged with the terms
[`Core.Computed`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Computed) or [`Core.Immutable`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Core.V1.md#Immutable), see [OData-VocCore](#ODataVocCore),
- properties listed as `NonUpdatableProperties` of term [`Capabilities.UpdateRestrictions`](https://github.com/oasis-tcs/odata-vocabularies/blob/main/vocabularies/Org.OData.Capabilities.V1.md#UpdateRestrictions), see [OData-VocCap](#ODataVocCap),
- properties annotated with term
@@ -385,7 +405,9 @@ Non-updatable properties include (and are not limited to)
Services MUST return an error if the request body contains a value for a
property that in principle can be specified on update but the request cannot currently be executed respecting the specified value, for example, due to permissions or state of the object.
-Clients SHOULD use `PATCH` and specify only those properties intended to be changed.
+Clients can provide non-updatable properties to impose "post-conditions" as explained
+for [non-insertable properties](#CreateanEntity). Otherwise,
+clients SHOULD use `PATCH` and specify only those properties intended to be changed.
The entity-id cannot be changed when updating an entity.
However, format-specific rules might in some cases require providing