diff --git a/docs/odata-csdl-json/styles/odata.css b/docs/odata-csdl-json/styles/odata.css index aa19bb20..1b808b0e 100644 --- a/docs/odata-csdl-json/styles/odata.css +++ b/docs/odata-csdl-json/styles/odata.css @@ -1,3 +1,7 @@ +:root { + --indent: 40px; +} + a:target, span:target { background-color: yellow; @@ -168,11 +172,31 @@ td > code { .example pre, .rep { - margin-left: 40px; + margin-left: var(--indent); +} + +.caption p { + margin-left: var(--indent); + margin-bottom: -1em; +} + +.side-by-side { + margin: -1em 0; +} + +.side-by-side:after { + content: ""; + display: block; + clear: both; +} + +.side-by-side > div { + width: 50%; + float: left; } .indent { - margin-left: 40px; + margin-left: var(--indent); } td pre { @@ -195,7 +219,7 @@ mjx-container { mjx-container[display="true"] { text-align: left !important; - margin-left: 40px !important; + margin-left: var(--indent) !important; } code .er { diff --git a/docs/odata-csdl-xml/styles/odata.css b/docs/odata-csdl-xml/styles/odata.css index aa19bb20..1b808b0e 100644 --- a/docs/odata-csdl-xml/styles/odata.css +++ b/docs/odata-csdl-xml/styles/odata.css @@ -1,3 +1,7 @@ +:root { + --indent: 40px; +} + a:target, span:target { background-color: yellow; @@ -168,11 +172,31 @@ td > code { .example pre, .rep { - margin-left: 40px; + margin-left: var(--indent); +} + +.caption p { + margin-left: var(--indent); + margin-bottom: -1em; +} + +.side-by-side { + margin: -1em 0; +} + +.side-by-side:after { + content: ""; + display: block; + clear: both; +} + +.side-by-side > div { + width: 50%; + float: left; } .indent { - margin-left: 40px; + margin-left: var(--indent); } td pre { @@ -195,7 +219,7 @@ mjx-container { mjx-container[display="true"] { text-align: left !important; - margin-left: 40px !important; + margin-left: var(--indent) !important; } code .er { diff --git a/docs/odata-data-aggregation-ext/styles/odata.css b/docs/odata-data-aggregation-ext/styles/odata.css index aa19bb20..1b808b0e 100644 --- a/docs/odata-data-aggregation-ext/styles/odata.css +++ b/docs/odata-data-aggregation-ext/styles/odata.css @@ -1,3 +1,7 @@ +:root { + --indent: 40px; +} + a:target, span:target { background-color: yellow; @@ -168,11 +172,31 @@ td > code { .example pre, .rep { - margin-left: 40px; + margin-left: var(--indent); +} + +.caption p { + margin-left: var(--indent); + margin-bottom: -1em; +} + +.side-by-side { + margin: -1em 0; +} + +.side-by-side:after { + content: ""; + display: block; + clear: both; +} + +.side-by-side > div { + width: 50%; + float: left; } .indent { - margin-left: 40px; + margin-left: var(--indent); } td pre { @@ -195,7 +219,7 @@ mjx-container { mjx-container[display="true"] { text-align: left !important; - margin-left: 40px !important; + margin-left: var(--indent) !important; } code .er { diff --git a/docs/odata-json-format/styles/odata.css b/docs/odata-json-format/styles/odata.css index aa19bb20..1b808b0e 100644 --- a/docs/odata-json-format/styles/odata.css +++ b/docs/odata-json-format/styles/odata.css @@ -1,3 +1,7 @@ +:root { + --indent: 40px; +} + a:target, span:target { background-color: yellow; @@ -168,11 +172,31 @@ td > code { .example pre, .rep { - margin-left: 40px; + margin-left: var(--indent); +} + +.caption p { + margin-left: var(--indent); + margin-bottom: -1em; +} + +.side-by-side { + margin: -1em 0; +} + +.side-by-side:after { + content: ""; + display: block; + clear: both; +} + +.side-by-side > div { + width: 50%; + float: left; } .indent { - margin-left: 40px; + margin-left: var(--indent); } td pre { @@ -195,7 +219,7 @@ mjx-container { mjx-container[display="true"] { text-align: left !important; - margin-left: 40px !important; + margin-left: var(--indent) !important; } code .er { diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 67b5040b..89f61580 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -2471,6 +2471,65 @@

$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

-
{
-  "@context": "http://host/service/$metadata#Products/$entity",
-  
-  "Thumbnail@mediaReadLink": "http://server/Thumbnail546.jpg",
-  "Thumbnail@mediaEditLink": "http://server/uploads/Thumbnail546.jpg",
-  
-}
+
{
+  "@context": "http://host/service/$metadata#Products/$entity",
+  
+  "Thumbnail@mediaReadLink": "http://server/Thumbnail546.jpg",
+  "Thumbnail@mediaEditLink": "http://server/uploads/Thumbnail546.jpg",
+  
+}

The stream data can then be requested using the media read link:

GET http://server/Thumbnail546.jpg

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.

@@ -2608,7 +2667,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.

@@ -2670,13 +2729,13 @@

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

-
POST /service/Customers('ALFKI')/EmailAddresses?$index=1
-Content-Type: application/json
-
-{
-  "value": "alfred@futterkiste.de"
-}
+

Example 84: Insert a new email address at the second position

+
POST /service/Customers('ALFKI')/EmailAddresses?$index=1
+Content-Type: application/json
+
+{
+  "value": "alfred@futterkiste.de"
+}
@@ -2731,13 +2790,13 @@

For primitive-typed collections the body of the request MUST be a primitive value. Each member of the potentially filtered collection is updated to the specified primitive value.

For collections of structured type, the body of the request MUST be a full or partial representation of an instance of the collection’s structured type. Each member of the potentially filtered collection is 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

-
PATCH /service/Products/$filter(@bar)/$each?@bar=Color eq 'beige-brown'
-Content-Type: application/json
-
-{
-  "Color": "taupe"
-}
+

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
+
+{
+  "Color": "taupe"
+}

The response, if requested, is a collection payload containing the updated representation of each member identified by the request. If the update payload includes nested collections or nested delta collections, then they MUST be included in the response, as described in Update a Collection of Entities.

Clients should note that requesting a response may be expensive for services that could otherwise efficiently apply updates to a (possibly filtered) collection.

@@ -2750,7 +2809,7 @@

Members of a collection can be deleted by submitting a DELETE request to the URL constructed by appending /$each to the resource path of the collection. The additional path segment expresses that the collection itself is not deleted.

The request resource path of the collection MAY contain type-cast or filter segments to subset the collection.

-

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.

@@ -2769,25 +2828,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

-
<Function Name="MostRecentOrder" IsBound="true">
-  <Parameter Name="customer" Type="SampleModel.Customer" />
-  <ReturnType Type="SampleModel.Order" />
-</Function>
+

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

-
<Function Name="Comparison" IsBound="true">
-  <Parameter Name="in" Type="Collection(Edm.EntityType)" />
-  <ReturnType Type="Diff.Overview" />
-</Function>
+

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()

@@ -2798,7 +2857,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.

@@ -2809,29 +2868,29 @@

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

-
{
-  "@context": ,
-  "CustomerID": "ALFKI",
-  "CompanyName": "Alfreds Futterkiste",
-  "#SampleEntities.MostRecentOrder": {
-    "title": "Most Recent Order",
-    "target": "Customers('ALFKI')/SampleEntities.MostRecentOrder()"
-  },
-  
-}
+

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",
+  "CompanyName": "Alfreds Futterkiste",
+  "#SampleEntities.MostRecentOrder": {
+    "title": "Most Recent Order",
+    "target": "Customers('ALFKI')/SampleEntities.MostRecentOrder()"
+  },
+  
+}

An efficient format that assumes client knowledge of metadata may omit actions and functions from the payload whose target URL can be computed via metadata following standard conventions defined in 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

-
{
-  "@context": ,
-  "CustomerID": "ALFKI",
-  "CompanyName": "Alfreds Futterkiste",
-  "#SampleEntities.MostRecentOrder": null,
-  
-}
+

Example 93: the SampleEntities.MostRecentOrder function is not available for customer ALFKI

+
{
+  "@context": ,
+  "CustomerID": "ALFKI",
+  "CompanyName": "Alfreds Futterkiste",
+  "#SampleEntities.MostRecentOrder": null,
+  
+}
@@ -2849,7 +2908,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
 
 …
@@ -2866,22 +2925,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.

@@ -2921,18 +2980,18 @@

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.

-
POST http://host/service/Customers('ALFKI')/SampleEntities.CreateOrder
-If-Match: W/"MjAxOS0wMy0yMVQxMzowNVo="
-Content-Type: application/json
-
-{
-  "items": [
-    { "product": 4001, "quantity": 2 },
-    { "product": 7062, "quantity": 1 },
-  ],
-  "discountCode": "BLACKFRIDAY"
-}
+

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
+
+{
+  "items": [
+    { "product": 4001, "quantity": 2 },
+    { "product": 7062, "quantity": 1 },
+  ],
+  "discountCode": "BLACKFRIDAY"
+}

@@ -2972,7 +3031,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
@@ -2982,7 +3041,7 @@ 

-

Example 100: JSON batch request

+

Example 101: JSON batch request

POST /service/$batch HTTP/1.1
 Host: odata.org
 OData-Version: 4.01
@@ -3009,7 +3068,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.

@@ -3043,25 +3102,25 @@

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:

-
PATCH /path/service/People(1) HTTP/1.1
-Host: myserver.mydomain.org:1234
-Content-Type: application/json
-
-{ "Name": "Peter" }
+

Example 103:

+
PATCH /path/service/People(1) HTTP/1.1
+Host: myserver.mydomain.org:1234
+Content-Type: application/json
+
+{ "Name": "Peter" }
  • 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.

@@ -3073,7 +3132,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: @@ -3139,7 +3198,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)
    • @@ -3199,54 +3258,54 @@

      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
    -
    POST /service/$batch HTTP/1.1
    -Host: host
    -OData-Version: 4.0
    -Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b
    -Content-Length: ###
    -
    ---batch_36522ad7-fc75-4b56-8c71-56071383e77b
    -Content-Type: application/http
    -Content-ID: 1
    -
    -GET /service/Employees(0) HTTP/1.1
    -Host: host
    -Accept: application/json
    -
    -
    ---batch_36522ad7-fc75-4b56-8c71-56071383e77b
    -Content-Type: application/http
    -Content-ID: 2
    -
    -PATCH /service/Employees(0) HTTP/1.1
    -Host: host
    -Content-Type: application/json
    -Content-Length: ###
    -If-Match: $1
    -
    -{
    -   "Salary": 75000
    -}
    ---batch_36522ad7-fc75-4b56-8c71-56071383e77b--
    +
    POST /service/$batch HTTP/1.1
    +Host: host
    +OData-Version: 4.0
    +Content-Type: multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b
    +Content-Length: ###
    +
    +--batch_36522ad7-fc75-4b56-8c71-56071383e77b
    +Content-Type: application/http
    +Content-ID: 1
    +
    +GET /service/Employees(0) HTTP/1.1
    +Host: host
    +Accept: application/json
    +
    +
    +--batch_36522ad7-fc75-4b56-8c71-56071383e77b
    +Content-Type: application/http
    +Content-ID: 2
    +
    +PATCH /service/Employees(0) HTTP/1.1
    +Host: host
    +Content-Type: application/json
    +Content-Length: ###
    +If-Match: $1
    +
    +{
    +   "Salary": 75000
    +}
    +--batch_36522ad7-fc75-4b56-8c71-56071383e77b--

    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
    • @@ -3295,9 +3354,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: ####
    @@ -3351,7 +3410,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 693825de..6e09298a 100644
    --- a/docs/odata-protocol/odata-protocol.md
    +++ b/docs/odata-protocol/odata-protocol.md
    @@ -4548,7 +4548,83 @@ nested delta representation to:
       ]
     }
     ```
    +:::
    +
    +::: example
    +Example 80: When updating an entity with a 4.01 `PUT` request, the target of a
    +non-containment navigation property can be replaced without changing either the
    +old or the new targeted entity itself. The targeted entity can then only be
    +specified by an entity reference (see [OData-JSON, section 14](https://docs.oasis-open.org/odata/odata-json-format/v4.02/odata-json-format-v4.02.html#EntityReference)).
    +
    +The following JSON payload changes the last name and the manager of Suzanne Brown.
    +The effect would be the same if the `@context` was omitted from the request.
    +:::: side-by-side
    +::::: caption
    +Request
    +```json
    +PUT http://host/service/Employees(7)?$expand=Manager
    +Content-Type: application/json
    +
    +{
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "@context": "$metadata#$ref",
    +    "@id": "Employees(6)"
    +  }
    +}
    +```
    +:::::
    +::::: caption
    +Response
    +```json
    +{
    +  "@context": "$metadata#Employees/$entity",
    +  "EmployeeID": 7,
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "EmployeeID": 6,
    +    "FirstName": "Patricia",
    +    "LastName": "Miller"
    +  }
    +}
    +```
    +:::::
    +::::
     
    +If the targeted entity in the payload contains some structural properties,
    +`PUT` resets all its other structural properties. The following alternative
    +payload resets the first and last names of the new manager.
    +The effect would be the same if the `@id` was omitted from the request.
    +:::: side-by-side
    +```json
    +PUT http://host/service/Employees(7)?$expand=Manager
    +Content-Type: application/json
    +
    +{
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "@id": "Employees(6)",
    +    "EmployeeID": 6
    +  }
    +}
    +```
    +```json
    +{
    +  "@context": "$metadata#Employees/$entity",
    +  "EmployeeID": 7,
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "EmployeeID": 6,
    +    "FirstName": null,
    +    "LastName": null
    +  }
    +}
    +```
    +::::
     :::
     
     Clients MAY associate an id with individual nested entities in the
    @@ -4795,7 +4871,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
    @@ -4826,7 +4902,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
    @@ -4877,7 +4953,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
    @@ -5031,7 +5107,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
    @@ -5193,7 +5269,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'
    @@ -5239,7 +5315,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
    @@ -5291,7 +5367,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
     
    @@ -5302,7 +5378,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)`
     ```
    @@ -5311,7 +5387,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
     
    @@ -5322,7 +5398,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()
     ```
    @@ -5345,7 +5421,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()
    @@ -5373,7 +5449,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
    @@ -5400,7 +5476,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
     {
    @@ -5484,7 +5560,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
    @@ -5533,7 +5609,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`
     ```
    @@ -5542,7 +5618,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?
    @@ -5555,7 +5631,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
     ```
    @@ -5575,7 +5651,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
     ```
    @@ -5715,7 +5791,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
    @@ -5862,7 +5938,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
    @@ -5877,7 +5953,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
    @@ -5932,7 +6008,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`,
    @@ -6033,7 +6109,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
     ```
    @@ -6042,7 +6118,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
    @@ -6055,7 +6131,7 @@ Content-Type: application/json
     - Resource path relative to the batch request URI.
     
     ::: example
    -Example 103:
    +Example 104:
     ```
     DELETE People(1) HTTP/1.1
     ```
    @@ -6080,7 +6156,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
    @@ -6159,7 +6235,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:
    @@ -6231,7 +6307,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)`.
     :::
    @@ -6239,7 +6315,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`)
    @@ -6280,7 +6356,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`)
    @@ -6373,11 +6449,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
     ```
    @@ -6453,7 +6529,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/docs/odata-protocol/styles/odata.css b/docs/odata-protocol/styles/odata.css
    index aa19bb20..1b808b0e 100644
    --- a/docs/odata-protocol/styles/odata.css
    +++ b/docs/odata-protocol/styles/odata.css
    @@ -1,3 +1,7 @@
    +:root {
    +  --indent: 40px;
    +}
    +
     a:target,
     span:target {
       background-color: yellow;
    @@ -168,11 +172,31 @@ td > code {
     
     .example pre,
     .rep {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
    +}
    +
    +.caption p {
    +  margin-left: var(--indent);
    +  margin-bottom: -1em;
    +}
    +
    +.side-by-side {
    +  margin: -1em 0;
    +}
    +
    +.side-by-side:after {
    +  content: "";
    +  display: block;
    +  clear: both;
    +}
    +
    +.side-by-side > div {
    +  width: 50%;
    +  float: left;
     }
     
     .indent {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
     }
     
     td pre {
    @@ -195,7 +219,7 @@ mjx-container {
     
     mjx-container[display="true"] {
       text-align: left !important;
    -  margin-left: 40px !important;
    +  margin-left: var(--indent) !important;
     }
     
     code .er {
    diff --git a/docs/odata-temporal-ext/styles/odata.css b/docs/odata-temporal-ext/styles/odata.css
    index aa19bb20..1b808b0e 100644
    --- a/docs/odata-temporal-ext/styles/odata.css
    +++ b/docs/odata-temporal-ext/styles/odata.css
    @@ -1,3 +1,7 @@
    +:root {
    +  --indent: 40px;
    +}
    +
     a:target,
     span:target {
       background-color: yellow;
    @@ -168,11 +172,31 @@ td > code {
     
     .example pre,
     .rep {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
    +}
    +
    +.caption p {
    +  margin-left: var(--indent);
    +  margin-bottom: -1em;
    +}
    +
    +.side-by-side {
    +  margin: -1em 0;
    +}
    +
    +.side-by-side:after {
    +  content: "";
    +  display: block;
    +  clear: both;
    +}
    +
    +.side-by-side > div {
    +  width: 50%;
    +  float: left;
     }
     
     .indent {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
     }
     
     td pre {
    @@ -195,7 +219,7 @@ mjx-container {
     
     mjx-container[display="true"] {
       text-align: left !important;
    -  margin-left: 40px !important;
    +  margin-left: var(--indent) !important;
     }
     
     code .er {
    diff --git a/docs/odata-url-conventions/styles/odata.css b/docs/odata-url-conventions/styles/odata.css
    index aa19bb20..1b808b0e 100644
    --- a/docs/odata-url-conventions/styles/odata.css
    +++ b/docs/odata-url-conventions/styles/odata.css
    @@ -1,3 +1,7 @@
    +:root {
    +  --indent: 40px;
    +}
    +
     a:target,
     span:target {
       background-color: yellow;
    @@ -168,11 +172,31 @@ td > code {
     
     .example pre,
     .rep {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
    +}
    +
    +.caption p {
    +  margin-left: var(--indent);
    +  margin-bottom: -1em;
    +}
    +
    +.side-by-side {
    +  margin: -1em 0;
    +}
    +
    +.side-by-side:after {
    +  content: "";
    +  display: block;
    +  clear: both;
    +}
    +
    +.side-by-side > div {
    +  width: 50%;
    +  float: left;
     }
     
     .indent {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
     }
     
     td pre {
    @@ -195,7 +219,7 @@ mjx-container {
     
     mjx-container[display="true"] {
       text-align: left !important;
    -  margin-left: 40px !important;
    +  margin-left: var(--indent) !important;
     }
     
     code .er {
    diff --git a/odata-protocol/11.4 Data Modification.md b/odata-protocol/11.4 Data Modification.md
    index addff612..a2dcb83a 100644
    --- a/odata-protocol/11.4 Data Modification.md	
    +++ b/odata-protocol/11.4 Data Modification.md	
    @@ -545,7 +545,83 @@ nested delta representation to:
       ]
     }
     ```
    +:::
    +
    +::: example
    +Example ##ex: When updating an entity with a 4.01 `PUT` request, the target of a
    +non-containment navigation property can be replaced without changing either the
    +old or the new targeted entity itself. The targeted entity can then only be
    +specified by an entity reference (see [#OData-JSON#EntityReference]).
    +
    +The following JSON payload changes the last name and the manager of Suzanne Brown.
    +The effect would be the same if the `@context` was omitted from the request.
    +:::: side-by-side
    +::::: caption
    +Request
    +```json
    +PUT http://host/service/Employees(7)?$expand=Manager
    +Content-Type: application/json
    +
    +{
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "@context": "$metadata#$ref",
    +    "@id": "Employees(6)"
    +  }
    +}
    +```
    +:::::
    +::::: caption
    +Response
    +```json
    +{
    +  "@context": "$metadata#Employees/$entity",
    +  "EmployeeID": 7,
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "EmployeeID": 6,
    +    "FirstName": "Patricia",
    +    "LastName": "Miller"
    +  }
    +}
    +```
    +:::::
    +::::
    +
    +If the targeted entity in the payload contains some structural properties,
    +`PUT` resets all its other structural properties. The following alternative
    +payload resets the first and last names of the new manager.
    +The effect would be the same if the `@id` was omitted from the request.
    +:::: side-by-side
    +```json
    +PUT http://host/service/Employees(7)?$expand=Manager
    +Content-Type: application/json
     
    +{
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "@id": "Employees(6)",
    +    "EmployeeID": 6
    +  }
    +}
    +```
    +```json
    +{
    +  "@context": "$metadata#Employees/$entity",
    +  "EmployeeID": 7,
    +  "FirstName": "Suzanne",
    +  "LastName": "Brown-Johnson",
    +  "Manager": {
    +    "EmployeeID": 6,
    +    "FirstName": null,
    +    "LastName": null
    +  }
    +}
    +```
    +::::
     :::
     
     Clients MAY associate an id with individual nested entities in the
    diff --git a/styles/odata.css b/styles/odata.css
    index aa19bb20..1b808b0e 100644
    --- a/styles/odata.css
    +++ b/styles/odata.css
    @@ -1,3 +1,7 @@
    +:root {
    +  --indent: 40px;
    +}
    +
     a:target,
     span:target {
       background-color: yellow;
    @@ -168,11 +172,31 @@ td > code {
     
     .example pre,
     .rep {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
    +}
    +
    +.caption p {
    +  margin-left: var(--indent);
    +  margin-bottom: -1em;
    +}
    +
    +.side-by-side {
    +  margin: -1em 0;
    +}
    +
    +.side-by-side:after {
    +  content: "";
    +  display: block;
    +  clear: both;
    +}
    +
    +.side-by-side > div {
    +  width: 50%;
    +  float: left;
     }
     
     .indent {
    -  margin-left: 40px;
    +  margin-left: var(--indent);
     }
     
     td pre {
    @@ -195,7 +219,7 @@ mjx-container {
     
     mjx-container[display="true"] {
       text-align: left !important;
    -  margin-left: 40px !important;
    +  margin-left: var(--indent) !important;
     }
     
     code .er {