From c0b95c9678a28cd3d6a532452ca3ffd92086c7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 08:29:49 +0200 Subject: [PATCH 01/10] Post-conditions --- docs/odata-protocol/odata-protocol.html | 8 +++++--- docs/odata-protocol/odata-protocol.md | 15 ++++++++++++--- odata-protocol/11.4 Data Modification.md | 15 ++++++++++++--- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index bae8b6b8..1695f012 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2270,7 +2270,8 @@

1

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.

+

A client who has out-of-band knowledge that a service has the latter behavior for certain non-insertable properties can provide them 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.

Non-insertable 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 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 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.

@@ -2349,7 +2351,7 @@

1
  • 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.

    diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 8ac825c9..c897c6be 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4180,10 +4180,16 @@ 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. +A client who has out-of-band knowledge that a service has the latter behavior for +certain non-insertable properties can provide them 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. + 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), @@ -4194,6 +4200,7 @@ Non-insertable properties include (and are not limited to) [`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. 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. @@ -4387,7 +4394,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 diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index cdcc419d..964bdf63 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -178,10 +178,16 @@ 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. +A client who has out-of-band knowledge that a service has the latter behavior for +certain non-insertable properties can provide them 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. + 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), @@ -192,6 +198,7 @@ Non-insertable properties include (and are not limited to) [`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. 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. @@ -385,7 +392,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 From 86899f91dab142259319c2479747dbc31d1f9a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 08:48:15 +0200 Subject: [PATCH 02/10] Clients SHOULD --- docs/odata-protocol/odata-protocol.html | 1 + docs/odata-protocol/odata-protocol.md | 2 ++ odata-protocol/11.4 Data Modification.md | 2 ++ 3 files changed, 5 insertions(+) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 1695f012..c133a4d9 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2272,6 +2272,7 @@

    1

    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.

    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.

    A client who has out-of-band knowledge that a service has the latter behavior for certain non-insertable properties can provide them 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.

    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 (informally: “denormalized” properties),
    • diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index c897c6be..4d96e07a 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4190,6 +4190,8 @@ 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. + 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), diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index 964bdf63..42b987c1 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -188,6 +188,8 @@ 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. + 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), From 28b6a3005922ee20fc1acfea2b10d2aa4f4e7eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 09:06:37 +0200 Subject: [PATCH 03/10] Example --- docs/odata-protocol/odata-protocol.html | 77 +++++++++++----------- docs/odata-protocol/odata-protocol.md | 82 +++++++++++++----------- odata-protocol/11.4 Data Modification.md | 8 +++ 3 files changed, 93 insertions(+), 74 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index c133a4d9..0d5807f3 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2280,6 +2280,9 @@

      1
    • properties listed as NonInsertableProperties of term Capabilities.InsertRestrictions, see OData-VocCap,
    • properties annotated with term Core.Permissions, see OData-VocCore, where the annotation value does not have the Write flag.
    +
    +

    Example 76: The entity SalesOrder has a property ExportRegulationsState which is a annotated with the term Core.Computed 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.

    @@ -2290,7 +2293,7 @@

    @@ -2752,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.

    @@ -2763,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",
    @@ -2778,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",
    @@ -2803,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
     
     …
    @@ -2820,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.

    @@ -2875,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
    @@ -2926,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
    @@ -2936,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
    @@ -2963,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.

    @@ -2997,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
    @@ -3015,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.

    @@ -3027,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

    1. A query request
    2. A change set that contains the following requests: @@ -3093,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)
      • @@ -3153,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
      • @@ -3200,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
        • @@ -3249,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: ####
        @@ -3305,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 4d96e07a..33403b31 100644
        --- a/docs/odata-protocol/odata-protocol.md
        +++ b/docs/odata-protocol/odata-protocol.md
        @@ -4201,6 +4201,14 @@ Non-insertable properties include (and are not limited to)
         - 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.
         
        +::: example
        +Example 76: The entity `SalesOrder` has a property `ExportRegulationsState`
        +which is a annotated with the term `Core.Computed` 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
        @@ -4229,7 +4237,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
         
        @@ -4250,7 +4258,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
         
        @@ -4462,7 +4470,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`.
        @@ -4512,7 +4520,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
        @@ -4804,7 +4812,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
        @@ -4835,7 +4843,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
        @@ -4886,7 +4894,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
        @@ -5040,7 +5048,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
        @@ -5202,7 +5210,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'
        @@ -5248,7 +5256,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
        @@ -5300,7 +5308,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
         
        @@ -5311,7 +5319,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)`
         ```
        @@ -5320,7 +5328,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
         
        @@ -5331,7 +5339,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()
         ```
        @@ -5354,7 +5362,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()
        @@ -5382,7 +5390,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
        @@ -5409,7 +5417,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
         {
        @@ -5493,7 +5501,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
        @@ -5542,7 +5550,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`
         ```
        @@ -5551,7 +5559,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?
        @@ -5564,7 +5572,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
         ```
        @@ -5584,7 +5592,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
         ```
        @@ -5724,7 +5732,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
        @@ -5871,7 +5879,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
        @@ -5886,7 +5894,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
        @@ -5941,7 +5949,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`,
        @@ -6042,7 +6050,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
         ```
        @@ -6051,7 +6059,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
        @@ -6064,7 +6072,7 @@ Content-Type: application/json
         - Resource path relative to the batch request URI.
         
         ::: example
        -Example 103:
        +Example 104:
         ```
         DELETE People(1) HTTP/1.1
         ```
        @@ -6089,7 +6097,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
        @@ -6168,7 +6176,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:
        @@ -6240,7 +6248,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)`.
         :::
        @@ -6248,7 +6256,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`)
        @@ -6289,7 +6297,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`)
        @@ -6382,11 +6390,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
         ```
        @@ -6462,7 +6470,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 42b987c1..7b199905 100644
        --- a/odata-protocol/11.4 Data Modification.md	
        +++ b/odata-protocol/11.4 Data Modification.md	
        @@ -199,6 +199,14 @@ Non-insertable properties include (and are not limited to)
         - 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.
         
        +::: example
        +Example ##ex: The entity `SalesOrder` has a property `ExportRegulationsState`
        +which is a annotated with the term `Core.Computed` 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
        
        From 94bc40bf3314d6910df880f6ac667d4e24483410 Mon Sep 17 00:00:00 2001
        From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= 
        Date: Thu, 1 Aug 2024 09:28:51 +0200
        Subject: [PATCH 04/10] Split overlong sentence
        
        ---
         docs/odata-protocol/odata-protocol.html  | 2 +-
         docs/odata-protocol/odata-protocol.md    | 4 ++--
         odata-protocol/11.4 Data Modification.md | 4 ++--
         3 files changed, 5 insertions(+), 5 deletions(-)
        
        diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html
        index 0d5807f3..0a98902f 100644
        --- a/docs/odata-protocol/odata-protocol.html
        +++ b/docs/odata-protocol/odata-protocol.html
        @@ -2271,7 +2271,7 @@ 

        1

        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.

        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.

        -

        A client who has out-of-band knowledge that a service has the latter behavior for certain non-insertable properties can provide them 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.

        +

        Assume a client has out-of-band knowledge that a service has the latter behavior for certain non-insertable properties. Then it 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.

        Non-insertable properties include (and are not limited to)

          diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 33403b31..8ebbb038 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4184,8 +4184,8 @@ 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. -A client who has out-of-band knowledge that a service has the latter behavior for -certain non-insertable properties can provide them in an insert request and benefit from the +Assume a client has out-of-band knowledge that a service has the latter behavior for +certain non-insertable properties. Then it 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. diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index 7b199905..daf4a273 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -182,8 +182,8 @@ 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. -A client who has out-of-band knowledge that a service has the latter behavior for -certain non-insertable properties can provide them in an insert request and benefit from the +Assume a client has out-of-band knowledge that a service has the latter behavior for +certain non-insertable properties. Then it 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. From 99daeaada6ffd6919d50e4a37c5dd5ccd919bdbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 10:41:02 +0200 Subject: [PATCH 05/10] No need for out-of-band knowledge --- docs/odata-protocol/odata-protocol.html | 4 ++-- docs/odata-protocol/odata-protocol.md | 18 ++++++++++-------- odata-protocol/11.4 Data Modification.md | 18 ++++++++++-------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 0a98902f..17bb3259 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2271,8 +2271,6 @@

          1

          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.

          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.

          -

          Assume a client has out-of-band knowledge that a service has the latter behavior for certain non-insertable properties. Then it 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.

          Non-insertable properties include (and are not limited to)

          +

          Properties annotated with Core.Computed MAY additionally be annotated with the term Core.PostCondition, see OData-VocCore, if the service does not ignore them. Clients can then 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 a annotated with the term Core.Computed 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.

          diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 8ebbb038..02222c94 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4184,14 +4184,6 @@ 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. -Assume a client has out-of-band knowledge that a service has the latter behavior for -certain non-insertable properties. Then it 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. - 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), @@ -4201,6 +4193,16 @@ Non-insertable properties include (and are not limited to) - 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 annotated with `Core.Computed` MAY additionally be annotated 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. +Clients can then 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 a annotated with the term `Core.Computed` and which diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index daf4a273..16cfb443 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -182,14 +182,6 @@ 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. -Assume a client has out-of-band knowledge that a service has the latter behavior for -certain non-insertable properties. Then it 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. - 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), @@ -199,6 +191,16 @@ Non-insertable properties include (and are not limited to) - 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 annotated with `Core.Computed` MAY additionally be annotated 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. +Clients can then 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 a annotated with the term `Core.Computed` and which From 6461a2340f2c3bb57a9f5c0d597d5b7e250fa5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 10:43:02 +0200 Subject: [PATCH 06/10] Extend example --- docs/odata-protocol/odata-protocol.html | 2 +- docs/odata-protocol/odata-protocol.md | 2 +- odata-protocol/11.4 Data Modification.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 17bb3259..7196186e 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2281,7 +2281,7 @@

          1

          Properties annotated with Core.Computed MAY additionally be annotated with the term Core.PostCondition, see OData-VocCore, if the service does not ignore them. Clients can then 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 a annotated with the term Core.Computed 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.

          +

          Example 76: The entity SalesOrder has a property ExportRegulationsState which is a annotated with the terms 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.

          diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 02222c94..1ff75198 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4205,7 +4205,7 @@ Otherwise, clients SHOULD omit non-insertable properties from the request body. ::: example Example 76: The entity `SalesOrder` has a property `ExportRegulationsState` -which is a annotated with the term `Core.Computed` and which +which is a annotated with the terms `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. diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index 16cfb443..92376dfd 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -203,7 +203,7 @@ Otherwise, clients SHOULD omit non-insertable properties from the request body. ::: example Example ##ex: The entity `SalesOrder` has a property `ExportRegulationsState` -which is a annotated with the term `Core.Computed` and which +which is a annotated with the terms `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. From 5c3f40d5df63bf9893667e1ea1110f57f8bd67f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 12:55:30 +0200 Subject: [PATCH 07/10] annotated -> tagged (to rule out value `false`) --- docs/odata-protocol/odata-protocol.html | 4 ++-- docs/odata-protocol/odata-protocol.md | 4 ++-- odata-protocol/11.4 Data Modification.md | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 7196186e..4ad5f645 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2274,11 +2274,11 @@

          1

          Non-insertable properties include (and are not limited to)

          -

          Properties annotated with Core.Computed MAY additionally be annotated with the term Core.PostCondition, see OData-VocCore, if the service does not ignore them. Clients can then 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.

          +

          Properties tagged with Core.Computed MAY additionally be tagged with the term Core.PostCondition, see OData-VocCore, if the service does not ignore them. Clients can then 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 a annotated with the terms 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.

          diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 1ff75198..585ebd83 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4187,13 +4187,13 @@ 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 annotated with `Core.Computed` MAY additionally be annotated with the term +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. Clients can then provide these properties in an insert request diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index 92376dfd..abb00754 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -185,13 +185,13 @@ 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 annotated with `Core.Computed` MAY additionally be annotated with the term +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. Clients can then provide these properties in an insert request From 6032e08fee294c71dce6788362f7d467202ba054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 12:57:04 +0200 Subject: [PATCH 08/10] typos --- docs/odata-protocol/odata-protocol.html | 2 +- docs/odata-protocol/odata-protocol.md | 2 +- odata-protocol/11.4 Data Modification.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 4ad5f645..068275d6 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2281,7 +2281,7 @@

          1

          Properties tagged with Core.Computed MAY additionally be tagged with the term Core.PostCondition, see OData-VocCore, if the service does not ignore them. Clients can then 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 a annotated with the terms 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.

          +

          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.

          diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 585ebd83..9235e226 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4205,7 +4205,7 @@ Otherwise, clients SHOULD omit non-insertable properties from the request body. ::: example Example 76: The entity `SalesOrder` has a property `ExportRegulationsState` -which is a annotated with the terms `Core.Computed` and `Core.PostCondition` and which +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. diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index abb00754..d4b22af6 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -203,7 +203,7 @@ Otherwise, clients SHOULD omit non-insertable properties from the request body. ::: example Example ##ex: The entity `SalesOrder` has a property `ExportRegulationsState` -which is a annotated with the terms `Core.Computed` and `Core.PostCondition` and which +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. From c76b66b74c0159866cfed5c86fb78ee71cfcd85d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 13:22:56 +0200 Subject: [PATCH 09/10] annotated -> tagged --- docs/odata-protocol/odata-protocol.html | 2 +- docs/odata-protocol/odata-protocol.md | 2 +- odata-protocol/11.4 Data Modification.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 068275d6..d2680688 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2350,7 +2350,7 @@

          1 diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 9235e226..f7ccbf6d 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4397,7 +4397,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 diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index d4b22af6..8d98d2f8 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -395,7 +395,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 From aa75d526a3b45b66a6a3e3b4d542eca03f769b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Thu, 1 Aug 2024 13:58:40 +0200 Subject: [PATCH 10/10] Allow out-of-band knowledge again --- docs/odata-protocol/odata-protocol.html | 2 +- docs/odata-protocol/odata-protocol.md | 3 ++- odata-protocol/11.4 Data Modification.md | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index d2680688..4dbc9382 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2278,7 +2278,7 @@

          1
        • properties listed as NonInsertableProperties of term Capabilities.InsertRestrictions, see OData-VocCap,
        • properties annotated with term Core.Permissions, see OData-VocCore, where the annotation value does not have the Write flag.
        -

        Properties tagged with Core.Computed MAY additionally be tagged with the term Core.PostCondition, see OData-VocCore, if the service does not ignore them. Clients can then 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.

        +

        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.

        diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index f7ccbf6d..0adfc8ac 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -4196,7 +4196,8 @@ Non-insertable properties include (and are not limited to) 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. -Clients can then provide these properties in an insert request +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. diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md index 8d98d2f8..0450a48f 100644 --- a/odata-protocol/11.4 Data Modification.md +++ b/odata-protocol/11.4 Data Modification.md @@ -194,7 +194,8 @@ Non-insertable properties include (and are not limited to) 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. -Clients can then provide these properties in an insert request +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.