From 36dc1d67235be46c7d0e3ec41ce5a2a8460468c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 09:31:02 +0200 Subject: [PATCH 1/7] null result with instance annotations --- docs/odata-json-format/odata-json-format.html | 1475 +++++++++-------- docs/odata-json-format/odata-json-format.md | 97 +- odata-json-format/10 Media Entity.md | 29 +- 3 files changed, 825 insertions(+), 776 deletions(-) diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index 66603c796..1e27803f0 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -1269,10 +1269,10 @@

10 Media Entity

11 Individual Property or Operation Response

An individual property or operation response is represented as a JSON object.

-

A single-valued property or operation response that has the null value does not have a representation; see OData-Protocol.

-

A property or operation response that is of a primitive type is represented as an object with a single name/value pair, whose name is value and whose value is a primitive value.

-

A property or operation response that is of complex type is represented as a complex value.

-

A property or operation response that is of a collection type is represented as an object with a single name/value pair whose name is value. Its value is the JSON representation of a collection of complex type values or collection of primitive values.

+

A single-valued property or operation response that has the null value and carries no control information or instance annotations does not have a representation; see OData-Protocol.

+

A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value and whose value is a primitive value or null.

+

A property or operation response that is of complex type is represented as a complex value. If the value is null, the JSON object consists of name/value pairs for the @context and the control information and instance annotations only.

+

A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value. Its value is the JSON representation of a collection of complex type values or collection of primitive values.

Example 26: primitive value

{
@@ -1312,6 +1312,17 @@ 

"value": [] }

+
+

Example 31: null value accompanied by an instance annotation

+
{
+  "@context": "http://host/service/$metadata#Model.Address",
+  "@Core.Messages": [{
+    "code": "EPOSTCODE",
+    "message": "Could not resolve postcode XYZ",
+    "severity": "error"
+  }]
+}
+

Note: the context URL is optional in requests.


@@ -1334,17 +1345,17 @@

functions or actions are advertised in the object representing a single entity.

The nextLink control information MUST be included in a response that represents a partial result.

-

Example 31:

-
{
-  "@context": "…",
-  "@count": 37,
-  "value": [
-    {  },
-    {  },
-    {  }
-  ],
-  "@nextLink": "…?$skiptoken=342r89"
-}
+

Example 32:

+
{
+  "@context": "…",
+  "@count": 37,
+  "value": [
+    {  },
+    {  },
+    {  }
+  ],
+  "@nextLink": "…?$skiptoken=342r89"
+}

@@ -1355,21 +1366,21 @@

14

A collection of entity references is represented as a collection of entities, with entity reference representations instead of entity representations as items in the array value of the value name/value pair.

The outermost JSON object in a response MUST contain a context control information and MAY contain count, nextLink, or deltaLink control information.

-

Example 32: entity reference to order 10643

-
{
-  "@context": "http://host/service/$metadata#$ref",
-  "@id": "Orders(10643)"
-}
+

Example 33: entity reference to order 10643

+
{
+  "@context": "http://host/service/$metadata#$ref",
+  "@id": "Orders(10643)"
+}
-

Example 33: collection of entity references

-
{
-  "@context": "http://host/service/$metadata#Collection($ref)",
-  "value": [
-    { "@id": "Orders(10643)" },
-    { "@id": "Orders(10759)" }
-  ]
-}
+

Example 34: collection of entity references

+
{
+  "@context": "http://host/service/$metadata#Collection($ref)",
+  "value": [
+    { "@id": "Orders(10643)" },
+    { "@id": "Orders(10759)" }
+  ]
+}

@@ -1387,60 +1398,60 @@

15.1

If the delta response contains a partial list of changes, it MUST include a next link for the client to retrieve the next set of changes.

The last page of a delta response SHOULD contain a delta link in place of the next link for retrieving subsequent changes once the current set of changes has been applied to the initial set.

-

Example 34: a 4.01 delta response with three changes, in order of occurrence

-
    -
  1. ContactName for customer BOTTM was changed to Susan Halvenstern
  2. -
  3. Customer ANTON was deleted
  4. -
  5. ContactName for customer ALFKI was changed to Blake Smithe
  6. -
-
{
-  "@context": "http://host/service/$metadata#Customers/$delta",
-  "@count":3,
-  "value": [
-    {
-      "@id": "Customers('BOTTM')",
-      "ContactName": "Susan Halvenstern"
-    },
-    {
-      "@removed": {
-        "reason": "deleted"
-      },
-      "@id": "Customers('ANTON')"
-    },
-    {
-      "@id": "Customers('ALFKI')",
-      "ContactName": "Blake Smithe"
-    }
-  ],
-  "@deltaLink": "Customers?$deltatoken=8015"
-}
-
-
-

Example 35: a 4.0 delta response with three changes, in order of occurrence

+

Example 35: a 4.01 delta response with three changes, in order of occurrence

  1. ContactName for customer BOTTM was changed to Susan Halvenstern
  2. Customer ANTON was deleted
  3. ContactName for customer ALFKI was changed to Blake Smithe
{
-  "@odata.context": "http://host/service/$metadata#Customers/$delta",
-  "@odata.count": 3,
+  "@context": "http://host/service/$metadata#Customers/$delta",
+  "@count":3,
   "value": [
     {
-      "@odata.id": "Customers('BOTTM')",
-      "ContactName": "Susan Halvenstern",
+      "@id": "Customers('BOTTM')",
+      "ContactName": "Susan Halvenstern"
     },
     {
-      "@odata.context": "#Customers/$deletedEntity",
-      "@odata.id": "Customers('ANTON')"
-    },
-    {
-      "@odata.id": "Customers('ALFKI')",
-      "ContactName": "Blake Smithe"
-    }
-  ],
-  "@odata.deltaLink": "Customers?$deltatoken=8015"
-}
+ "@removed": { + "reason": "deleted" + }, + "@id": "Customers('ANTON')" + }, + { + "@id": "Customers('ALFKI')", + "ContactName": "Blake Smithe" + } + ], + "@deltaLink": "Customers?$deltatoken=8015" +}
+ +
+

Example 36: a 4.0 delta response with three changes, in order of occurrence

+
    +
  1. ContactName for customer BOTTM was changed to Susan Halvenstern
  2. +
  3. Customer ANTON was deleted
  4. +
  5. ContactName for customer ALFKI was changed to Blake Smithe
  6. +
+
{
+  "@odata.context": "http://host/service/$metadata#Customers/$delta",
+  "@odata.count": 3,
+  "value": [
+    {
+      "@odata.id": "Customers('BOTTM')",
+      "ContactName": "Susan Halvenstern",
+    },
+    {
+      "@odata.context": "#Customers/$deletedEntity",
+      "@odata.id": "Customers('ANTON')"
+    },
+    {
+      "@odata.id": "Customers('ALFKI')",
+      "ContactName": "Blake Smithe"
+    }
+  ],
+  "@odata.deltaLink": "Customers?$deltatoken=8015"
+}
@@ -1469,12 +1480,12 @@

15.3 Del
  • reason — either deleted, if the entity was deleted (destroyed), or changed if the entity was removed from membership in the result (i.e., due to a data change).
  • -

    Example 36: deleted entity in OData 4.0 response — note that id is a property, not control information

    -
    {
    -  "@context": "#Customers/$deletedEntity",
    -  "reason": "deleted",
    -  "id": "Customers('ANTON')"
    -}
    +

    Example 37: deleted entity in OData 4.0 response — note that id is a property, not control information

    +
    {
    +  "@context": "#Customers/$deletedEntity",
    +  "reason": "deleted",
    +  "id": "Customers('ANTON')"
    +}

    In OData 4.01 payloads the deleted-entity object MUST include the following properties, regardless of the specified metadata value. For ordered payloads, this control information MUST follow the payload ordering constraints.

      @@ -1484,22 +1495,22 @@

      15.3 Del

      For full metadata the context control information MUST be included. It also MUST be included if the entity set of the deleted entity cannot be determined from the surrounding context.

      The deleted-entity object MAY include additional properties of the entity, as well as annotations, and MAY include related entities, related deleted entities, or a delta or full representation of a related collection of entities, to represent related entities that have been modified or deleted.

      -

      Example 37: deleted entity in OData 4.01 response with id control information (prefixed with an @)

      -
      {
      -  "@context": "#Customers/$deletedEntity",
      -  "@removed": {
      -    "reason": "deleted",
      -    "@myannoation.deletedBy": "Mario"
      -  },
      -  "@id": "Customers('ANTON')"
      -}
      +

      Example 38: deleted entity in OData 4.01 response with id control information (prefixed with an @)

      +
      {
      +  "@context": "#Customers/$deletedEntity",
      +  "@removed": {
      +    "reason": "deleted",
      +    "@myannoation.deletedBy": "Mario"
      +  },
      +  "@id": "Customers('ANTON')"
      +}
      -

      Example 38: entity removed OData 4.01 response without id control information and instead all key fields (ID is the single key field of Customer)

      -
      {
      -  "@removed": {},
      -  "ID": "ANTON"
      -}
      +

      Example 39: entity removed OData 4.01 response without id control information and instead all key fields (ID is the single key field of Customer)

      +
      {
      +  "@removed": {},
      +  "ID": "ANTON"
      +}

    @@ -1514,7 +1525,7 @@

    added/changed entity, an entity reference, a deleted entity, or a null value (if no entity is related as the outcome of the change). Collection-valued navigation properties are represented either as a delta representation or as a full representation of the collection.

    If the expanded navigation property represents a delta, it MUST be represented as an array-valued control information delta on the navigation property. Added/changed entities or entity references are added to the collection. Deleted entities in a nested delta representation represent entities no longer part of the collection. If the deleted entity specifies a reason as deleted, then the entity is both removed from the collection and deleted, otherwise it is removed from the collection and only deleted if the navigation property is a containment navigation property. The array MUST NOT contain added or deleted links.

    -

    Example 39: changes to related orders represented as a 4.01 nested delta representation

    +

    Example 40: changes to related orders represented as a 4.01 nested delta representation

    1. For Customer ALFKI:
        @@ -1525,57 +1536,57 @@

        {
        -  "@context": "http://host/service/$metadata#Customers/$delta",
        -  "@count":3,
        -  "value": [
        -    {
        -      "@id": "Customers('ALFKI')",
        -      "Orders@delta": [
        -        {
        -          "@removed": {
        -            "reason": "changed"
        -          },
        -          "@id": "Orders(10643)"
        -        },
        -        {
        -          "@id": "Orders(10645)",
        -          "ShippingAddress": {
        -            "Street": "23 Tsawassen Blvd.",
        -            "City": "Tsawassen",
        -            "Region": "BC",
        -            "PostalCode": "T2F 8M4"
        -          }
        -        }
        -      ]
        -    },
        -    {
        -      "@removed": {
        -        "reason": "deleted"
        -      },
        -      "@id": "Customers('ANTON')"
        -    },
        -    {
        -      "@id": "Customers('ALFKI')",
        -      "ContactName": "Blake Smithe"
        -    }
        -  ],
        -  "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
        -}

    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$delta",
    +  "@count":3,
    +  "value": [
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "Orders@delta": [
    +        {
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "@id": "Orders(10643)"
    +        },
    +        {
    +          "@id": "Orders(10645)",
    +          "ShippingAddress": {
    +            "Street": "23 Tsawassen Blvd.",
    +            "City": "Tsawassen",
    +            "Region": "BC",
    +            "PostalCode": "T2F 8M4"
    +          }
    +        }
    +      ]
    +    },
    +    {
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "@id": "Customers('ANTON')"
    +    },
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
    +}

    If the expanded navigation property is a full representation of the collection, it MUST be represented as an expanded navigation property, and its array value MUST represent the full set of entities related according to that relationship and satisfying any specified expand options, or a partial list containing a nextLink. Following this chain of next links MUST eventually return the full set of entities related according to that relationship and satisfying any specified expand options; the final page does not include a delta link.

    Members of the expanded navigation property MUST be represented as added/changed entities or entity references and MUST NOT include added links, deleted links, or deleted entities. Any entity not represented in the collection has either been removed, deleted, or changed such that it no longer satisfies the expand options in the defining query. In any case, clients SHOULD NOT receive additional notifications for such removed entities.

    -

    Example 40: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)

    -
    {
    -  "@context": "http://host/service/$metadata#Customers/$entity/$delta",
    -  
    -  "Orders@count": 42,
    -  "Orders": [  ],
    -  "Orders@nextLink": "…",
    -  
    -  "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
    -}
    +

    Example 41: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)

    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$entity/$delta",
    +  
    +  "Orders@count": 42,
    +  "Orders": [  ],
    +  "Orders@nextLink": "…",
    +  
    +  "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
    +}

    @@ -1583,7 +1594,7 @@

    added or deleted links. Changes to related entities are represented as top-level entities whose context control information specifies the entity set of the entity. This control information MUST be present for entities are not part of the entity set specified by the context URL, regardless of the specified metadata value.

    -

    Example 41: changes to related orders represented as a 4.0 flattened delta payload

    +

    Example 42: changes to related orders represented as a 4.0 flattened delta payload

    1. Order 10643 was removed from customer ALFKI
    2. Order 10645 was added to customer ALFKI
    3. @@ -1591,43 +1602,43 @@

      {
      -  "@odata.context": "http://host/service/$metadata#Customers/$delta",
      -  "@odata.count": 5,
      -  "value": [
      -    {
      -      "@odata.context": "#Customers/$deletedLink",
      -      "source": "Customers('ALFKI')",
      -      "relationship": "Orders",
      -      "target": "Orders(10643)"
      -    },
      -    {
      -      "@odata.context": "#Customers/$link",
      -      "source": "Customers('BOTTM')",
      -      "relationship": "Orders",
      -      "target": "Orders(10645)"
      -    },
      -    {
      -      "@odata.context": "#Orders/$entity",
      -      "@odata.id": "Orders(10645)",
      -      "ShippingAddress": {
      -        "Street": "23 Tsawassen Blvd.",
      -        "City": "Tsawassen",
      -        "Region": "BC",
      -        "PostalCode": "T2F 8M4"
      -      }
      -    },
      -    {
      -      "@odata.context": "#Customers/$deletedEntity",
      -      "@odata.id": "Customers('ANTON')"
      -    },
      -    {
      -      "@odata.id": "Customers('ALFKI')",
      -      "ContactName": "Blake Smithe"
      -    }
      -  ],
      -  "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
      -}

    +
    {
    +  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    +  "@odata.count": 5,
    +  "value": [
    +    {
    +      "@odata.context": "#Customers/$deletedLink",
    +      "source": "Customers('ALFKI')",
    +      "relationship": "Orders",
    +      "target": "Orders(10643)"
    +    },
    +    {
    +      "@odata.context": "#Customers/$link",
    +      "source": "Customers('BOTTM')",
    +      "relationship": "Orders",
    +      "target": "Orders(10645)"
    +    },
    +    {
    +      "@odata.context": "#Orders/$entity",
    +      "@odata.id": "Orders(10645)",
    +      "ShippingAddress": {
    +        "Street": "23 Tsawassen Blvd.",
    +        "City": "Tsawassen",
    +        "Region": "BC",
    +        "PostalCode": "T2F 8M4"
    +      }
    +    },
    +    {
    +      "@odata.context": "#Customers/$deletedEntity",
    +      "@odata.id": "Customers('ANTON')"
    +    },
    +    {
    +      "@odata.id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
    +}

    If a property of an entity is dependent upon the property of another entity within the expanded set of entities being tracked, then both the change to the dependent property as well as the change to the principal property or added/deleted link corresponding to the change to the dependent property are returned in the delta response.

    @@ -1667,7 +1678,7 @@

    The body of a PATCH request to a URL identifying a collection of entities is a JSON object. It MUST contain the context control information with a string value of #$delta, and it MUST contain an array-valued property named value containing all added, changed, or deleted entities. OData 4.0 delta payloads MAY additionally include added or deleted links between entities.

    -

    Example 42: 4.01 collection-update request for customers with expanded orders represented inline as a delta

    +

    Example 43: 4.01 collection-update request for customers with expanded orders represented inline as a delta

    1. Add customer EASTC
    2. Change ContactName of customer AROUT
    3. @@ -1682,90 +1693,90 @@

      Add order 10643 to customer ANATR
    4. Remove order 10311 from customer DUMON
    -
    PATCH /service/Customers HTTP/1.1
    -Host: host
    -Content-Type: application/json
    -Content-Length: ###
    -Prefer: return=minimal, continue-on-error
    -
    -{
    -  "@context": "#$delta",
    -  "value": [
    -    {
    -      "@Org.OData.Core.V1.ContentID": "1",
    -      "CustomerID": "EASTC",
    -      "CompanyName": "Eastern Connection",
    -      "ContactName": "Ann Devon",
    -      "ContactTitle": "Sales Agent"
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "2",
    -      "CustomerID": "AROUT",
    -      "ContactName": "Thomas Hardy",
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "3",
    -      "@removed": {
    -        "reason": "deleted"
    -      },
    -      "CustomerID": "ANTON"
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "4",
    -      "CustomerID": "ALFKI",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.1",
    -          "OrderID": 11011,
    -          "CustomerID": "ALFKI",
    -          "EmployeeID": 3,
    -          "OrderDate": "1998-04-09T00:00:00Z",
    -          "RequiredDate": "1998-05-07T00:00:00Z",
    -          "ShippedDate": "1998-04-13T00:00:00Z"
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.2",
    -          "@id": "Orders(10692)"
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.3",
    -          "@id": "Orders(10835)",
    -          "RequiredDate": "1998-01-23T00:00:00Z",
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.4",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10643
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "5",
    -      "CustomerID": "ANATR",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "5.1",
    -          "OrderID": 10643
    -        }
    -      ],
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "6",
    -      "CustomerID": "DUMON",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "6.1",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10311
    -        }
    -      ]
    -    }
    -  ]
    -}
    +
    PATCH /service/Customers HTTP/1.1
    +Host: host
    +Content-Type: application/json
    +Content-Length: ###
    +Prefer: return=minimal, continue-on-error
    +
    +{
    +  "@context": "#$delta",
    +  "value": [
    +    {
    +      "@Org.OData.Core.V1.ContentID": "1",
    +      "CustomerID": "EASTC",
    +      "CompanyName": "Eastern Connection",
    +      "ContactName": "Ann Devon",
    +      "ContactTitle": "Sales Agent"
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "2",
    +      "CustomerID": "AROUT",
    +      "ContactName": "Thomas Hardy",
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "3",
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "CustomerID": "ANTON"
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "4",
    +      "CustomerID": "ALFKI",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.1",
    +          "OrderID": 11011,
    +          "CustomerID": "ALFKI",
    +          "EmployeeID": 3,
    +          "OrderDate": "1998-04-09T00:00:00Z",
    +          "RequiredDate": "1998-05-07T00:00:00Z",
    +          "ShippedDate": "1998-04-13T00:00:00Z"
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.2",
    +          "@id": "Orders(10692)"
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.3",
    +          "@id": "Orders(10835)",
    +          "RequiredDate": "1998-01-23T00:00:00Z",
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.4",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10643
    +        }
    +      ]
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "5",
    +      "CustomerID": "ANATR",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "5.1",
    +          "OrderID": 10643
    +        }
    +      ],
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "6",
    +      "CustomerID": "DUMON",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "6.1",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10311
    +        }
    +      ]
    +    }
    +  ]
    +}

    Assuming all changes can be applied without errors, the response would be

    HTTP/1.1 204 No Content
     Preference-Applied: return=minimal, continue-on-error
    @@ -1786,124 +1797,124 @@ 

    Add order 10643 to customer ‘ANATR’ - failed without further info
  • Remove order 10311 from customer ‘DUMON’ - failed without further info
  • -
    HTTP/1.1 200 OK
    -Content-Type: application/json
    -Content-Length: ###
    -Preference-Applied: return=minimal, continue-on-error
    -
    -{
    -  "@context": "#$delta",
    -  "value": [
    -    {
    -      "@Org.OData.Core.V1.ContentID": "1",
    -      "CustomerID": "EASTC",
    -      "@removed": {
    -        "reason": "changed"
    -      },
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "insert",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "incmplt",
    -          "message": "Required field(s) not provided",
    -          "target": "Address",
    -          "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "2",
    -      "CustomerID": "AROUT",
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "update",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "r-o",
    -          "message": "Customer is archived and cannot be changed",
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "3",
    -      "CustomerID": "ANTON",
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "delete",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "ufo",
    -          "message": "Customer has unfinished orders and cannot be deleted",
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "4",
    -      "CustomerID": "ALFKI",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.3",
    -          "@id": "Orders(10835)",
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "update",
    -            "responseCode": 400,
    -            "info": {
    -              "code": "b/s",
    -              "message": "RequiredDate cannot be changed because Order is already being shipped",
    -              "severity": "error"
    -            }
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "5",
    -      "CustomerID": "ANATR",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "5.1",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10643,
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "link",
    -            "responseCode": 404,
    -            "info": null
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "6",
    -      "CustomerID": "DUMON",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "6.1",
    -          "OrderID": 10311,
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "unlink",
    -            "responseCode": 404
    -          }
    -        }
    -      ]
    -    }
    -  ]
    -}
    -

    Without the continue-on-error preference processing would stop on the first error, and the response would be a standard OData error response

    -
    HTTP/1.1 400 Bad Request
    +
    HTTP/1.1 200 OK
     Content-Type: application/json
     Content-Length: ###
    -
    -{
    -  "error": {
    -    "code": "incmplt",
    -    "message": "Required field(s) not provided",
    -    "target": "Customers('EASTC')/Address",
    -    "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
    -  }
    -}
    +Preference-Applied: return=minimal, continue-on-error + +{ + "@context": "#$delta", + "value": [ + { + "@Org.OData.Core.V1.ContentID": "1", + "CustomerID": "EASTC", + "@removed": { + "reason": "changed" + }, + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "insert", + "responseCode": 400, + "info": { + "code": "incmplt", + "message": "Required field(s) not provided", + "target": "Address", + "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ], + "severity": "error" + } + } + }, + { + "@Org.OData.Core.V1.ContentID": "2", + "CustomerID": "AROUT", + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "update", + "responseCode": 400, + "info": { + "code": "r-o", + "message": "Customer is archived and cannot be changed", + "severity": "error" + } + } + }, + { + "@Org.OData.Core.V1.ContentID": "3", + "CustomerID": "ANTON", + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "delete", + "responseCode": 400, + "info": { + "code": "ufo", + "message": "Customer has unfinished orders and cannot be deleted", + "severity": "error" + } + } + }, + { + "@Org.OData.Core.V1.ContentID": "4", + "CustomerID": "ALFKI", + "Orders@delta": [ + { + "@Org.OData.Core.V1.ContentID": "4.3", + "@id": "Orders(10835)", + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "update", + "responseCode": 400, + "info": { + "code": "b/s", + "message": "RequiredDate cannot be changed because Order is already being shipped", + "severity": "error" + } + } + } + ] + }, + { + "@Org.OData.Core.V1.ContentID": "5", + "CustomerID": "ANATR", + "Orders@delta": [ + { + "@Org.OData.Core.V1.ContentID": "5.1", + "@removed": { + "reason": "changed" + }, + "OrderID": 10643, + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "link", + "responseCode": 404, + "info": null + } + } + ] + }, + { + "@Org.OData.Core.V1.ContentID": "6", + "CustomerID": "DUMON", + "Orders@delta": [ + { + "@Org.OData.Core.V1.ContentID": "6.1", + "OrderID": 10311, + "@Org.OData.Core.V1.DataModificationException": { + "failedOperation": "unlink", + "responseCode": 404 + } + } + ] + } + ] +}
    +

    Without the continue-on-error preference processing would stop on the first error, and the response would be a standard OData error response

    +
    HTTP/1.1 400 Bad Request
    +Content-Type: application/json
    +Content-Length: ###
    +
    +{
    +  "error": {
    +    "code": "incmplt",
    +    "message": "Required field(s) not provided",
    +    "target": "Customers('EASTC')/Address",
    +    "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
    +  }
    +}

    @@ -1920,47 +1931,47 @@

    16 Bound

    The title name/value pair contains the function or action title as a string.

    If metadata=minimal is requested, the target name/value pair MUST be included if its value differs from the canonical function or action URL.

    -

    Example 43: minimal representation of a function where all overloads are applicable

    -
    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "#Model.RemainingVacation": {},
    -  
    -}
    -
    -
    -

    Example 44: full representation of a specific overload with parameter alias for the Year parameter

    +

    Example 44: minimal representation of a function where all overloads are applicable

    {
       "@context": "http://host/service/$metadata#Employees/$entity",
    -  "#Model.RemainingVacation(Year)": {
    -    "title": "Remaining vacation from year.",
    -    "target": "Employees(2)/RemainingVacation(Year=@Year)"
    -  },
    -  
    -}
    + "#Model.RemainingVacation": {}, + +}
    -

    Example 45: full representation in a collection

    +

    Example 45: full representation of a specific overload with parameter alias for the Year parameter

    {
    -  "@context": "http://host/service/$metadata#Employees",
    -  "#Model.RemainingVacation": {
    -    "title": "Remaining Vacation",
    -    "target": "Managers(22)/Employees/RemainingVacation"
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "#Model.RemainingVacation(Year)": {
    +    "title": "Remaining vacation from year.",
    +    "target": "Employees(2)/RemainingVacation(Year=@Year)"
       },
    -  "value": [  ]
    +  
     }
    -

    Example 46: full representation in a nested collection

    +

    Example 46: full representation in a collection

    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "@type": "Model.Manager",
    -  "ID":22,
    -  
    -  "Employees#RemainingVacation": {
    -    "title": "RemainingVacation",
    -    "target": "Managers(22)/Employees/RemainingVacation"
    -  }
    -}
    + "@context": "http://host/service/$metadata#Employees", + "#Model.RemainingVacation": { + "title": "Remaining Vacation", + "target": "Managers(22)/Employees/RemainingVacation" + }, + "value": [ ] +}
    + +
    +

    Example 47: full representation in a nested collection

    +
    {
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "@type": "Model.Manager",
    +  "ID":22,
    +  
    +  "Employees#RemainingVacation": {
    +    "title": "RemainingVacation",
    +    "target": "Managers(22)/Employees/RemainingVacation"
    +  }
    +}

    @@ -1976,47 +1987,47 @@

    17 Bound Action

    The title name/value pair contains the function or action title as a string.

    If metadata=minimal is requested, the target name/value pair MUST be included if its value differs from the canonical function or action URL.

    -

    Example 47: minimal representation in an entity

    -
    {
    -  "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    -  "#Model.Approve": {},
    -  
    -}
    -
    -
    -

    Example 48: full representation in an entity:

    +

    Example 48: minimal representation in an entity

    {
       "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    -  "#Model.Approve": {
    -    "title": "Approve Leave Request",
    -    "target": "LeaveRequests(2)/Approve"
    -  },
    -  
    -}
    + "#Model.Approve": {}, + +}
    -

    Example 49: full representation in a collection

    +

    Example 49: full representation in an entity:

    {
    -  "@context": "http://host/service/$metadata#LeaveRequests",
    +  "@context": "http://host/service/$metadata#LeaveRequests/$entity",
       "#Model.Approve": {
    -    "title": "Approve All Leave Requests",
    -    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    +    "title": "Approve Leave Request",
    +    "target": "LeaveRequests(2)/Approve"
       },
    -  "value": [  ]
    +  
     }
    -

    Example 50: full representation in a nested collection

    +

    Example 50: full representation in a collection

    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "@type": "Model.Manager",
    -  "ID": 22,
    -  
    -  "LeaveRequests#Model.Approve": {
    -    "title": "Approve All Leave Requests",
    -    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    -  }
    -}
    + "@context": "http://host/service/$metadata#LeaveRequests", + "#Model.Approve": { + "title": "Approve All Leave Requests", + "target": "Employees(22)/Model.Manager/LeaveRequests/Approve" + }, + "value": [ ] +}
    + +
    +

    Example 51: full representation in a nested collection

    +
    {
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "@type": "Model.Manager",
    +  "ID": 22,
    +  
    +  "LeaveRequests#Model.Approve": {
    +    "title": "Approve All Leave Requests",
    +    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    +  }
    +}

    @@ -2027,79 +2038,79 @@

    Each non-binding parameter value is encoded as a separate name/value pair in this JSON object. The name is the name of the parameter. The value is the parameter value in the JSON representation appropriate for its type. Entity typed parameter values MAY include a subset of the properties, or just the entity reference, as appropriate to the action. Stream typed parameter values are represented following the same rules as inlined stream properties.

    Entities as parameter values are represented as explained in section 6.

    -

    Example 51: Create a quote for a product that does not yet exist. The Product parameter takes a transient entity.

    -
    POST http://host/service/CreateQuote
    -Content-Type: application/json
    -
    -{
    -  "Product": {
    -    "Name": "Our best ever",
    -    "Price": 1
    -  },
    -  "CustomerID": "ALFKI"
    -}
    -
    -
    -

    Example 52: Create a quote for an existing product. The Product parameter takes a non-transient entity which can be identified through its entity-id:

    +

    Example 52: Create a quote for a product that does not yet exist. The Product parameter takes a transient entity.

    POST http://host/service/CreateQuote
     Content-Type: application/json
     
     {
       "Product": {
    -    "@id": "Products(14)"
    -  },
    -  "CustomerID": "ALFKI"
    -}
    -

    or, as in section 15.2, through its primary key fields plus, if necessary, its context:

    + "Name": "Our best ever", + "Price": 1 + }, + "CustomerID": "ALFKI" +}
    + +
    +

    Example 53: Create a quote for an existing product. The Product parameter takes a non-transient entity which can be identified through its entity-id:

    POST http://host/service/CreateQuote
     Content-Type: application/json
     
     {
       "Product": {
    -    "@context": "#Products",
    -    "ProductID": 14
    -  },
    -  "CustomerID": "ALFKI"
    -}
    + "@id": "Products(14)" + }, + "CustomerID": "ALFKI" +}
    +

    or, as in section 15.2, through its primary key fields plus, if necessary, its context:

    +
    POST http://host/service/CreateQuote
    +Content-Type: application/json
    +
    +{
    +  "Product": {
    +    "@context": "#Products",
    +    "ProductID": 14
    +  },
    +  "CustomerID": "ALFKI"
    +}

    Alternatively, values of non-binding parameters MAY be specified as common expressions OData-URL, section 5.1.1. In the case of a bound action these MAY contain path expressions OData-URL, section 5.1.1.15, which the service evaluates on the binding parameter value. Such parameters are encoded as name/value pairs where the name is the name of the parameter followed by @expression and the value is the common expression. As the following example demonstrates, non-transient entities can be passed as non-binding action parameters through a resource path in this way.

    -

    Example 53: An employee requests leave from their manager for the next two weeks:

    -
    POST /service/Employees(23)/self.RequestLeave
    -Host: host
    -Content-Type: application/json
    -
    -{
    -  "StartDate@expression": "now()",
    -  "EndDate@expression": "now() add duration'P14D'",
    -  "Approver@expression": "Manager"
    -}
    -

    The expression Manager is evaluated on the binding parameter value Employees(23).

    -

    When invoking an unbound action through an action import, expressions involving paths must start with $root:

    -
    POST /service/RequestLeave
    +

    Example 54: An employee requests leave from their manager for the next two weeks:

    +
    POST /service/Employees(23)/self.RequestLeave
     Host: host
     Content-Type: application/json
     
     {
    -  "Requester@expression": "$root/services/Employee(23)",
    -  "StartDate@expression": "now()",
    -  "EndDate@expression": "now() add duration'P14D'",
    -  "Approver@expression": "$root/services/Employee(23)/Manager"
    -}
    + "StartDate@expression": "now()", + "EndDate@expression": "now() add duration'P14D'", + "Approver@expression": "Manager" +}
    +

    The expression Manager is evaluated on the binding parameter value Employees(23).

    +

    When invoking an unbound action through an action import, expressions involving paths must start with $root:

    +
    POST /service/RequestLeave
    +Host: host
    +Content-Type: application/json
    +
    +{
    +  "Requester@expression": "$root/services/Employee(23)",
    +  "StartDate@expression": "now()",
    +  "EndDate@expression": "now() add duration'P14D'",
    +  "Approver@expression": "$root/services/Employee(23)/Manager"
    +}

    Inside a batch request the common expressions can also be value references starting with $, as introduced in OData-Protocol, section 11.7.6.

    Non-binding parameters that are nullable or annotated with the term Core.OptionalParameter defined in OData-VocCore MAY be omitted from the request body. If an omitted parameter is not annotated (and thus nullable), it MUST be interpreted as having the null value. 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. Note: a nullable non-binding parameter is equivalent to being annotated as optional with a default value of null.

    -

    Example 54:

    -
    {
    -  "param1": 42,
    -  "param2": {
    -    "Street": "One Microsoft Way",
    -    "Zip": 98052
    -  },
    -  "param3": [ 1, 42, 99 ],
    -  "param4": null
    -}
    +

    Example 55:

    +
    {
    +  "param1": 42,
    +  "param2": {
    +    "Street": "One Microsoft Way",
    +    "Zip": 98052
    +  },
    +  "param3": [ 1, 42, 99 ],
    +  "param4": null
    +}

    In order to invoke an action with no non-binding parameters, the client passes an empty JSON object in the body of the request. 4.01 Services MUST also support clients passing an empty request body for this case.

    @@ -2137,7 +2148,7 @@

    19.1 Batch

    A body MUST NOT be specified if the method is get or delete.

    The request object and the headers object MUST NOT contain name/value pairs with duplicate names. This is in conformance with RFC7493.

    -

    Example 55: a batch request that contains the following individual requests in the order listed

    +

    Example 56: a batch request that contains the following individual requests in the order listed

    1. A query request
    2. An atomicity group that contains the following requests: @@ -2148,57 +2159,6 @@

      19.1 Batch
    3. A second query request

    Note: For brevity, in the example, request bodies are excluded in favor of English descriptions inside <> brackets and OData-Version headers are omitted.

    -
    POST /service/$batch HTTP/1.1
    -Host: host
    -OData-Version: 4.01
    -Content-Type: application/json
    -Content-Length: ###
    -
    -{
    -  "requests": [
    -    {
    -      "id": "0",
    -      "method": "get",
    -      "url": "/service/Customers('ALFKI')"
    -    },
    -    {
    -      "id": "1",
    -      "atomicityGroup": "group1",
    -      "dependsOn": [ "0" ],
    -      "method": "patch",
    -      "url": "/service/Customers('ALFKI')",
    -      "headers": {
    -        "Prefer": "return=minimal"
    -      },
    -      "body": <JSON representation of changes to Customer ALFKI>
    -    },
    -    {
    -      "id": "2",
    -      "atomicityGroup": "group1",
    -      "method": "post",
    -      "url": "/service/Customers",
    -      "body": <JSON representation of a new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "dependsOn": [ "group1" ],
    -      "method": "get",
    -      "url": "/service/Products"
    -    }
    -  ]
    -}
    -
    - -
    -

    19.2 Referencing New Entities

    -
    -

    The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.

    -
    -

    Example 56: a batch request that contains the following operations in the order listed:

    -
      -
    • Insert a new entity (with id = 1)
    • -
    • Insert a second new entity (references request with id = 1)
    • -
    POST /service/$batch HTTP/1.1
     Host: host
     OData-Version: 4.01
    @@ -2208,30 +2168,47 @@ 

    { "requests": [ { - "id": "1", - "method": "post", - "url": "/service/Customers", - "body": <JSON representation of a new Customer entity> - }, - { - "id": "2", - "dependsOn": [ "1" ] - "method": "post", - "url": "$1/Orders", - "body": <JSON representation of a new Order> - } - ] -}

    + "id": "0", + "method": "get", + "url": "/service/Customers('ALFKI')" + }, + { + "id": "1", + "atomicityGroup": "group1", + "dependsOn": [ "0" ], + "method": "patch", + "url": "/service/Customers('ALFKI')", + "headers": { + "Prefer": "return=minimal" + }, + "body": <JSON representation of changes to Customer ALFKI> + }, + { + "id": "2", + "atomicityGroup": "group1", + "method": "post", + "url": "/service/Customers", + "body": <JSON representation of a new Customer entity> + }, + { + "id": "3", + "dependsOn": [ "group1" ], + "method": "get", + "url": "/service/Products" + } + ] +}
    -

    19.3 Referencing an ETag

    +

    19.2 Referencing New Entities

    +

    The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.

    Example 57: a batch request that contains the following operations in the order listed:

      -
    • Get an Employee (with id = 1)
    • -
    • Update the salary only if the employee has not changed
    • +
    • Insert a new entity (with id = 1)
    • +
    • Insert a second new entity (references request with id = 1)
    POST /service/$batch HTTP/1.1
     Host: host
    @@ -2243,36 +2220,29 @@ 

    "requests": [ { "id": "1", - "method": "get", - "url": "/service/Employees(0)", - "headers": { - "accept": "application/json" - } - }, - { - "id": "2", - "dependsOn": [ "1" ], - "method": "patch", - "url": "/service/Employees(0)", - "headers": { - "if-match": "$1" - }, - "body": { - "Salary": 75000 - } - } - ] -}

    + "method": "post", + "url": "/service/Customers", + "body": <JSON representation of a new Customer entity> + }, + { + "id": "2", + "dependsOn": [ "1" ] + "method": "post", + "url": "$1/Orders", + "body": <JSON representation of a new Order> + } + ] +}
    -

    19.4 Referencing Response Body Values

    +

    19.3 Referencing an ETag

    Example 58: 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
    • +
    • Get an Employee (with id = 1)
    • +
    • Update the salary only if the employee has not changed
    POST /service/$batch HTTP/1.1
     Host: host
    @@ -2285,7 +2255,7 @@ 

    { "id": "1", "method": "get", - "url": "/service/Employees/0?$select=Building", + "url": "/service/Employees(0)", "headers": { "accept": "application/json" } @@ -2293,14 +2263,55 @@

    { "id": "2", "dependsOn": [ "1" ], - "method": "get", - "url": "/service/Employees?$filter=Building eq $1/Building", + "method": "patch", + "url": "/service/Employees(0)", "headers": { - "accept": "application/json" - } - } - ] -}

    + "if-match": "$1" + }, + "body": { + "Salary": 75000 + } + } + ] +}
    + +
    +
    +

    19.4 Referencing Response Body Values

    +
    +
    +

    Example 59: 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
    • +
    +
    POST /service/$batch HTTP/1.1
    +Host: host
    +OData-Version: 4.01
    +Content-Type: application/json
    +Content-Length: ###
    +
    +{
    +  "requests": [
    +    {
    +      "id": "1",
    +      "method": "get",
    +      "url": "/service/Employees/0?$select=Building",
    +      "headers": {
    +        "accept": "application/json"
    +      }
    +    },
    +    {
    +      "id": "2",
    +      "dependsOn": [ "1" ],
    +      "method": "get",
    +      "url": "/service/Employees?$filter=Building eq $1/Building",
    +      "headers": {
    +        "accept": "application/json"
    +      }
    +    }
    +  ]
    +}
    @@ -2325,38 +2336,38 @@

    19.6 Bat

    If the media type is not exactly equal to application/json (i.e. it is a subtype or has format parameters), the headers object MUST contain a name/value pair with the name content-type whose value is the media type.

    Relative URLs in a response object follow the rules for relative URLs based on the request URL of the corresponding request. Especially: URLs in responses MUST NOT contain $-prefixed request identifiers.

    -

    Example 59: referencing the batch request example 55 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.01
    -Content-Length: ####
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 200,
    -      "body": <JSON representation of the Customer entity with key ALFKI>
    -    },
    -    {
    -      "id": "1",
    -      "status": 204
    -    },
    -    {
    -      "id": "2",
    -      "status": 201,
    -      "headers": {
    -        "location": "http://host/service.svc/Customer('POIUY')"
    -      },
    -      "body": <JSON representation of the new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "status": 404,
    -      "body": <Error message>
    -    }
    -  ]
    -}
    +

    Example 60: referencing the batch request example 56 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.01
    +Content-Length: ####
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 200,
    +      "body": <JSON representation of the Customer entity with key ALFKI>
    +    },
    +    {
    +      "id": "1",
    +      "status": 204
    +    },
    +    {
    +      "id": "2",
    +      "status": 201,
    +      "headers": {
    +        "location": "http://host/service.svc/Customer('POIUY')"
    +      },
    +      "body": <JSON representation of the new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "status": 404,
    +      "body": <Error message>
    +    }
    +  ]
    +}

    @@ -2365,83 +2376,83 @@

    A batch request that specifies the respond-async preference MAY be executed asynchronously. This means that the “outer” batch request is executed asynchronously; this preference does not automatically cascade down to the individual requests within the batch. After successful execution of the batch request the response to the batch request is returned in the body of a response to an interrogation request against the status monitor resource URL, see OData-Protocol, section 11.6.

    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 nextLink control information in the JSON batch response, thus signaling that the response is only a partial result. A subsequent GET request to the next link MAY result in a 202 Accepted response with a location header pointing to a new status monitor resource.

    -

    Example 60: referencing the example 55 above again, assume that the request is sent with the respond-async preference. This results in a 202 response pointing to a status monitor resource:

    -
    HTTP/1.1 202 Accepted
    -Location: http://service-root/async-monitor-0
    -Retry-After: ###
    +

    Example 61: referencing the example 56 above again, assume that the request is sent with the respond-async preference. This results in a 202 response pointing to a status monitor resource:

    +
    HTTP/1.1 202 Accepted
    +Location: http://service-root/async-monitor-0
    +Retry-After: ###

    When interrogating the monitor URL only the first request in the batch has finished processing and all the remaining requests are still being processed. The service signals that asynchronous processing is “finished” and returns a partial result with the first response and a next link. The client did not explicitly accept application/http, so the response is “unwrapped” and only indicates with the AsyncResult header that it is a response to a status monitor resource:

    -
    HTTP/1.1 200 OK
    -AsyncResult: 200
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 200,
    -      "body": <JSON representation of the Customer entity with key ALFKI>
    -    }
    -  ],
    -  "@nextLink": "…?$skiptoken=YmF0Y2gx"
    -}
    +
    HTTP/1.1 200 OK
    +AsyncResult: 200
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 200,
    +      "body": <JSON representation of the Customer entity with key ALFKI>
    +    }
    +  ],
    +  "@nextLink": "…?$skiptoken=YmF0Y2gx"
    +}

    Client makes a GET request to the next link and receives a 202 response with the location of a new monitor resource.

    -
    HTTP/1.1 202 Accepted
    -Location: http://service-root/async-monitor-1
    -Retry-After: ###
    +
    HTTP/1.1 202 Accepted
    +Location: http://service-root/async-monitor-1
    +Retry-After: ###

    After some time a GET request to the monitor resource returns the remainder of the result.

    -
    HTTP/1.1 200 OK
    -AsyncResult: 200
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "1",
    -      "status": 204
    -    },
    -    {
    -      "id": "2",
    -      "status": 201,
    -      "headers": {
    -        "location": "http://host/service.svc/Customer('POIUY')"
    -      },
    -      "body": <JSON representation of the new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "status": 404,
    -      "body": <Error message>
    -    }
    -  ]
    -}
    +
    HTTP/1.1 200 OK
    +AsyncResult: 200
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "1",
    +      "status": 204
    +    },
    +    {
    +      "id": "2",
    +      "status": 201,
    +      "headers": {
    +        "location": "http://host/service.svc/Customer('POIUY')"
    +      },
    +      "body": <JSON representation of the new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "status": 404,
    +      "body": <Error message>
    +    }
    +  ]
    +}

    In addition to the above interaction pattern individual requests within a batch with no other requests depending on it and not part of an atomicity group MAY be executed asynchronously if they specify the respond-async preference and if the service responds with a JSON batch response. In this case the response array contains a response object for each asynchronously executed individual request with a status of 202, a location header pointing to an individual status monitor resource, and optionally a retry-after header.

    -

    Example 61: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously

    -
    HTTP/1.1 200 OK
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 202,
    -      "headers": {
    -        "location": "http://service-root/async-monitor-0"
    -      }
    -    },
    -    {
    -      "id": "1",
    -      "status": 204
    -    }
    -  ]
    -}
    +

    Example 62: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously

    +
    HTTP/1.1 200 OK
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 202,
    +      "headers": {
    +        "location": "http://service-root/async-monitor-0"
    +      }
    +    },
    +    {
    +      "id": "1",
    +      "status": 204
    +    }
    +  ]
    +}

    @@ -2455,20 +2466,20 @@

    single primitive or collection value, the annotations for the value appear next to the value property and are not prefixed with a property name.

    -

    Example 62:

    -
    {
    -  "@context": "http://host/service/$metadata#Customers",
    -  "@com.example.customer.setkind": "VIPs",
    -  "value": [
    -    {
    -      "@com.example.display.highlight": true,
    -      "ID": "ALFKI",
    -      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
    -      "CompanyName": "Alfreds Futterkiste",
    -      "Orders@com.example.display.style#simple": { "order": 2 }
    -    }
    -  ]
    -}
    +

    Example 63:

    +
    {
    +  "@context": "http://host/service/$metadata#Customers",
    +  "@com.example.customer.setkind": "VIPs",
    +  "value": [
    +    {
    +      "@com.example.display.highlight": true,
    +      "ID": "ALFKI",
    +      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
    +      "CompanyName": "Alfreds Futterkiste",
    +      "Orders@com.example.display.style#simple": { "order": 2 }
    +    }
    +  ]
    +}

    20.1 Annotate a JSON Object

    @@ -2509,25 +2520,25 @@

    21.1 Err

    Service implementations SHOULD carefully consider which information to include in production environments to guard against potential security concerns around information disclosure.

    Error responses MAY contain annotations in any of its JSON objects.

    -

    Example 63:

    -
    {
    -  "error": {
    -    "code": "err123",
    -    "message": "Unsupported functionality",
    -    "target": "query",
    -    "details": [
    -      {
    -      "code": "forty-two",
    -      "target": "$search",
    -      "message": "$search query option not supported"
    -      }
    -    ],
    -    "innererror": {
    -      "trace": [],
    -      "context": {}
    -    }
    -  }
    -}
    +

    Example 64:

    +
    {
    +  "error": {
    +    "code": "err123",
    +    "message": "Unsupported functionality",
    +    "target": "query",
    +    "details": [
    +      {
    +      "code": "forty-two",
    +      "target": "$search",
    +      "message": "$search query option not supported"
    +      }
    +    ],
    +    "innererror": {
    +      "trace": [],
    +      "context": {}
    +    }
    +  }
    +}

    @@ -2541,10 +2552,10 @@

    21.2 In
  • Control characters (00 to 1F and 7F) and Unicode characters beyond 00FF within JSON strings are encoded as \uXXXX or \uXXXX\uXXXX (see RFC8259, section 7)

  • -

    Example 64: note that this is one HTTP header line without any line breaks or optional whitespace

    -
    OData-error: {"code":"err123","message":"Unsupported
    -functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    -query option not supported"}]}
    +

    Example 65: note that this is one HTTP header line without any line breaks or optional whitespace

    +
    OData-error: {"code":"err123","message":"Unsupported
    +functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    +query option not supported"}]}

    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index 231c32917..d0272483c 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1897,19 +1897,24 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation; see +`null` value and carries no [control information](#ControlInformation) +or [instance annotations](#InstanceAnnotations) +does not have a representation; see [OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is -represented as an object with a single name/value pair, whose name is +represented as an object with a name/value pair whose name is `value` and whose value is a [primitive -value](#PrimitiveValue). +value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). +as a [complex value](#ComplexValue). If the value is `null`, the JSON object +consists of name/value pairs for the `@context` and the +[control information](#ControlInformation) +and [instance annotations](#InstanceAnnotations) only. A property or operation response that is of a collection type is -represented as an object with a single name/value pair whose name is +represented as an object with a name/value pair whose name is `value`. Its value is the JSON representation of a [collection of complex type values](#CollectionofComplexValues) or [collection of primitive values](#CollectionofPrimitiveValues). @@ -1968,6 +1973,20 @@ Example 30: empty collection of complex values ``` ::: +::: example +Example 31: `null` value accompanied by an instance annotation +```json +{ + "@context": "http://host/service/$metadata#Model.Address", + "@Core.Messages": [{ + "code": "EPOSTCODE", + "message": "Could not resolve postcode XYZ", + "severity": "error" + }] +} +``` +::: + Note: the context URL is optional in requests. ------- @@ -2039,7 +2058,7 @@ control information MUST be included in a response that represents a partial result. ::: example -Example 31: +Example 32: ```json { "@context": "…", @@ -2076,7 +2095,7 @@ control information and MAY contain [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. ::: example -Example 32: entity reference to order 10643 +Example 33: entity reference to order 10643 ```json { "@context": "http://host/service/$metadata#$ref", @@ -2086,7 +2105,7 @@ Example 32: entity reference to order 10643 ::: ::: example -Example 33: collection of entity references +Example 34: collection of entity references ```json { "@context": "http://host/service/$metadata#Collection($ref)", @@ -2133,7 +2152,7 @@ subsequent changes once the current set of changes has been applied to the initial set. ::: example -Example 34: a 4.01 delta response with three changes, in order of +Example 35: a 4.01 delta response with three changes, in order of occurrence 1. `ContactName` for customer `BOTTM` was changed to `Susan Halvenstern` @@ -2166,7 +2185,7 @@ occurrence ::: ::: example -Example 35: a 4.0 delta response with three changes, in order of +Example 36: a 4.0 delta response with three changes, in order of occurrence 1. `ContactName` for customer `BOTTM` was changed to `Susan Halvenstern` @@ -2261,7 +2280,7 @@ following optional property, regardless of the specified result (i.e., due to a data change). ::: example -Example 36: deleted entity in OData 4.0 response --- note that `id` is +Example 37: deleted entity in OData 4.0 response --- note that `id` is a property, not control information ```json { @@ -2312,7 +2331,7 @@ representation of a related collection of entities, to represent related entities that have been modified or deleted. ::: example -Example 37: deleted entity in OData 4.01 response with `id` +Example 38: deleted entity in OData 4.01 response with `id` control information (prefixed with an `@`) ```json { @@ -2327,7 +2346,7 @@ control information (prefixed with an `@`) ::: ::: example -Example 38: entity removed OData 4.01 response without `id` +Example 39: entity removed OData 4.01 response without `id` control information and instead all key fields (`ID` is the single key field of `Customer`) ```json @@ -2366,7 +2385,7 @@ only deleted if the navigation property is a containment navigation property. The array MUST NOT contain [added](#AddedLink) or [deleted links](#DeletedLink). ::: example -Example 39: changes to related orders represented as a 4.01 nested delta representation +Example 40: changes to related orders represented as a 4.01 nested delta representation 1. For Customer `ALFKI`: 1. Order 10643 was removed @@ -2432,7 +2451,7 @@ clients SHOULD NOT receive additional notifications for such removed entities. ::: example -Example 40: 4.01 delta response for a single entity with an expanded navigation +Example 41: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a [next link](#ControlInformationnextLinkodatanextLink)) ```json @@ -2458,7 +2477,7 @@ information MUST be present for entities are not part of the entity set specifie [`metadata`](#ControllingtheAmountofControlInformationinResponses) value. ::: example -Example 41: changes to related orders represented as a 4.0 flattened delta payload +Example 42: changes to related orders represented as a 4.0 flattened delta payload 1. Order 10643 was removed from customer `ALFKI` 2. Order 10645 was added to customer `ALFKI` @@ -2576,7 +2595,7 @@ entities. OData 4.0 delta payloads MAY additionally include [added](#AddedLink) [deleted](#DeletedLink) links between entities. ::: example -Example 42: 4.01 collection-update request for customers with expanded orders represented +Example 43: 4.01 collection-update request for customers with expanded orders represented inline as a delta 1. Add customer `EASTC` 2. Change `ContactName` of customer `AROUT` @@ -2883,7 +2902,7 @@ is requested, the `target` name/value pair MUST be included if its value differs from the canonical function or action URL. ::: example -Example 43: minimal representation of a function where all overloads are +Example 44: minimal representation of a function where all overloads are applicable ```json { @@ -2895,7 +2914,7 @@ applicable ::: ::: example -Example 44: full representation of a specific overload with parameter +Example 45: full representation of a specific overload with parameter alias for the `Year` parameter ```json { @@ -2910,7 +2929,7 @@ alias for the `Year` parameter ::: ::: example -Example 45: full representation in a collection +Example 46: full representation in a collection ```json { "@context": "http://host/service/$metadata#Employees", @@ -2924,7 +2943,7 @@ Example 45: full representation in a collection ::: ::: example -Example 46: full representation in a nested collection +Example 47: full representation in a nested collection ```json { "@context": "http://host/service/$metadata#Employees/$entity", @@ -2987,7 +3006,7 @@ is requested, the `target` name/value pair MUST be included if its value differs from the canonical function or action URL. ::: example -Example 47: minimal representation in an entity +Example 48: minimal representation in an entity ```json { "@context": "http://host/service/$metadata#LeaveRequests/$entity", @@ -2998,7 +3017,7 @@ Example 47: minimal representation in an entity ::: ::: example -Example 48: full representation in an entity: +Example 49: full representation in an entity: ```json { "@context": "http://host/service/$metadata#LeaveRequests/$entity", @@ -3012,7 +3031,7 @@ Example 48: full representation in an entity: ::: ::: example -Example 49: full representation in a collection +Example 50: full representation in a collection ```json { "@context": "http://host/service/$metadata#LeaveRequests", @@ -3026,7 +3045,7 @@ Example 49: full representation in a collection ::: ::: example -Example 50: full representation in a nested collection +Example 51: full representation in a nested collection ```json { "@context": "http://host/service/$metadata#Employees/$entity", @@ -3059,7 +3078,7 @@ Stream typed parameter values are represented following the same rules as inline Entities as parameter values are represented as explained in [section 6](#Entity). ::: example -Example 51: Create a quote for a product that does not yet exist. The `Product` +Example 52: Create a quote for a product that does not yet exist. The `Product` parameter takes a transient entity. ```json POST http://host/service/CreateQuote @@ -3076,7 +3095,7 @@ Content-Type: application/json ::: ::: example -Example 52: Create a quote for an existing product. The `Product` +Example 53: Create a quote for an existing product. The `Product` parameter takes a non-transient entity which can be identified through its entity-id: ```json @@ -3116,7 +3135,7 @@ non-transient entities can be passed as non-binding action parameters through a resource path in this way. ::: example -Example 53: An employee requests leave from their manager for the next two weeks: +Example 54: An employee requests leave from their manager for the next two weeks: ```json POST /service/Employees(23)/self.RequestLeave Host: host @@ -3162,7 +3181,7 @@ parameter is equivalent to being annotated as optional with a default value of `null`. ::: example -Example 54: +Example 55: ```json { "param1": 42, @@ -3308,7 +3327,7 @@ The request object and the `headers` object MUST NOT contain name/value pairs wi This is in conformance with [RFC7493](#rfc7493). ::: example -Example 55: a batch request that contains +Example 56: a batch request that contains the following individual requests in the order listed 1. A query request @@ -3371,7 +3390,7 @@ contains a relative URL, clients MUST be able to resolve it relative to the request's URL even if that contains such a reference. ::: example -Example 56: a batch request that contains the following operations in +Example 57: a batch request that contains the following operations in the order listed: - Insert a new entity (with `id = 1`) @@ -3406,7 +3425,7 @@ Content-Length: ### ## 19.3 Referencing an ETag ::: example -Example 57: a batch request that contains the following operations in +Example 58: a batch request that contains the following operations in the order listed: - Get an Employee (with `id` = 1) @@ -3449,7 +3468,7 @@ Content-Length: ### ## 19.4 Referencing Response Body Values ::: example -Example 58: a batch request that contains the following operations in +Example 59: a batch request that contains the following operations in the order listed: - Get an employee (with `Content-ID = 1`) @@ -3580,7 +3599,7 @@ request. Especially: URLs in responses MUST NOT contain `$`-prefixed request identifiers. ::: example -Example 59: referencing the batch request [example 55](#batchRequest) above, assume all +Example 60: referencing the batch request [example 56](#batchRequest) above, assume all the requests except the final query request succeed. In this case the response would be ```json @@ -3637,7 +3656,7 @@ to the next link MAY result in a `202 Accepted` response with a `location` header pointing to a new status monitor resource. ::: example -Example 60: referencing the [example 55](#batchRequest) above again, assume that the +Example 61: referencing the [example 56](#batchRequest) above again, assume that the request is sent with the `respond-async` preference. This results in a `202` response pointing to a status monitor resource: ```json @@ -3727,7 +3746,7 @@ asynchronously executed individual request with a `status` of individual status monitor resource, and optionally a `retry-after` header. ::: example -Example 61: the first individual request is processed asynchronously, +Example 62: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously ```json HTTP/1.1 200 OK @@ -3790,7 +3809,7 @@ the annotations for the value appear next to the `value` property and are not prefixed with a property name. ::: example -Example 62: +Example 63: ```json { "@context": "http://host/service/$metadata#Customers", @@ -3900,7 +3919,7 @@ Error responses MAY contain [annotations](#InstanceAnnotations) in any of its JSON objects. ::: example -Example 63: +Example 64: ```json { "error": { @@ -3949,7 +3968,7 @@ header-appropriate way: [RFC8259](#rfc8259), section 7) ::: example -Example 64: note that this is one HTTP header line without any line +Example 65: note that this is one HTTP header line without any line breaks or optional whitespace ```json OData-error: {"code":"err123","message":"Unsupported diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index 348bfdd74..d31dd19cc 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -33,19 +33,24 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation; see +`null` value and carries no [control information](#ControlInformation) +or [instance annotations](#InstanceAnnotations) +does not have a representation; see [OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is -represented as an object with a single name/value pair, whose name is +represented as an object with a name/value pair whose name is `value` and whose value is a [primitive -value](#PrimitiveValue). +value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). +as a [complex value](#ComplexValue). If the value is `null`, the JSON object +consists of name/value pairs for the `@context` and the +[control information](#ControlInformation) +and [instance annotations](#InstanceAnnotations) only. A property or operation response that is of a collection type is -represented as an object with a single name/value pair whose name is +represented as an object with a name/value pair whose name is `value`. Its value is the JSON representation of a [collection of complex type values](#CollectionofComplexValues) or [collection of primitive values](#CollectionofPrimitiveValues). @@ -104,6 +109,20 @@ Example ##ex: empty collection of complex values ``` ::: +::: example +Example ##ex: `null` value accompanied by an instance annotation +```json +{ + "@context": "http://host/service/$metadata#Model.Address", + "@Core.Messages": [{ + "code": "EPOSTCODE", + "message": "Could not resolve postcode XYZ", + "severity": "error" + }] +} +``` +::: + Note: the context URL is optional in requests. ------- From 69aa249665d4e1b4495d2e7e1edb6c86e3798d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 09:43:17 +0200 Subject: [PATCH 2/7] Explain null example --- docs/odata-json-format/odata-json-format.html | 6 +++--- docs/odata-json-format/odata-json-format.md | 8 +++++--- odata-json-format/10 Media Entity.md | 8 +++++--- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index 1e27803f0..8b90188bf 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -1313,12 +1313,12 @@

    }
    -

    Example 31: null value accompanied by an instance annotation

    +

    Example 31: An action is invoked when a utilities customer moves into a building, it returns the address. After a successful move-in it might return the null value accompanied by an instance annotation:

    {
       "@context": "http://host/service/$metadata#Model.Address",
       "@Core.Messages": [{
    -    "code": "EPOSTCODE",
    -    "message": "Could not resolve postcode XYZ",
    +    "code": "EADDRESS",
    +    "message": "Street name not yet determined",
         "severity": "error"
       }]
     }
    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index d0272483c..7deb04a8a 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1974,13 +1974,15 @@ Example 30: empty collection of complex values ::: ::: example -Example 31: `null` value accompanied by an instance annotation +Example 31: An action is invoked when a utilities customer moves into a building, +it returns the address. After a successful move-in it might return the +`null` value accompanied by an instance annotation: ```json { "@context": "http://host/service/$metadata#Model.Address", "@Core.Messages": [{ - "code": "EPOSTCODE", - "message": "Could not resolve postcode XYZ", + "code": "EADDRESS", + "message": "Street name not yet determined", "severity": "error" }] } diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index d31dd19cc..95ebc2d0d 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -110,13 +110,15 @@ Example ##ex: empty collection of complex values ::: ::: example -Example ##ex: `null` value accompanied by an instance annotation +Example ##ex: An action is invoked when a utilities customer moves into a building, +it returns the address. After a successful move-in it might return the +`null` value accompanied by an instance annotation: ```json { "@context": "http://host/service/$metadata#Model.Address", "@Core.Messages": [{ - "code": "EPOSTCODE", - "message": "Could not resolve postcode XYZ", + "code": "EADDRESS", + "message": "Street name not yet determined", "severity": "error" }] } From eeb9d5a51d4edf855e98f88d546f9bdec50a30f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 09:56:41 +0200 Subject: [PATCH 3/7] Rephrased --- docs/odata-json-format/odata-json-format.html | 4 ++-- docs/odata-json-format/odata-json-format.md | 10 +++++----- odata-json-format/10 Media Entity.md | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index 8b90188bf..437b6c745 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -1269,9 +1269,9 @@

    10 Media Entity

    11 Individual Property or Operation Response

    An individual property or operation response is represented as a JSON object.

    -

    A single-valued property or operation response that has the null value and carries no control information or instance annotations does not have a representation; see OData-Protocol.

    +

    A single-valued property or operation response that has the null value does not have a representation provided that it carries no control information other than context and no instance annotations; see OData-Protocol.

    A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value and whose value is a primitive value or null.

    -

    A property or operation response that is of complex type is represented as a complex value. If the value is null, the JSON object consists of name/value pairs for the @context and the control information and instance annotations only.

    +

    A property or operation response that is of complex type is represented as a complex value. If the value is null, the JSON object consists of name/value pairs for the control information and instance annotations only.

    A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value. Its value is the JSON representation of a collection of complex type values or collection of primitive values.

    Example 26: primitive value

    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index 7deb04a8a..c6fb9ba36 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1897,10 +1897,10 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value and carries no [control information](#ControlInformation) -or [instance annotations](#InstanceAnnotations) -does not have a representation; see -[OData-Protocol](#ODataProtocol). +`null` value does not have a representation provided that it carries no +[control information](#ControlInformation) other than +[`context`](#ControlInformationcontextodatacontext) +and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is @@ -1909,7 +1909,7 @@ value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the `@context` and the +consists of name/value pairs for the [control information](#ControlInformation) and [instance annotations](#InstanceAnnotations) only. diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index 95ebc2d0d..2c7ddab0e 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -33,10 +33,10 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value and carries no [control information](#ControlInformation) -or [instance annotations](#InstanceAnnotations) -does not have a representation; see -[OData-Protocol](#ODataProtocol). +`null` value does not have a representation provided that it carries no +[control information](#ControlInformation) other than +[`context`](#ControlInformationcontextodatacontext) +and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is @@ -45,7 +45,7 @@ value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the `@context` and the +consists of name/value pairs for the [control information](#ControlInformation) and [instance annotations](#InstanceAnnotations) only. From 944edea32653651d96717e1f79b378aabcd8f75a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 12:51:46 +0200 Subject: [PATCH 4/7] Serialization of entity-valued nulls --- docs/odata-json-format/odata-json-format.html | 28 ++++++++++++------- docs/odata-json-format/odata-json-format.md | 27 +++++++++++++----- odata-json-format/10 Media Entity.md | 11 ++++---- odata-json-format/5 Service Document.md | 16 ++++++++++- 4 files changed, 58 insertions(+), 24 deletions(-) diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index 437b6c745..ec6523b51 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -903,7 +903,16 @@

    5 Se

    6 Entity

    An entity is serialized as a JSON object. It MAY contain context, type, or deltaLink control information.

    -

    Each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.

    +

    If a nullable single-valued navigation property or entity-valued annotation or return type of an operation has the null value, the value is serialized as follows:

    + +

    Otherwise, each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.

    An entity in a payload may be a complete entity, a projected entity (see System Query Option $select in OData-Protocol), or a partial entity update (see Update an Entity in OData-Protocol).

    An entity representation can be (modified and) round-tripped to the service directly. The context URL is used in requests only as a base for relative URLs.

    @@ -1269,9 +1278,9 @@

    10 Media Entity

    11 Individual Property or Operation Response

    An individual property or operation response is represented as a JSON object.

    -

    A single-valued property or operation response that has the null value does not have a representation provided that it carries no control information other than context and no instance annotations; see OData-Protocol.

    +

    A single-valued property or operation response that has the null value does not have a representation provided that, with minimal metadata, it carries no control information other than context and no instance annotations; see OData-Protocol.

    A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value and whose value is a primitive value or null.

    -

    A property or operation response that is of complex type is represented as a complex value. If the value is null, the JSON object consists of name/value pairs for the control information and instance annotations only.

    +

    A property or operation response that is of complex type is represented as a complex value. If the value is null, the context control information is omitted and the JSON object consists of name/value pairs for the other control information and instance annotations only.

    A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value. Its value is the JSON representation of a collection of complex type values or collection of primitive values.

    Example 26: primitive value

    @@ -1315,13 +1324,12 @@

    Example 31: An action is invoked when a utilities customer moves into a building, it returns the address. After a successful move-in it might return the null value accompanied by an instance annotation:

    {
    -  "@context": "http://host/service/$metadata#Model.Address",
    -  "@Core.Messages": [{
    -    "code": "EADDRESS",
    -    "message": "Street name not yet determined",
    -    "severity": "error"
    -  }]
    -}
    + "@Core.Messages": [{ + "code": "EADDRESS", + "message": "Street name not yet determined", + "severity": "error" + }] +}

    Note: the context URL is optional in requests.

    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index c6fb9ba36..d1c5cd893 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1295,7 +1295,21 @@ An entity is serialized as a JSON object. It MAY contain or [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. -Each [property](#StructuralProperty) to be transmitted is +If a nullable single-valued navigation property or +entity-valued annotation or return type of an operation has the `null` value, +the value is serialized as follows: +- If, with [minimal metadata](#metadataminimalodatametadataminimal), + the value carries no [control information](#ControlInformation) other than + [`context`](#ControlInformationcontextodatacontext) + and no [instance annotations](#InstanceAnnotations), + - the value does not have a representation as response to a request (see [OData-Protocol, section 9.1.4](https://docs.oasis-open.org/odata/odata/v4.02/odata-v4.02-part1-protocol.html#ResponseCode204NoContent)) + - but is represented by the JSON literal `null` when it occurs in a name/value pair + in another JSON object (for example, an [expanded single-valued navigation property](#ExpandedNavigationProperty)). +- Otherwise the context control information is omitted and the serialization produces + a JSON object consisting of name/value pairs for the + other control information and instance annotations only. + +Otherwise, each [property](#StructuralProperty) to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant. @@ -1897,7 +1911,8 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation provided that it carries no +`null` value does not have a representation provided that, with +[minimal metadata](#metadataminimalodatametadataminimal), it carries no [control information](#ControlInformation) other than [`context`](#ControlInformationcontextodatacontext) and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). @@ -1908,10 +1923,9 @@ represented as an object with a name/value pair whose name is value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the -[control information](#ControlInformation) -and [instance annotations](#InstanceAnnotations) only. +as a [complex value](#ComplexValue). If the value is `null`, the context control information +is omitted and the JSON object consists of name/value pairs for the +other control information and instance annotations only. A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is @@ -1979,7 +1993,6 @@ it returns the address. After a successful move-in it might return the `null` value accompanied by an instance annotation: ```json { - "@context": "http://host/service/$metadata#Model.Address", "@Core.Messages": [{ "code": "EADDRESS", "message": "Street name not yet determined", diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index 2c7ddab0e..2cea00a2e 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -33,7 +33,8 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation provided that it carries no +`null` value does not have a representation provided that, with +[minimal metadata](#metadataminimalodatametadataminimal), it carries no [control information](#ControlInformation) other than [`context`](#ControlInformationcontextodatacontext) and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). @@ -44,10 +45,9 @@ represented as an object with a name/value pair whose name is value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). If the value is `null`, the JSON object -consists of name/value pairs for the -[control information](#ControlInformation) -and [instance annotations](#InstanceAnnotations) only. +as a [complex value](#ComplexValue). If the value is `null`, the context control information +is omitted and the JSON object consists of name/value pairs for the +other control information and instance annotations only. A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is @@ -115,7 +115,6 @@ it returns the address. After a successful move-in it might return the `null` value accompanied by an instance annotation: ```json { - "@context": "http://host/service/$metadata#Model.Address", "@Core.Messages": [{ "code": "EADDRESS", "message": "Street name not yet determined", diff --git a/odata-json-format/5 Service Document.md b/odata-json-format/5 Service Document.md index 6140d0505..baaa719c1 100644 --- a/odata-json-format/5 Service Document.md +++ b/odata-json-format/5 Service Document.md @@ -99,7 +99,21 @@ An entity is serialized as a JSON object. It MAY contain or [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. -Each [property](#StructuralProperty) to be transmitted is +If a nullable single-valued navigation property or +entity-valued annotation or return type of an operation has the `null` value, +the value is serialized as follows: +- If, with [minimal metadata](#metadataminimalodatametadataminimal), + the value carries no [control information](#ControlInformation) other than + [`context`](#ControlInformationcontextodatacontext) + and no [instance annotations](#InstanceAnnotations), + - the value does not have a representation as response to a request (see [#OData-Protocol#ResponseCode204NoContent]) + - but is represented by the JSON literal `null` when it occurs in a name/value pair + in another JSON object (for example, an [expanded single-valued navigation property](#ExpandedNavigationProperty)). +- Otherwise the context control information is omitted and the serialization produces + a JSON object consisting of name/value pairs for the + other control information and instance annotations only. + +Otherwise, each [property](#StructuralProperty) to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant. From ebf397218f1a3e4f92d7ec34925da5e8d320f4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 14:41:26 +0200 Subject: [PATCH 5/7] Place the additional text (mostly) in [OData-Protocol] --- odata-json-format/10 Media Entity.md | 26 +++---------------------- odata-json-format/5 Service Document.md | 16 +-------------- odata-protocol/8 Header Fields.md | 14 +++++++++++-- 3 files changed, 16 insertions(+), 40 deletions(-) diff --git a/odata-json-format/10 Media Entity.md b/odata-json-format/10 Media Entity.md index 2cea00a2e..37e684e2e 100644 --- a/odata-json-format/10 Media Entity.md +++ b/odata-json-format/10 Media Entity.md @@ -33,11 +33,8 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation provided that, with -[minimal metadata](#metadataminimalodatametadataminimal), it carries no -[control information](#ControlInformation) other than -[`context`](#ControlInformationcontextodatacontext) -and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). +`null` value does not have a representation; see +[OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is @@ -45,9 +42,7 @@ represented as an object with a name/value pair whose name is value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). If the value is `null`, the context control information -is omitted and the JSON object consists of name/value pairs for the -other control information and instance annotations only. +as a [complex value](#ComplexValue). A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is @@ -109,21 +104,6 @@ Example ##ex: empty collection of complex values ``` ::: -::: example -Example ##ex: An action is invoked when a utilities customer moves into a building, -it returns the address. After a successful move-in it might return the -`null` value accompanied by an instance annotation: -```json -{ - "@Core.Messages": [{ - "code": "EADDRESS", - "message": "Street name not yet determined", - "severity": "error" - }] -} -``` -::: - Note: the context URL is optional in requests. ------- diff --git a/odata-json-format/5 Service Document.md b/odata-json-format/5 Service Document.md index baaa719c1..6140d0505 100644 --- a/odata-json-format/5 Service Document.md +++ b/odata-json-format/5 Service Document.md @@ -99,21 +99,7 @@ An entity is serialized as a JSON object. It MAY contain or [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. -If a nullable single-valued navigation property or -entity-valued annotation or return type of an operation has the `null` value, -the value is serialized as follows: -- If, with [minimal metadata](#metadataminimalodatametadataminimal), - the value carries no [control information](#ControlInformation) other than - [`context`](#ControlInformationcontextodatacontext) - and no [instance annotations](#InstanceAnnotations), - - the value does not have a representation as response to a request (see [#OData-Protocol#ResponseCode204NoContent]) - - but is represented by the JSON literal `null` when it occurs in a name/value pair - in another JSON object (for example, an [expanded single-valued navigation property](#ExpandedNavigationProperty)). -- Otherwise the context control information is omitted and the serialization produces - a JSON object consisting of name/value pairs for the - other control information and instance annotations only. - -Otherwise, each [property](#StructuralProperty) to be transmitted is +Each [property](#StructuralProperty) to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant. diff --git a/odata-protocol/8 Header Fields.md b/odata-protocol/8 Header Fields.md index aa388e72c..d0988a7f8 100644 --- a/odata-protocol/8 Header Fields.md +++ b/odata-protocol/8 Header Fields.md @@ -930,9 +930,19 @@ Requests](#AsynchronousBatchRequests). ### ##subsubsec Response Code `204 No Content` A request returns `204 No Content` if the requested resource has the -`null` value, or if the service applies a +`null` value and carries no control information [#OData-JSON#ControlInformation] +other than what the minimal metadata format [#OData-JSON#metadataminimalodatametadataminimal] +requires and no [instance annotations](#VocabularyExtensibility). + +It also returns `204 No Content` if the service applies a [`return=minimal`](#Preferencereturnrepresentationandreturnminimal) preference. -In this case, the response body MUST be empty. + +In these cases, the response body MUST be empty. + +If the requested resource has the `null` value but carries additional control information +or instance annotations, the request returns [`200 OK`](#ResponseCode200OK) instead but +omits the [context URL](#ContextURL) from the representation of the response, +which then consists of the other control information and instance annotations only. As defined in [RFC9110](#rfc9110), a [Data Modification Request](#DataModification) that responds with From 5312965b624dc489348f0eaddfa93f530ea10ce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 14:41:38 +0200 Subject: [PATCH 6/7] Rebuilt --- docs/odata-json-format/odata-json-format.html | 1481 ++++++++--------- docs/odata-json-format/odata-json-format.md | 110 +- docs/odata-protocol/odata-protocol.html | 5 +- docs/odata-protocol/odata-protocol.md | 14 +- 4 files changed, 785 insertions(+), 825 deletions(-) diff --git a/docs/odata-json-format/odata-json-format.html b/docs/odata-json-format/odata-json-format.html index ec6523b51..8aebc90f8 100644 --- a/docs/odata-json-format/odata-json-format.html +++ b/docs/odata-json-format/odata-json-format.html @@ -903,16 +903,7 @@

    5 Se

    6 Entity

    An entity is serialized as a JSON object. It MAY contain context, type, or deltaLink control information.

    -

    If a nullable single-valued navigation property or entity-valued annotation or return type of an operation has the null value, the value is serialized as follows:

    - -

    Otherwise, each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.

    +

    Each property to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant.

    An entity in a payload may be a complete entity, a projected entity (see System Query Option $select in OData-Protocol), or a partial entity update (see Update an Entity in OData-Protocol).

    An entity representation can be (modified and) round-tripped to the service directly. The context URL is used in requests only as a base for relative URLs.

    @@ -1278,9 +1269,9 @@

    10 Media Entity

    11 Individual Property or Operation Response

    An individual property or operation response is represented as a JSON object.

    -

    A single-valued property or operation response that has the null value does not have a representation provided that, with minimal metadata, it carries no control information other than context and no instance annotations; see OData-Protocol.

    +

    A single-valued property or operation response that has the null value does not have a representation; see OData-Protocol.

    A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is value and whose value is a primitive value or null.

    -

    A property or operation response that is of complex type is represented as a complex value. If the value is null, the context control information is omitted and the JSON object consists of name/value pairs for the other control information and instance annotations only.

    +

    A property or operation response that is of complex type is represented as a complex value.

    A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is value. Its value is the JSON representation of a collection of complex type values or collection of primitive values.

    Example 26: primitive value

    @@ -1321,16 +1312,6 @@

    "value": [] }

    -
    -

    Example 31: An action is invoked when a utilities customer moves into a building, it returns the address. After a successful move-in it might return the null value accompanied by an instance annotation:

    -
    {
    -  "@Core.Messages": [{
    -    "code": "EADDRESS",
    -    "message": "Street name not yet determined",
    -    "severity": "error"
    -  }]
    -}
    -

    Note: the context URL is optional in requests.


    @@ -1353,17 +1334,17 @@

    functions or actions are advertised in the object representing a single entity.

    The nextLink control information MUST be included in a response that represents a partial result.

    -

    Example 32:

    -
    {
    -  "@context": "…",
    -  "@count": 37,
    -  "value": [
    -    {  },
    -    {  },
    -    {  }
    -  ],
    -  "@nextLink": "…?$skiptoken=342r89"
    -}
    +

    Example 31:

    +
    {
    +  "@context": "…",
    +  "@count": 37,
    +  "value": [
    +    {  },
    +    {  },
    +    {  }
    +  ],
    +  "@nextLink": "…?$skiptoken=342r89"
    +}

    @@ -1374,21 +1355,21 @@

    14

    A collection of entity references is represented as a collection of entities, with entity reference representations instead of entity representations as items in the array value of the value name/value pair.

    The outermost JSON object in a response MUST contain a context control information and MAY contain count, nextLink, or deltaLink control information.

    -

    Example 33: entity reference to order 10643

    -
    {
    -  "@context": "http://host/service/$metadata#$ref",
    -  "@id": "Orders(10643)"
    -}
    +

    Example 32: entity reference to order 10643

    +
    {
    +  "@context": "http://host/service/$metadata#$ref",
    +  "@id": "Orders(10643)"
    +}
    -

    Example 34: collection of entity references

    -
    {
    -  "@context": "http://host/service/$metadata#Collection($ref)",
    -  "value": [
    -    { "@id": "Orders(10643)" },
    -    { "@id": "Orders(10759)" }
    -  ]
    -}
    +

    Example 33: collection of entity references

    +
    {
    +  "@context": "http://host/service/$metadata#Collection($ref)",
    +  "value": [
    +    { "@id": "Orders(10643)" },
    +    { "@id": "Orders(10759)" }
    +  ]
    +}

    @@ -1406,60 +1387,60 @@

    15.1

    If the delta response contains a partial list of changes, it MUST include a next link for the client to retrieve the next set of changes.

    The last page of a delta response SHOULD contain a delta link in place of the next link for retrieving subsequent changes once the current set of changes has been applied to the initial set.

    -

    Example 35: a 4.01 delta response with three changes, in order of occurrence

    +

    Example 34: a 4.01 delta response with three changes, in order of occurrence

    1. ContactName for customer BOTTM was changed to Susan Halvenstern
    2. Customer ANTON was deleted
    3. ContactName for customer ALFKI was changed to Blake Smithe
    -
    {
    -  "@context": "http://host/service/$metadata#Customers/$delta",
    -  "@count":3,
    -  "value": [
    -    {
    -      "@id": "Customers('BOTTM')",
    -      "ContactName": "Susan Halvenstern"
    -    },
    -    {
    -      "@removed": {
    -        "reason": "deleted"
    -      },
    -      "@id": "Customers('ANTON')"
    -    },
    -    {
    -      "@id": "Customers('ALFKI')",
    -      "ContactName": "Blake Smithe"
    -    }
    -  ],
    -  "@deltaLink": "Customers?$deltatoken=8015"
    -}
    -
    -
    -

    Example 36: a 4.0 delta response with three changes, in order of occurrence

    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$delta",
    +  "@count":3,
    +  "value": [
    +    {
    +      "@id": "Customers('BOTTM')",
    +      "ContactName": "Susan Halvenstern"
    +    },
    +    {
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "@id": "Customers('ANTON')"
    +    },
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@deltaLink": "Customers?$deltatoken=8015"
    +}
    +
    +
    +

    Example 35: a 4.0 delta response with three changes, in order of occurrence

    1. ContactName for customer BOTTM was changed to Susan Halvenstern
    2. Customer ANTON was deleted
    3. ContactName for customer ALFKI was changed to Blake Smithe
    -
    {
    -  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    -  "@odata.count": 3,
    -  "value": [
    -    {
    -      "@odata.id": "Customers('BOTTM')",
    -      "ContactName": "Susan Halvenstern",
    -    },
    -    {
    -      "@odata.context": "#Customers/$deletedEntity",
    -      "@odata.id": "Customers('ANTON')"
    -    },
    -    {
    -      "@odata.id": "Customers('ALFKI')",
    -      "ContactName": "Blake Smithe"
    -    }
    -  ],
    -  "@odata.deltaLink": "Customers?$deltatoken=8015"
    -}
    +
    {
    +  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    +  "@odata.count": 3,
    +  "value": [
    +    {
    +      "@odata.id": "Customers('BOTTM')",
    +      "ContactName": "Susan Halvenstern",
    +    },
    +    {
    +      "@odata.context": "#Customers/$deletedEntity",
    +      "@odata.id": "Customers('ANTON')"
    +    },
    +    {
    +      "@odata.id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@odata.deltaLink": "Customers?$deltatoken=8015"
    +}
    @@ -1488,12 +1469,12 @@

    15.3 Del
  • reason — either deleted, if the entity was deleted (destroyed), or changed if the entity was removed from membership in the result (i.e., due to a data change).
  • -

    Example 37: deleted entity in OData 4.0 response — note that id is a property, not control information

    -
    {
    -  "@context": "#Customers/$deletedEntity",
    -  "reason": "deleted",
    -  "id": "Customers('ANTON')"
    -}
    +

    Example 36: deleted entity in OData 4.0 response — note that id is a property, not control information

    +
    {
    +  "@context": "#Customers/$deletedEntity",
    +  "reason": "deleted",
    +  "id": "Customers('ANTON')"
    +}

    In OData 4.01 payloads the deleted-entity object MUST include the following properties, regardless of the specified metadata value. For ordered payloads, this control information MUST follow the payload ordering constraints.

      @@ -1503,22 +1484,22 @@

      15.3 Del

      For full metadata the context control information MUST be included. It also MUST be included if the entity set of the deleted entity cannot be determined from the surrounding context.

      The deleted-entity object MAY include additional properties of the entity, as well as annotations, and MAY include related entities, related deleted entities, or a delta or full representation of a related collection of entities, to represent related entities that have been modified or deleted.

      -

      Example 38: deleted entity in OData 4.01 response with id control information (prefixed with an @)

      -
      {
      -  "@context": "#Customers/$deletedEntity",
      -  "@removed": {
      -    "reason": "deleted",
      -    "@myannoation.deletedBy": "Mario"
      -  },
      -  "@id": "Customers('ANTON')"
      -}
      +

      Example 37: deleted entity in OData 4.01 response with id control information (prefixed with an @)

      +
      {
      +  "@context": "#Customers/$deletedEntity",
      +  "@removed": {
      +    "reason": "deleted",
      +    "@myannoation.deletedBy": "Mario"
      +  },
      +  "@id": "Customers('ANTON')"
      +}
      -

      Example 39: entity removed OData 4.01 response without id control information and instead all key fields (ID is the single key field of Customer)

      -
      {
      -  "@removed": {},
      -  "ID": "ANTON"
      -}
      +

      Example 38: entity removed OData 4.01 response without id control information and instead all key fields (ID is the single key field of Customer)

      +
      {
      +  "@removed": {},
      +  "ID": "ANTON"
      +}

    @@ -1533,7 +1514,7 @@

    added/changed entity, an entity reference, a deleted entity, or a null value (if no entity is related as the outcome of the change). Collection-valued navigation properties are represented either as a delta representation or as a full representation of the collection.

    If the expanded navigation property represents a delta, it MUST be represented as an array-valued control information delta on the navigation property. Added/changed entities or entity references are added to the collection. Deleted entities in a nested delta representation represent entities no longer part of the collection. If the deleted entity specifies a reason as deleted, then the entity is both removed from the collection and deleted, otherwise it is removed from the collection and only deleted if the navigation property is a containment navigation property. The array MUST NOT contain added or deleted links.

    -

    Example 40: changes to related orders represented as a 4.01 nested delta representation

    +

    Example 39: changes to related orders represented as a 4.01 nested delta representation

    1. For Customer ALFKI:
        @@ -1544,57 +1525,57 @@

        {
        -  "@context": "http://host/service/$metadata#Customers/$delta",
        -  "@count":3,
        -  "value": [
        -    {
        -      "@id": "Customers('ALFKI')",
        -      "Orders@delta": [
        -        {
        -          "@removed": {
        -            "reason": "changed"
        -          },
        -          "@id": "Orders(10643)"
        -        },
        -        {
        -          "@id": "Orders(10645)",
        -          "ShippingAddress": {
        -            "Street": "23 Tsawassen Blvd.",
        -            "City": "Tsawassen",
        -            "Region": "BC",
        -            "PostalCode": "T2F 8M4"
        -          }
        -        }
        -      ]
        -    },
        -    {
        -      "@removed": {
        -        "reason": "deleted"
        -      },
        -      "@id": "Customers('ANTON')"
        -    },
        -    {
        -      "@id": "Customers('ALFKI')",
        -      "ContactName": "Blake Smithe"
        -    }
        -  ],
        -  "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
        -}

    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$delta",
    +  "@count":3,
    +  "value": [
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "Orders@delta": [
    +        {
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "@id": "Orders(10643)"
    +        },
    +        {
    +          "@id": "Orders(10645)",
    +          "ShippingAddress": {
    +            "Street": "23 Tsawassen Blvd.",
    +            "City": "Tsawassen",
    +            "Region": "BC",
    +            "PostalCode": "T2F 8M4"
    +          }
    +        }
    +      ]
    +    },
    +    {
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "@id": "Customers('ANTON')"
    +    },
    +    {
    +      "@id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@deltaLink": "Customers?$expand=Orders&$deltatoken=8015"
    +}

    If the expanded navigation property is a full representation of the collection, it MUST be represented as an expanded navigation property, and its array value MUST represent the full set of entities related according to that relationship and satisfying any specified expand options, or a partial list containing a nextLink. Following this chain of next links MUST eventually return the full set of entities related according to that relationship and satisfying any specified expand options; the final page does not include a delta link.

    Members of the expanded navigation property MUST be represented as added/changed entities or entity references and MUST NOT include added links, deleted links, or deleted entities. Any entity not represented in the collection has either been removed, deleted, or changed such that it no longer satisfies the expand options in the defining query. In any case, clients SHOULD NOT receive additional notifications for such removed entities.

    -

    Example 41: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)

    -
    {
    -  "@context": "http://host/service/$metadata#Customers/$entity/$delta",
    -  
    -  "Orders@count": 42,
    -  "Orders": [  ],
    -  "Orders@nextLink": "…",
    -  
    -  "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
    -}
    +

    Example 40: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a next link)

    +
    {
    +  "@context": "http://host/service/$metadata#Customers/$entity/$delta",
    +  
    +  "Orders@count": 42,
    +  "Orders": [  ],
    +  "Orders@nextLink": "…",
    +  
    +  "@deltaLink": "Customers('ALFKI')?$expand=Orders&$deltatoken=9711"
    +}

    @@ -1602,7 +1583,7 @@

    added or deleted links. Changes to related entities are represented as top-level entities whose context control information specifies the entity set of the entity. This control information MUST be present for entities are not part of the entity set specified by the context URL, regardless of the specified metadata value.

    -

    Example 42: changes to related orders represented as a 4.0 flattened delta payload

    +

    Example 41: changes to related orders represented as a 4.0 flattened delta payload

    1. Order 10643 was removed from customer ALFKI
    2. Order 10645 was added to customer ALFKI
    3. @@ -1610,43 +1591,43 @@

      {
      -  "@odata.context": "http://host/service/$metadata#Customers/$delta",
      -  "@odata.count": 5,
      -  "value": [
      -    {
      -      "@odata.context": "#Customers/$deletedLink",
      -      "source": "Customers('ALFKI')",
      -      "relationship": "Orders",
      -      "target": "Orders(10643)"
      -    },
      -    {
      -      "@odata.context": "#Customers/$link",
      -      "source": "Customers('BOTTM')",
      -      "relationship": "Orders",
      -      "target": "Orders(10645)"
      -    },
      -    {
      -      "@odata.context": "#Orders/$entity",
      -      "@odata.id": "Orders(10645)",
      -      "ShippingAddress": {
      -        "Street": "23 Tsawassen Blvd.",
      -        "City": "Tsawassen",
      -        "Region": "BC",
      -        "PostalCode": "T2F 8M4"
      -      }
      -    },
      -    {
      -      "@odata.context": "#Customers/$deletedEntity",
      -      "@odata.id": "Customers('ANTON')"
      -    },
      -    {
      -      "@odata.id": "Customers('ALFKI')",
      -      "ContactName": "Blake Smithe"
      -    }
      -  ],
      -  "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
      -}

    +
    {
    +  "@odata.context": "http://host/service/$metadata#Customers/$delta",
    +  "@odata.count": 5,
    +  "value": [
    +    {
    +      "@odata.context": "#Customers/$deletedLink",
    +      "source": "Customers('ALFKI')",
    +      "relationship": "Orders",
    +      "target": "Orders(10643)"
    +    },
    +    {
    +      "@odata.context": "#Customers/$link",
    +      "source": "Customers('BOTTM')",
    +      "relationship": "Orders",
    +      "target": "Orders(10645)"
    +    },
    +    {
    +      "@odata.context": "#Orders/$entity",
    +      "@odata.id": "Orders(10645)",
    +      "ShippingAddress": {
    +        "Street": "23 Tsawassen Blvd.",
    +        "City": "Tsawassen",
    +        "Region": "BC",
    +        "PostalCode": "T2F 8M4"
    +      }
    +    },
    +    {
    +      "@odata.context": "#Customers/$deletedEntity",
    +      "@odata.id": "Customers('ANTON')"
    +    },
    +    {
    +      "@odata.id": "Customers('ALFKI')",
    +      "ContactName": "Blake Smithe"
    +    }
    +  ],
    +  "@odata.deltaLink": "Customers?$expand=Orders&$deltatoken=8016"
    +}

    If a property of an entity is dependent upon the property of another entity within the expanded set of entities being tracked, then both the change to the dependent property as well as the change to the principal property or added/deleted link corresponding to the change to the dependent property are returned in the delta response.

    @@ -1686,7 +1667,7 @@

    The body of a PATCH request to a URL identifying a collection of entities is a JSON object. It MUST contain the context control information with a string value of #$delta, and it MUST contain an array-valued property named value containing all added, changed, or deleted entities. OData 4.0 delta payloads MAY additionally include added or deleted links between entities.

    -

    Example 43: 4.01 collection-update request for customers with expanded orders represented inline as a delta

    +

    Example 42: 4.01 collection-update request for customers with expanded orders represented inline as a delta

    1. Add customer EASTC
    2. Change ContactName of customer AROUT
    3. @@ -1701,90 +1682,90 @@

      Add order 10643 to customer ANATR
    4. Remove order 10311 from customer DUMON
    -
    PATCH /service/Customers HTTP/1.1
    -Host: host
    -Content-Type: application/json
    -Content-Length: ###
    -Prefer: return=minimal, continue-on-error
    -
    -{
    -  "@context": "#$delta",
    -  "value": [
    -    {
    -      "@Org.OData.Core.V1.ContentID": "1",
    -      "CustomerID": "EASTC",
    -      "CompanyName": "Eastern Connection",
    -      "ContactName": "Ann Devon",
    -      "ContactTitle": "Sales Agent"
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "2",
    -      "CustomerID": "AROUT",
    -      "ContactName": "Thomas Hardy",
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "3",
    -      "@removed": {
    -        "reason": "deleted"
    -      },
    -      "CustomerID": "ANTON"
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "4",
    -      "CustomerID": "ALFKI",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.1",
    -          "OrderID": 11011,
    -          "CustomerID": "ALFKI",
    -          "EmployeeID": 3,
    -          "OrderDate": "1998-04-09T00:00:00Z",
    -          "RequiredDate": "1998-05-07T00:00:00Z",
    -          "ShippedDate": "1998-04-13T00:00:00Z"
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.2",
    -          "@id": "Orders(10692)"
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.3",
    -          "@id": "Orders(10835)",
    -          "RequiredDate": "1998-01-23T00:00:00Z",
    -        },
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.4",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10643
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "5",
    -      "CustomerID": "ANATR",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "5.1",
    -          "OrderID": 10643
    -        }
    -      ],
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "6",
    -      "CustomerID": "DUMON",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "6.1",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10311
    -        }
    -      ]
    -    }
    -  ]
    -}
    +
    PATCH /service/Customers HTTP/1.1
    +Host: host
    +Content-Type: application/json
    +Content-Length: ###
    +Prefer: return=minimal, continue-on-error
    +
    +{
    +  "@context": "#$delta",
    +  "value": [
    +    {
    +      "@Org.OData.Core.V1.ContentID": "1",
    +      "CustomerID": "EASTC",
    +      "CompanyName": "Eastern Connection",
    +      "ContactName": "Ann Devon",
    +      "ContactTitle": "Sales Agent"
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "2",
    +      "CustomerID": "AROUT",
    +      "ContactName": "Thomas Hardy",
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "3",
    +      "@removed": {
    +        "reason": "deleted"
    +      },
    +      "CustomerID": "ANTON"
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "4",
    +      "CustomerID": "ALFKI",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.1",
    +          "OrderID": 11011,
    +          "CustomerID": "ALFKI",
    +          "EmployeeID": 3,
    +          "OrderDate": "1998-04-09T00:00:00Z",
    +          "RequiredDate": "1998-05-07T00:00:00Z",
    +          "ShippedDate": "1998-04-13T00:00:00Z"
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.2",
    +          "@id": "Orders(10692)"
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.3",
    +          "@id": "Orders(10835)",
    +          "RequiredDate": "1998-01-23T00:00:00Z",
    +        },
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.4",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10643
    +        }
    +      ]
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "5",
    +      "CustomerID": "ANATR",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "5.1",
    +          "OrderID": 10643
    +        }
    +      ],
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "6",
    +      "CustomerID": "DUMON",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "6.1",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10311
    +        }
    +      ]
    +    }
    +  ]
    +}

    Assuming all changes can be applied without errors, the response would be

    HTTP/1.1 204 No Content
     Preference-Applied: return=minimal, continue-on-error
    @@ -1805,124 +1786,124 @@ 

    Add order 10643 to customer ‘ANATR’ - failed without further info
  • Remove order 10311 from customer ‘DUMON’ - failed without further info
  • -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 200 OK
    +Content-Type: application/json
    +Content-Length: ###
    +Preference-Applied: return=minimal, continue-on-error
    +
    +{
    +  "@context": "#$delta",
    +  "value": [
    +    {
    +      "@Org.OData.Core.V1.ContentID": "1",
    +      "CustomerID": "EASTC",
    +      "@removed": {
    +        "reason": "changed"
    +      },
    +      "@Org.OData.Core.V1.DataModificationException": {
    +        "failedOperation": "insert",
    +        "responseCode": 400,
    +        "info": {
    +          "code": "incmplt",
    +          "message": "Required field(s) not provided",
    +          "target": "Address",
    +          "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
    +          "severity": "error"
    +        }
    +      }
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "2",
    +      "CustomerID": "AROUT",
    +      "@Org.OData.Core.V1.DataModificationException": {
    +        "failedOperation": "update",
    +        "responseCode": 400,
    +        "info": {
    +          "code": "r-o",
    +          "message": "Customer is archived and cannot be changed",
    +          "severity": "error"
    +        }
    +      }
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "3",
    +      "CustomerID": "ANTON",
    +      "@Org.OData.Core.V1.DataModificationException": {
    +        "failedOperation": "delete",
    +        "responseCode": 400,
    +        "info": {
    +          "code": "ufo",
    +          "message": "Customer has unfinished orders and cannot be deleted",
    +          "severity": "error"
    +        }
    +      }
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "4",
    +      "CustomerID": "ALFKI",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "4.3",
    +          "@id": "Orders(10835)",
    +          "@Org.OData.Core.V1.DataModificationException": {
    +            "failedOperation": "update",
    +            "responseCode": 400,
    +            "info": {
    +              "code": "b/s",
    +              "message": "RequiredDate cannot be changed because Order is already being shipped",
    +              "severity": "error"
    +            }
    +          }
    +        }
    +      ]
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "5",
    +      "CustomerID": "ANATR",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "5.1",
    +          "@removed": {
    +            "reason": "changed"
    +          },
    +          "OrderID": 10643,
    +          "@Org.OData.Core.V1.DataModificationException": {
    +            "failedOperation": "link",
    +            "responseCode": 404,
    +            "info": null
    +          }
    +        }
    +      ]
    +    },
    +    {
    +      "@Org.OData.Core.V1.ContentID": "6",
    +      "CustomerID": "DUMON",
    +      "Orders@delta": [
    +        {
    +          "@Org.OData.Core.V1.ContentID": "6.1",
    +          "OrderID": 10311,
    +          "@Org.OData.Core.V1.DataModificationException": {
    +            "failedOperation": "unlink",
    +            "responseCode": 404
    +          }
    +        }
    +      ]
    +    }
    +  ]
    +}
    +

    Without the continue-on-error preference processing would stop on the first error, and the response would be a standard OData error response

    +
    HTTP/1.1 400 Bad Request
     Content-Type: application/json
     Content-Length: ###
    -Preference-Applied: return=minimal, continue-on-error
    -
    -{
    -  "@context": "#$delta",
    -  "value": [
    -    {
    -      "@Org.OData.Core.V1.ContentID": "1",
    -      "CustomerID": "EASTC",
    -      "@removed": {
    -        "reason": "changed"
    -      },
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "insert",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "incmplt",
    -          "message": "Required field(s) not provided",
    -          "target": "Address",
    -          "@OtherVocab.additionalTargets": [ "Industry", "VATRegistration" ],
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "2",
    -      "CustomerID": "AROUT",
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "update",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "r-o",
    -          "message": "Customer is archived and cannot be changed",
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "3",
    -      "CustomerID": "ANTON",
    -      "@Org.OData.Core.V1.DataModificationException": {
    -        "failedOperation": "delete",
    -        "responseCode": 400,
    -        "info": {
    -          "code": "ufo",
    -          "message": "Customer has unfinished orders and cannot be deleted",
    -          "severity": "error"
    -        }
    -      }
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "4",
    -      "CustomerID": "ALFKI",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "4.3",
    -          "@id": "Orders(10835)",
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "update",
    -            "responseCode": 400,
    -            "info": {
    -              "code": "b/s",
    -              "message": "RequiredDate cannot be changed because Order is already being shipped",
    -              "severity": "error"
    -            }
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "5",
    -      "CustomerID": "ANATR",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "5.1",
    -          "@removed": {
    -            "reason": "changed"
    -          },
    -          "OrderID": 10643,
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "link",
    -            "responseCode": 404,
    -            "info": null
    -          }
    -        }
    -      ]
    -    },
    -    {
    -      "@Org.OData.Core.V1.ContentID": "6",
    -      "CustomerID": "DUMON",
    -      "Orders@delta": [
    -        {
    -          "@Org.OData.Core.V1.ContentID": "6.1",
    -          "OrderID": 10311,
    -          "@Org.OData.Core.V1.DataModificationException": {
    -            "failedOperation": "unlink",
    -            "responseCode": 404
    -          }
    -        }
    -      ]
    -    }
    -  ]
    -}
    -

    Without the continue-on-error preference processing would stop on the first error, and the response would be a standard OData error response

    -
    HTTP/1.1 400 Bad Request
    -Content-Type: application/json
    -Content-Length: ###
    -
    -{
    -  "error": {
    -    "code": "incmplt",
    -    "message": "Required field(s) not provided",
    -    "target": "Customers('EASTC')/Address",
    -    "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ]
    -  }
    -}
    + +{ + "error": { + "code": "incmplt", + "message": "Required field(s) not provided", + "target": "Customers('EASTC')/Address", + "@OtherVocab.additionalTargets": [ "Customers('EASTC')/Industry", "Customers('EASTC')/VATRegistration" ] + } +}

    @@ -1939,47 +1920,47 @@

    16 Bound

    The title name/value pair contains the function or action title as a string.

    If metadata=minimal is requested, the target name/value pair MUST be included if its value differs from the canonical function or action URL.

    -

    Example 44: minimal representation of a function where all overloads are applicable

    +

    Example 43: minimal representation of a function where all overloads are applicable

    +
    {
    +  "@context": "http://host/service/$metadata#Employees/$entity",
    +  "#Model.RemainingVacation": {},
    +  
    +}
    +
    +
    +

    Example 44: full representation of a specific overload with parameter alias for the Year parameter

    {
       "@context": "http://host/service/$metadata#Employees/$entity",
    -  "#Model.RemainingVacation": {},
    -  
    -}
    + "#Model.RemainingVacation(Year)": { + "title": "Remaining vacation from year.", + "target": "Employees(2)/RemainingVacation(Year=@Year)" + }, + +}
    -

    Example 45: full representation of a specific overload with parameter alias for the Year parameter

    +

    Example 45: full representation in a collection

    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "#Model.RemainingVacation(Year)": {
    -    "title": "Remaining vacation from year.",
    -    "target": "Employees(2)/RemainingVacation(Year=@Year)"
    +  "@context": "http://host/service/$metadata#Employees",
    +  "#Model.RemainingVacation": {
    +    "title": "Remaining Vacation",
    +    "target": "Managers(22)/Employees/RemainingVacation"
       },
    -  
    +  "value": [  ]
     }
    -

    Example 46: full representation in a collection

    +

    Example 46: full representation in a nested collection

    {
    -  "@context": "http://host/service/$metadata#Employees",
    -  "#Model.RemainingVacation": {
    -    "title": "Remaining Vacation",
    -    "target": "Managers(22)/Employees/RemainingVacation"
    -  },
    -  "value": [  ]
    -}
    -
    -
    -

    Example 47: full representation in a nested collection

    -
    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "@type": "Model.Manager",
    -  "ID":22,
    -  
    -  "Employees#RemainingVacation": {
    -    "title": "RemainingVacation",
    -    "target": "Managers(22)/Employees/RemainingVacation"
    -  }
    -}
    + "@context": "http://host/service/$metadata#Employees/$entity", + "@type": "Model.Manager", + "ID":22, + + "Employees#RemainingVacation": { + "title": "RemainingVacation", + "target": "Managers(22)/Employees/RemainingVacation" + } +}

    @@ -1995,47 +1976,47 @@

    17 Bound Action

    The title name/value pair contains the function or action title as a string.

    If metadata=minimal is requested, the target name/value pair MUST be included if its value differs from the canonical function or action URL.

    -

    Example 48: minimal representation in an entity

    +

    Example 47: minimal representation in an entity

    +
    {
    +  "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    +  "#Model.Approve": {},
    +  
    +}
    +
    +
    +

    Example 48: full representation in an entity:

    {
       "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    -  "#Model.Approve": {},
    -  
    -}
    + "#Model.Approve": { + "title": "Approve Leave Request", + "target": "LeaveRequests(2)/Approve" + }, + +}
    -

    Example 49: full representation in an entity:

    +

    Example 49: full representation in a collection

    {
    -  "@context": "http://host/service/$metadata#LeaveRequests/$entity",
    +  "@context": "http://host/service/$metadata#LeaveRequests",
       "#Model.Approve": {
    -    "title": "Approve Leave Request",
    -    "target": "LeaveRequests(2)/Approve"
    +    "title": "Approve All Leave Requests",
    +    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
       },
    -  
    +  "value": [  ]
     }
    -

    Example 50: full representation in a collection

    +

    Example 50: full representation in a nested collection

    {
    -  "@context": "http://host/service/$metadata#LeaveRequests",
    -  "#Model.Approve": {
    -    "title": "Approve All Leave Requests",
    -    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    -  },
    -  "value": [  ]
    -}
    -
    -
    -

    Example 51: full representation in a nested collection

    -
    {
    -  "@context": "http://host/service/$metadata#Employees/$entity",
    -  "@type": "Model.Manager",
    -  "ID": 22,
    -  
    -  "LeaveRequests#Model.Approve": {
    -    "title": "Approve All Leave Requests",
    -    "target": "Employees(22)/Model.Manager/LeaveRequests/Approve"
    -  }
    -}
    + "@context": "http://host/service/$metadata#Employees/$entity", + "@type": "Model.Manager", + "ID": 22, + + "LeaveRequests#Model.Approve": { + "title": "Approve All Leave Requests", + "target": "Employees(22)/Model.Manager/LeaveRequests/Approve" + } +}

    @@ -2046,79 +2027,79 @@

    Each non-binding parameter value is encoded as a separate name/value pair in this JSON object. The name is the name of the parameter. The value is the parameter value in the JSON representation appropriate for its type. Entity typed parameter values MAY include a subset of the properties, or just the entity reference, as appropriate to the action. Stream typed parameter values are represented following the same rules as inlined stream properties.

    Entities as parameter values are represented as explained in section 6.

    -

    Example 52: Create a quote for a product that does not yet exist. The Product parameter takes a transient entity.

    +

    Example 51: Create a quote for a product that does not yet exist. The Product parameter takes a transient entity.

    +
    POST http://host/service/CreateQuote
    +Content-Type: application/json
    +
    +{
    +  "Product": {
    +    "Name": "Our best ever",
    +    "Price": 1
    +  },
    +  "CustomerID": "ALFKI"
    +}
    +
    +
    +

    Example 52: Create a quote for an existing product. The Product parameter takes a non-transient entity which can be identified through its entity-id:

    POST http://host/service/CreateQuote
     Content-Type: application/json
     
     {
       "Product": {
    -    "Name": "Our best ever",
    -    "Price": 1
    -  },
    -  "CustomerID": "ALFKI"
    -}
    -
    -
    -

    Example 53: Create a quote for an existing product. The Product parameter takes a non-transient entity which can be identified through its entity-id:

    + "@id": "Products(14)" + }, + "CustomerID": "ALFKI" +}
    +

    or, as in section 15.2, through its primary key fields plus, if necessary, its context:

    POST http://host/service/CreateQuote
     Content-Type: application/json
     
     {
       "Product": {
    -    "@id": "Products(14)"
    -  },
    -  "CustomerID": "ALFKI"
    -}
    -

    or, as in section 15.2, through its primary key fields plus, if necessary, its context:

    -
    POST http://host/service/CreateQuote
    -Content-Type: application/json
    -
    -{
    -  "Product": {
    -    "@context": "#Products",
    -    "ProductID": 14
    -  },
    -  "CustomerID": "ALFKI"
    -}
    + "@context": "#Products", + "ProductID": 14 + }, + "CustomerID": "ALFKI" +}

    Alternatively, values of non-binding parameters MAY be specified as common expressions OData-URL, section 5.1.1. In the case of a bound action these MAY contain path expressions OData-URL, section 5.1.1.15, which the service evaluates on the binding parameter value. Such parameters are encoded as name/value pairs where the name is the name of the parameter followed by @expression and the value is the common expression. As the following example demonstrates, non-transient entities can be passed as non-binding action parameters through a resource path in this way.

    -

    Example 54: An employee requests leave from their manager for the next two weeks:

    -
    POST /service/Employees(23)/self.RequestLeave
    +

    Example 53: An employee requests leave from their manager for the next two weeks:

    +
    POST /service/Employees(23)/self.RequestLeave
    +Host: host
    +Content-Type: application/json
    +
    +{
    +  "StartDate@expression": "now()",
    +  "EndDate@expression": "now() add duration'P14D'",
    +  "Approver@expression": "Manager"
    +}
    +

    The expression Manager is evaluated on the binding parameter value Employees(23).

    +

    When invoking an unbound action through an action import, expressions involving paths must start with $root:

    +
    POST /service/RequestLeave
     Host: host
     Content-Type: application/json
     
     {
    -  "StartDate@expression": "now()",
    -  "EndDate@expression": "now() add duration'P14D'",
    -  "Approver@expression": "Manager"
    -}
    -

    The expression Manager is evaluated on the binding parameter value Employees(23).

    -

    When invoking an unbound action through an action import, expressions involving paths must start with $root:

    -
    POST /service/RequestLeave
    -Host: host
    -Content-Type: application/json
    -
    -{
    -  "Requester@expression": "$root/services/Employee(23)",
    -  "StartDate@expression": "now()",
    -  "EndDate@expression": "now() add duration'P14D'",
    -  "Approver@expression": "$root/services/Employee(23)/Manager"
    -}
    + "Requester@expression": "$root/services/Employee(23)", + "StartDate@expression": "now()", + "EndDate@expression": "now() add duration'P14D'", + "Approver@expression": "$root/services/Employee(23)/Manager" +}

    Inside a batch request the common expressions can also be value references starting with $, as introduced in OData-Protocol, section 11.7.6.

    Non-binding parameters that are nullable or annotated with the term Core.OptionalParameter defined in OData-VocCore MAY be omitted from the request body. If an omitted parameter is not annotated (and thus nullable), it MUST be interpreted as having the null value. 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. Note: a nullable non-binding parameter is equivalent to being annotated as optional with a default value of null.

    -

    Example 55:

    -
    {
    -  "param1": 42,
    -  "param2": {
    -    "Street": "One Microsoft Way",
    -    "Zip": 98052
    -  },
    -  "param3": [ 1, 42, 99 ],
    -  "param4": null
    -}
    +

    Example 54:

    +
    {
    +  "param1": 42,
    +  "param2": {
    +    "Street": "One Microsoft Way",
    +    "Zip": 98052
    +  },
    +  "param3": [ 1, 42, 99 ],
    +  "param4": null
    +}

    In order to invoke an action with no non-binding parameters, the client passes an empty JSON object in the body of the request. 4.01 Services MUST also support clients passing an empty request body for this case.

    @@ -2156,7 +2137,7 @@

    19.1 Batch

    A body MUST NOT be specified if the method is get or delete.

    The request object and the headers object MUST NOT contain name/value pairs with duplicate names. This is in conformance with RFC7493.

    -

    Example 56: a batch request that contains the following individual requests in the order listed

    +

    Example 55: a batch request that contains the following individual requests in the order listed

    1. A query request
    2. An atomicity group that contains the following requests: @@ -2167,6 +2148,57 @@

      19.1 Batch
    3. A second query request

    Note: For brevity, in the example, request bodies are excluded in favor of English descriptions inside <> brackets and OData-Version headers are omitted.

    +
    POST /service/$batch HTTP/1.1
    +Host: host
    +OData-Version: 4.01
    +Content-Type: application/json
    +Content-Length: ###
    +
    +{
    +  "requests": [
    +    {
    +      "id": "0",
    +      "method": "get",
    +      "url": "/service/Customers('ALFKI')"
    +    },
    +    {
    +      "id": "1",
    +      "atomicityGroup": "group1",
    +      "dependsOn": [ "0" ],
    +      "method": "patch",
    +      "url": "/service/Customers('ALFKI')",
    +      "headers": {
    +        "Prefer": "return=minimal"
    +      },
    +      "body": <JSON representation of changes to Customer ALFKI>
    +    },
    +    {
    +      "id": "2",
    +      "atomicityGroup": "group1",
    +      "method": "post",
    +      "url": "/service/Customers",
    +      "body": <JSON representation of a new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "dependsOn": [ "group1" ],
    +      "method": "get",
    +      "url": "/service/Products"
    +    }
    +  ]
    +}
    +
    + +
    +

    19.2 Referencing New Entities

    +
    +

    The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.

    +
    +

    Example 56: a batch request that contains the following operations in the order listed:

    +
      +
    • Insert a new entity (with id = 1)
    • +
    • Insert a second new entity (references request with id = 1)
    • +
    POST /service/$batch HTTP/1.1
     Host: host
     OData-Version: 4.01
    @@ -2176,47 +2208,30 @@ 

    19.1 Batch { "requests": [ { - "id": "0", - "method": "get", - "url": "/service/Customers('ALFKI')" - }, - { - "id": "1", - "atomicityGroup": "group1", - "dependsOn": [ "0" ], - "method": "patch", - "url": "/service/Customers('ALFKI')", - "headers": { - "Prefer": "return=minimal" - }, - "body": <JSON representation of changes to Customer ALFKI> - }, - { - "id": "2", - "atomicityGroup": "group1", - "method": "post", - "url": "/service/Customers", - "body": <JSON representation of a new Customer entity> - }, - { - "id": "3", - "dependsOn": [ "group1" ], - "method": "get", - "url": "/service/Products" - } - ] -}

    + "id": "1", + "method": "post", + "url": "/service/Customers", + "body": <JSON representation of a new Customer entity> + }, + { + "id": "2", + "dependsOn": [ "1" ] + "method": "post", + "url": "$1/Orders", + "body": <JSON representation of a new Order> + } + ] +}
    -

    19.2 Referencing New Entities

    +

    19.3 Referencing an ETag

    -

    The entity returned by a preceding request can be referenced in the request URL of subsequent requests. If the Location header in the response contains a relative URL, clients MUST be able to resolve it relative to the request’s URL even if that contains such a reference.

    Example 57: a batch request that contains the following operations in the order listed:

      -
    • Insert a new entity (with id = 1)
    • -
    • Insert a second new entity (references request with id = 1)
    • +
    • Get an Employee (with id = 1)
    • +
    • Update the salary only if the employee has not changed
    POST /service/$batch HTTP/1.1
     Host: host
    @@ -2228,29 +2243,36 @@ 

    "requests": [ { "id": "1", - "method": "post", - "url": "/service/Customers", - "body": <JSON representation of a new Customer entity> - }, - { - "id": "2", - "dependsOn": [ "1" ] - "method": "post", - "url": "$1/Orders", - "body": <JSON representation of a new Order> - } - ] -}

    + "method": "get", + "url": "/service/Employees(0)", + "headers": { + "accept": "application/json" + } + }, + { + "id": "2", + "dependsOn": [ "1" ], + "method": "patch", + "url": "/service/Employees(0)", + "headers": { + "if-match": "$1" + }, + "body": { + "Salary": 75000 + } + } + ] +}
    -

    19.3 Referencing an ETag

    +

    19.4 Referencing Response Body Values

    Example 58: a batch request that contains the following operations in the order listed:

      -
    • Get an Employee (with id = 1)
    • -
    • Update the salary only if the employee has not changed
    • +
    • Get an employee (with Content-ID = 1)
    • +
    • Get all employees residing in the same building
    POST /service/$batch HTTP/1.1
     Host: host
    @@ -2263,7 +2285,7 @@ 

    { "id": "1", "method": "get", - "url": "/service/Employees(0)", + "url": "/service/Employees/0?$select=Building", "headers": { "accept": "application/json" } @@ -2271,55 +2293,14 @@

    { "id": "2", "dependsOn": [ "1" ], - "method": "patch", - "url": "/service/Employees(0)", + "method": "get", + "url": "/service/Employees?$filter=Building eq $1/Building", "headers": { - "if-match": "$1" - }, - "body": { - "Salary": 75000 - } - } - ] -}

    -
    -
    -
    -

    19.4 Referencing Response Body Values

    -
    -
    -

    Example 59: 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
    • -
    -
    POST /service/$batch HTTP/1.1
    -Host: host
    -OData-Version: 4.01
    -Content-Type: application/json
    -Content-Length: ###
    -
    -{
    -  "requests": [
    -    {
    -      "id": "1",
    -      "method": "get",
    -      "url": "/service/Employees/0?$select=Building",
    -      "headers": {
    -        "accept": "application/json"
    -      }
    -    },
    -    {
    -      "id": "2",
    -      "dependsOn": [ "1" ],
    -      "method": "get",
    -      "url": "/service/Employees?$filter=Building eq $1/Building",
    -      "headers": {
    -        "accept": "application/json"
    -      }
    -    }
    -  ]
    -}
    + "accept": "application/json" + } + } + ] +}
    @@ -2344,38 +2325,38 @@

    19.6 Bat

    If the media type is not exactly equal to application/json (i.e. it is a subtype or has format parameters), the headers object MUST contain a name/value pair with the name content-type whose value is the media type.

    Relative URLs in a response object follow the rules for relative URLs based on the request URL of the corresponding request. Especially: URLs in responses MUST NOT contain $-prefixed request identifiers.

    -

    Example 60: referencing the batch request example 56 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.01
    -Content-Length: ####
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 200,
    -      "body": <JSON representation of the Customer entity with key ALFKI>
    -    },
    -    {
    -      "id": "1",
    -      "status": 204
    -    },
    -    {
    -      "id": "2",
    -      "status": 201,
    -      "headers": {
    -        "location": "http://host/service.svc/Customer('POIUY')"
    -      },
    -      "body": <JSON representation of the new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "status": 404,
    -      "body": <Error message>
    -    }
    -  ]
    -}
    +

    Example 59: referencing the batch request example 55 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.01
    +Content-Length: ####
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 200,
    +      "body": <JSON representation of the Customer entity with key ALFKI>
    +    },
    +    {
    +      "id": "1",
    +      "status": 204
    +    },
    +    {
    +      "id": "2",
    +      "status": 201,
    +      "headers": {
    +        "location": "http://host/service.svc/Customer('POIUY')"
    +      },
    +      "body": <JSON representation of the new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "status": 404,
    +      "body": <Error message>
    +    }
    +  ]
    +}

    @@ -2384,83 +2365,83 @@

    A batch request that specifies the respond-async preference MAY be executed asynchronously. This means that the “outer” batch request is executed asynchronously; this preference does not automatically cascade down to the individual requests within the batch. After successful execution of the batch request the response to the batch request is returned in the body of a response to an interrogation request against the status monitor resource URL, see OData-Protocol, section 11.6.

    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 nextLink control information in the JSON batch response, thus signaling that the response is only a partial result. A subsequent GET request to the next link MAY result in a 202 Accepted response with a location header pointing to a new status monitor resource.

    -

    Example 61: referencing the example 56 above again, assume that the request is sent with the respond-async preference. This results in a 202 response pointing to a status monitor resource:

    -
    HTTP/1.1 202 Accepted
    -Location: http://service-root/async-monitor-0
    -Retry-After: ###
    +

    Example 60: referencing the example 55 above again, assume that the request is sent with the respond-async preference. This results in a 202 response pointing to a status monitor resource:

    +
    HTTP/1.1 202 Accepted
    +Location: http://service-root/async-monitor-0
    +Retry-After: ###

    When interrogating the monitor URL only the first request in the batch has finished processing and all the remaining requests are still being processed. The service signals that asynchronous processing is “finished” and returns a partial result with the first response and a next link. The client did not explicitly accept application/http, so the response is “unwrapped” and only indicates with the AsyncResult header that it is a response to a status monitor resource:

    -
    HTTP/1.1 200 OK
    -AsyncResult: 200
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 200,
    -      "body": <JSON representation of the Customer entity with key ALFKI>
    -    }
    -  ],
    -  "@nextLink": "…?$skiptoken=YmF0Y2gx"
    -}
    +
    HTTP/1.1 200 OK
    +AsyncResult: 200
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 200,
    +      "body": <JSON representation of the Customer entity with key ALFKI>
    +    }
    +  ],
    +  "@nextLink": "…?$skiptoken=YmF0Y2gx"
    +}

    Client makes a GET request to the next link and receives a 202 response with the location of a new monitor resource.

    -
    HTTP/1.1 202 Accepted
    -Location: http://service-root/async-monitor-1
    -Retry-After: ###
    +
    HTTP/1.1 202 Accepted
    +Location: http://service-root/async-monitor-1
    +Retry-After: ###

    After some time a GET request to the monitor resource returns the remainder of the result.

    -
    HTTP/1.1 200 OK
    -AsyncResult: 200
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "1",
    -      "status": 204
    -    },
    -    {
    -      "id": "2",
    -      "status": 201,
    -      "headers": {
    -        "location": "http://host/service.svc/Customer('POIUY')"
    -      },
    -      "body": <JSON representation of the new Customer entity>
    -    },
    -    {
    -      "id": "3",
    -      "status": 404,
    -      "body": <Error message>
    -    }
    -  ]
    -}
    +
    HTTP/1.1 200 OK
    +AsyncResult: 200
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "1",
    +      "status": 204
    +    },
    +    {
    +      "id": "2",
    +      "status": 201,
    +      "headers": {
    +        "location": "http://host/service.svc/Customer('POIUY')"
    +      },
    +      "body": <JSON representation of the new Customer entity>
    +    },
    +    {
    +      "id": "3",
    +      "status": 404,
    +      "body": <Error message>
    +    }
    +  ]
    +}

    In addition to the above interaction pattern individual requests within a batch with no other requests depending on it and not part of an atomicity group MAY be executed asynchronously if they specify the respond-async preference and if the service responds with a JSON batch response. In this case the response array contains a response object for each asynchronously executed individual request with a status of 202, a location header pointing to an individual status monitor resource, and optionally a retry-after header.

    -

    Example 62: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously

    -
    HTTP/1.1 200 OK
    -OData-Version: 4.01
    -Content-Length: ###
    -Content-Type: application/json
    -
    -{
    -  "responses": [
    -    {
    -      "id": "0",
    -      "status": 202,
    -      "headers": {
    -        "location": "http://service-root/async-monitor-0"
    -      }
    -    },
    -    {
    -      "id": "1",
    -      "status": 204
    -    }
    -  ]
    -}
    +

    Example 61: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously

    +
    HTTP/1.1 200 OK
    +OData-Version: 4.01
    +Content-Length: ###
    +Content-Type: application/json
    +
    +{
    +  "responses": [
    +    {
    +      "id": "0",
    +      "status": 202,
    +      "headers": {
    +        "location": "http://service-root/async-monitor-0"
    +      }
    +    },
    +    {
    +      "id": "1",
    +      "status": 204
    +    }
    +  ]
    +}

    @@ -2474,20 +2455,20 @@

    single primitive or collection value, the annotations for the value appear next to the value property and are not prefixed with a property name.

    -

    Example 63:

    -
    {
    -  "@context": "http://host/service/$metadata#Customers",
    -  "@com.example.customer.setkind": "VIPs",
    -  "value": [
    -    {
    -      "@com.example.display.highlight": true,
    -      "ID": "ALFKI",
    -      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
    -      "CompanyName": "Alfreds Futterkiste",
    -      "Orders@com.example.display.style#simple": { "order": 2 }
    -    }
    -  ]
    -}
    +

    Example 62:

    +
    {
    +  "@context": "http://host/service/$metadata#Customers",
    +  "@com.example.customer.setkind": "VIPs",
    +  "value": [
    +    {
    +      "@com.example.display.highlight": true,
    +      "ID": "ALFKI",
    +      "CompanyName@com.example.display.style": { "title": true, "order": 1 },
    +      "CompanyName": "Alfreds Futterkiste",
    +      "Orders@com.example.display.style#simple": { "order": 2 }
    +    }
    +  ]
    +}

    20.1 Annotate a JSON Object

    @@ -2528,25 +2509,25 @@

    21.1 Err

    Service implementations SHOULD carefully consider which information to include in production environments to guard against potential security concerns around information disclosure.

    Error responses MAY contain annotations in any of its JSON objects.

    -

    Example 64:

    -
    {
    -  "error": {
    -    "code": "err123",
    -    "message": "Unsupported functionality",
    -    "target": "query",
    -    "details": [
    -      {
    -      "code": "forty-two",
    -      "target": "$search",
    -      "message": "$search query option not supported"
    -      }
    -    ],
    -    "innererror": {
    -      "trace": [],
    -      "context": {}
    -    }
    -  }
    -}
    +

    Example 63:

    +
    {
    +  "error": {
    +    "code": "err123",
    +    "message": "Unsupported functionality",
    +    "target": "query",
    +    "details": [
    +      {
    +      "code": "forty-two",
    +      "target": "$search",
    +      "message": "$search query option not supported"
    +      }
    +    ],
    +    "innererror": {
    +      "trace": [],
    +      "context": {}
    +    }
    +  }
    +}

    @@ -2560,10 +2541,10 @@

    21.2 In
  • Control characters (00 to 1F and 7F) and Unicode characters beyond 00FF within JSON strings are encoded as \uXXXX or \uXXXX\uXXXX (see RFC8259, section 7)

  • -

    Example 65: note that this is one HTTP header line without any line breaks or optional whitespace

    -
    OData-error: {"code":"err123","message":"Unsupported
    -functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    -query option not supported"}]}
    +

    Example 64: note that this is one HTTP header line without any line breaks or optional whitespace

    +
    OData-error: {"code":"err123","message":"Unsupported
    +functionality","target":"query","details":[{"code":"forty-two","target":"$search","message":"$search
    +query option not supported"}]}

    diff --git a/docs/odata-json-format/odata-json-format.md b/docs/odata-json-format/odata-json-format.md index d1c5cd893..27c9e5035 100644 --- a/docs/odata-json-format/odata-json-format.md +++ b/docs/odata-json-format/odata-json-format.md @@ -1295,21 +1295,7 @@ An entity is serialized as a JSON object. It MAY contain or [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. -If a nullable single-valued navigation property or -entity-valued annotation or return type of an operation has the `null` value, -the value is serialized as follows: -- If, with [minimal metadata](#metadataminimalodatametadataminimal), - the value carries no [control information](#ControlInformation) other than - [`context`](#ControlInformationcontextodatacontext) - and no [instance annotations](#InstanceAnnotations), - - the value does not have a representation as response to a request (see [OData-Protocol, section 9.1.4](https://docs.oasis-open.org/odata/odata/v4.02/odata-v4.02-part1-protocol.html#ResponseCode204NoContent)) - - but is represented by the JSON literal `null` when it occurs in a name/value pair - in another JSON object (for example, an [expanded single-valued navigation property](#ExpandedNavigationProperty)). -- Otherwise the context control information is omitted and the serialization produces - a JSON object consisting of name/value pairs for the - other control information and instance annotations only. - -Otherwise, each [property](#StructuralProperty) to be transmitted is +Each [property](#StructuralProperty) to be transmitted is represented as a name/value pair within the object. The order properties appear within the object is considered insignificant. @@ -1911,11 +1897,8 @@ An individual property or operation response is represented as a JSON object. A single-valued property or operation response that has the -`null` value does not have a representation provided that, with -[minimal metadata](#metadataminimalodatametadataminimal), it carries no -[control information](#ControlInformation) other than -[`context`](#ControlInformationcontextodatacontext) -and no [instance annotations](#InstanceAnnotations); see [OData-Protocol](#ODataProtocol). +`null` value does not have a representation; see +[OData-Protocol](#ODataProtocol). A property or operation response that is of a primitive type is represented as an object with a name/value pair whose name is @@ -1923,9 +1906,7 @@ represented as an object with a name/value pair whose name is value](#PrimitiveValue) or `null`. A property or operation response that is of complex type is represented -as a [complex value](#ComplexValue). If the value is `null`, the context control information -is omitted and the JSON object consists of name/value pairs for the -other control information and instance annotations only. +as a [complex value](#ComplexValue). A property or operation response that is of a collection type is represented as an object with a name/value pair whose name is @@ -1987,21 +1968,6 @@ Example 30: empty collection of complex values ``` ::: -::: example -Example 31: An action is invoked when a utilities customer moves into a building, -it returns the address. After a successful move-in it might return the -`null` value accompanied by an instance annotation: -```json -{ - "@Core.Messages": [{ - "code": "EADDRESS", - "message": "Street name not yet determined", - "severity": "error" - }] -} -``` -::: - Note: the context URL is optional in requests. ------- @@ -2073,7 +2039,7 @@ control information MUST be included in a response that represents a partial result. ::: example -Example 32: +Example 31: ```json { "@context": "…", @@ -2110,7 +2076,7 @@ control information and MAY contain [`deltaLink`](#ControlInformationdeltaLinkodatadeltaLink) control information. ::: example -Example 33: entity reference to order 10643 +Example 32: entity reference to order 10643 ```json { "@context": "http://host/service/$metadata#$ref", @@ -2120,7 +2086,7 @@ Example 33: entity reference to order 10643 ::: ::: example -Example 34: collection of entity references +Example 33: collection of entity references ```json { "@context": "http://host/service/$metadata#Collection($ref)", @@ -2167,7 +2133,7 @@ subsequent changes once the current set of changes has been applied to the initial set. ::: example -Example 35: a 4.01 delta response with three changes, in order of +Example 34: a 4.01 delta response with three changes, in order of occurrence 1. `ContactName` for customer `BOTTM` was changed to `Susan Halvenstern` @@ -2200,7 +2166,7 @@ occurrence ::: ::: example -Example 36: a 4.0 delta response with three changes, in order of +Example 35: a 4.0 delta response with three changes, in order of occurrence 1. `ContactName` for customer `BOTTM` was changed to `Susan Halvenstern` @@ -2295,7 +2261,7 @@ following optional property, regardless of the specified result (i.e., due to a data change). ::: example -Example 37: deleted entity in OData 4.0 response --- note that `id` is +Example 36: deleted entity in OData 4.0 response --- note that `id` is a property, not control information ```json { @@ -2346,7 +2312,7 @@ representation of a related collection of entities, to represent related entities that have been modified or deleted. ::: example -Example 38: deleted entity in OData 4.01 response with `id` +Example 37: deleted entity in OData 4.01 response with `id` control information (prefixed with an `@`) ```json { @@ -2361,7 +2327,7 @@ control information (prefixed with an `@`) ::: ::: example -Example 39: entity removed OData 4.01 response without `id` +Example 38: entity removed OData 4.01 response without `id` control information and instead all key fields (`ID` is the single key field of `Customer`) ```json @@ -2400,7 +2366,7 @@ only deleted if the navigation property is a containment navigation property. The array MUST NOT contain [added](#AddedLink) or [deleted links](#DeletedLink). ::: example -Example 40: changes to related orders represented as a 4.01 nested delta representation +Example 39: changes to related orders represented as a 4.01 nested delta representation 1. For Customer `ALFKI`: 1. Order 10643 was removed @@ -2466,7 +2432,7 @@ clients SHOULD NOT receive additional notifications for such removed entities. ::: example -Example 41: 4.01 delta response for a single entity with an expanded navigation +Example 40: 4.01 delta response for a single entity with an expanded navigation property containing only a partial list of related entities (as indicated with a [next link](#ControlInformationnextLinkodatanextLink)) ```json @@ -2492,7 +2458,7 @@ information MUST be present for entities are not part of the entity set specifie [`metadata`](#ControllingtheAmountofControlInformationinResponses) value. ::: example -Example 42: changes to related orders represented as a 4.0 flattened delta payload +Example 41: changes to related orders represented as a 4.0 flattened delta payload 1. Order 10643 was removed from customer `ALFKI` 2. Order 10645 was added to customer `ALFKI` @@ -2610,7 +2576,7 @@ entities. OData 4.0 delta payloads MAY additionally include [added](#AddedLink) [deleted](#DeletedLink) links between entities. ::: example -Example 43: 4.01 collection-update request for customers with expanded orders represented +Example 42: 4.01 collection-update request for customers with expanded orders represented inline as a delta 1. Add customer `EASTC` 2. Change `ContactName` of customer `AROUT` @@ -2917,7 +2883,7 @@ is requested, the `target` name/value pair MUST be included if its value differs from the canonical function or action URL. ::: example -Example 44: minimal representation of a function where all overloads are +Example 43: minimal representation of a function where all overloads are applicable ```json { @@ -2929,7 +2895,7 @@ applicable ::: ::: example -Example 45: full representation of a specific overload with parameter +Example 44: full representation of a specific overload with parameter alias for the `Year` parameter ```json { @@ -2944,7 +2910,7 @@ alias for the `Year` parameter ::: ::: example -Example 46: full representation in a collection +Example 45: full representation in a collection ```json { "@context": "http://host/service/$metadata#Employees", @@ -2958,7 +2924,7 @@ Example 46: full representation in a collection ::: ::: example -Example 47: full representation in a nested collection +Example 46: full representation in a nested collection ```json { "@context": "http://host/service/$metadata#Employees/$entity", @@ -3021,7 +2987,7 @@ is requested, the `target` name/value pair MUST be included if its value differs from the canonical function or action URL. ::: example -Example 48: minimal representation in an entity +Example 47: minimal representation in an entity ```json { "@context": "http://host/service/$metadata#LeaveRequests/$entity", @@ -3032,7 +2998,7 @@ Example 48: minimal representation in an entity ::: ::: example -Example 49: full representation in an entity: +Example 48: full representation in an entity: ```json { "@context": "http://host/service/$metadata#LeaveRequests/$entity", @@ -3046,7 +3012,7 @@ Example 49: full representation in an entity: ::: ::: example -Example 50: full representation in a collection +Example 49: full representation in a collection ```json { "@context": "http://host/service/$metadata#LeaveRequests", @@ -3060,7 +3026,7 @@ Example 50: full representation in a collection ::: ::: example -Example 51: full representation in a nested collection +Example 50: full representation in a nested collection ```json { "@context": "http://host/service/$metadata#Employees/$entity", @@ -3093,7 +3059,7 @@ Stream typed parameter values are represented following the same rules as inline Entities as parameter values are represented as explained in [section 6](#Entity). ::: example -Example 52: Create a quote for a product that does not yet exist. The `Product` +Example 51: Create a quote for a product that does not yet exist. The `Product` parameter takes a transient entity. ```json POST http://host/service/CreateQuote @@ -3110,7 +3076,7 @@ Content-Type: application/json ::: ::: example -Example 53: Create a quote for an existing product. The `Product` +Example 52: Create a quote for an existing product. The `Product` parameter takes a non-transient entity which can be identified through its entity-id: ```json @@ -3150,7 +3116,7 @@ non-transient entities can be passed as non-binding action parameters through a resource path in this way. ::: example -Example 54: An employee requests leave from their manager for the next two weeks: +Example 53: An employee requests leave from their manager for the next two weeks: ```json POST /service/Employees(23)/self.RequestLeave Host: host @@ -3196,7 +3162,7 @@ parameter is equivalent to being annotated as optional with a default value of `null`. ::: example -Example 55: +Example 54: ```json { "param1": 42, @@ -3342,7 +3308,7 @@ The request object and the `headers` object MUST NOT contain name/value pairs wi This is in conformance with [RFC7493](#rfc7493). ::: example -Example 56: a batch request that contains +Example 55: a batch request that contains the following individual requests in the order listed 1. A query request @@ -3405,7 +3371,7 @@ contains a relative URL, clients MUST be able to resolve it relative to the request's URL even if that contains such a reference. ::: example -Example 57: a batch request that contains the following operations in +Example 56: a batch request that contains the following operations in the order listed: - Insert a new entity (with `id = 1`) @@ -3440,7 +3406,7 @@ Content-Length: ### ## 19.3 Referencing an ETag ::: example -Example 58: a batch request that contains the following operations in +Example 57: a batch request that contains the following operations in the order listed: - Get an Employee (with `id` = 1) @@ -3483,7 +3449,7 @@ Content-Length: ### ## 19.4 Referencing Response Body Values ::: example -Example 59: a batch request that contains the following operations in +Example 58: a batch request that contains the following operations in the order listed: - Get an employee (with `Content-ID = 1`) @@ -3614,7 +3580,7 @@ request. Especially: URLs in responses MUST NOT contain `$`-prefixed request identifiers. ::: example -Example 60: referencing the batch request [example 56](#batchRequest) above, assume all +Example 59: referencing the batch request [example 55](#batchRequest) above, assume all the requests except the final query request succeed. In this case the response would be ```json @@ -3671,7 +3637,7 @@ to the next link MAY result in a `202 Accepted` response with a `location` header pointing to a new status monitor resource. ::: example -Example 61: referencing the [example 56](#batchRequest) above again, assume that the +Example 60: referencing the [example 55](#batchRequest) above again, assume that the request is sent with the `respond-async` preference. This results in a `202` response pointing to a status monitor resource: ```json @@ -3761,7 +3727,7 @@ asynchronously executed individual request with a `status` of individual status monitor resource, and optionally a `retry-after` header. ::: example -Example 62: the first individual request is processed asynchronously, +Example 61: the first individual request is processed asynchronously, the second synchronously, the batch itself is processed synchronously ```json HTTP/1.1 200 OK @@ -3824,7 +3790,7 @@ the annotations for the value appear next to the `value` property and are not prefixed with a property name. ::: example -Example 63: +Example 62: ```json { "@context": "http://host/service/$metadata#Customers", @@ -3934,7 +3900,7 @@ Error responses MAY contain [annotations](#InstanceAnnotations) in any of its JSON objects. ::: example -Example 64: +Example 63: ```json { "error": { @@ -3983,7 +3949,7 @@ header-appropriate way: [RFC8259](#rfc8259), section 7) ::: example -Example 65: note that this is one HTTP header line without any line +Example 64: note that this is one HTTP header line without any line breaks or optional whitespace ```json OData-error: {"code":"err123","message":"Unsupported diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index 83fc639c6..b24967f3f 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -1210,7 +1210,10 @@

    9.1.4 Response Code 204 No Content

    -

    A request returns 204 No Content if the requested resource has the null value, or if the service applies a return=minimal preference. In this case, the response body MUST be empty.

    +

    A request returns 204 No Content if the requested resource has the null value and carries no control information OData-JSON, section 4.6 other than what the minimal metadata format OData-JSON, section 3.1.1 requires and no instance annotations.

    +

    It also returns 204 No Content if the service applies a return=minimal preference.

    +

    In these cases, the response body MUST be empty.

    +

    If the requested resource has the null value but carries additional control information or instance annotations, the request returns 200 OK instead but omits the context URL from the representation of the response, which then consists of the other control information and instance annotations only.

    As defined in RFC9110, a Data Modification Request that responds with 204 No Content MAY include an ETag header with a value reflecting the result of the data modification if and only if the client can reasonably “know” the new representation of the resource without actually receiving it. For a PUT request this means that the response body of a corresponding 200 OK or 201 Created response would have been identical to the request body, i.e. no server-side modification of values sent in the request body, no server-calculated values etc. For a PATCH request this means that the response body of a corresponding 200 OK or 201 Created response would have consisted of all values sent in the request body, plus (for values not sent in the request body) server-side values corresponding to the ETag value sent in the If-Match header of the PATCH request, i.e. the previous values “known” to the client.

    diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 049d318e4..40e4fc55c 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -1826,9 +1826,19 @@ Requests](#AsynchronousBatchRequests). ### 9.1.4 Response Code `204 No Content` A request returns `204 No Content` if the requested resource has the -`null` value, or if the service applies a +`null` value and carries no control information [OData-JSON, section 4.6](https://docs.oasis-open.org/odata/odata-json-format/v4.02/odata-json-format-v4.02.html#ControlInformation) +other than what the minimal metadata format [OData-JSON, section 3.1.1](https://docs.oasis-open.org/odata/odata-json-format/v4.02/odata-json-format-v4.02.html#metadataminimalodatametadataminimal) +requires and no [instance annotations](#VocabularyExtensibility). + +It also returns `204 No Content` if the service applies a [`return=minimal`](#Preferencereturnrepresentationandreturnminimal) preference. -In this case, the response body MUST be empty. + +In these cases, the response body MUST be empty. + +If the requested resource has the `null` value but carries additional control information +or instance annotations, the request returns [`200 OK`](#ResponseCode200OK) instead but +omits the [context URL](#ContextURL) from the representation of the response, +which then consists of the other control information and instance annotations only. As defined in [RFC9110](#rfc9110), a [Data Modification Request](#DataModification) that responds with From 9b503c47adfeb7e14d64a462cb44b7e779e048d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heiko=20Thei=C3=9Fen?= Date: Fri, 25 Oct 2024 14:46:15 +0200 Subject: [PATCH 7/7] Rephrased --- docs/odata-protocol/odata-protocol.html | 6 +++--- docs/odata-protocol/odata-protocol.md | 12 ++++++------ odata-protocol/8 Header Fields.md | 12 ++++++------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/odata-protocol/odata-protocol.html b/docs/odata-protocol/odata-protocol.html index b24967f3f..501489847 100644 --- a/docs/odata-protocol/odata-protocol.html +++ b/docs/odata-protocol/odata-protocol.html @@ -1210,10 +1210,10 @@

    9.1.4 Response Code 204 No Content

    -

    A request returns 204 No Content if the requested resource has the null value and carries no control information OData-JSON, section 4.6 other than what the minimal metadata format OData-JSON, section 3.1.1 requires and no instance annotations.

    -

    It also returns 204 No Content if the service applies a return=minimal preference.

    -

    In these cases, the response body MUST be empty.

    +

    A request returns 204 No Content if the requested resource has the null value and carries no control information OData-JSON, section 4.6 other than what the minimal metadata format OData-JSON, section 3.1.1 demands and no instance annotations.

    If the requested resource has the null value but carries additional control information or instance annotations, the request returns 200 OK instead but omits the context URL from the representation of the response, which then consists of the other control information and instance annotations only.

    +

    A request always returns 204 No Content if the service applies a return=minimal preference.

    +

    With response code 204, the response body MUST be empty.

    As defined in RFC9110, a Data Modification Request that responds with 204 No Content MAY include an ETag header with a value reflecting the result of the data modification if and only if the client can reasonably “know” the new representation of the resource without actually receiving it. For a PUT request this means that the response body of a corresponding 200 OK or 201 Created response would have been identical to the request body, i.e. no server-side modification of values sent in the request body, no server-calculated values etc. For a PATCH request this means that the response body of a corresponding 200 OK or 201 Created response would have consisted of all values sent in the request body, plus (for values not sent in the request body) server-side values corresponding to the ETag value sent in the If-Match header of the PATCH request, i.e. the previous values “known” to the client.

    diff --git a/docs/odata-protocol/odata-protocol.md b/docs/odata-protocol/odata-protocol.md index 40e4fc55c..0a6e1ac1b 100644 --- a/docs/odata-protocol/odata-protocol.md +++ b/docs/odata-protocol/odata-protocol.md @@ -1828,18 +1828,18 @@ Requests](#AsynchronousBatchRequests). A request returns `204 No Content` if the requested resource has the `null` value and carries no control information [OData-JSON, section 4.6](https://docs.oasis-open.org/odata/odata-json-format/v4.02/odata-json-format-v4.02.html#ControlInformation) other than what the minimal metadata format [OData-JSON, section 3.1.1](https://docs.oasis-open.org/odata/odata-json-format/v4.02/odata-json-format-v4.02.html#metadataminimalodatametadataminimal) -requires and no [instance annotations](#VocabularyExtensibility). - -It also returns `204 No Content` if the service applies a -[`return=minimal`](#Preferencereturnrepresentationandreturnminimal) preference. - -In these cases, the response body MUST be empty. +demands and no [instance annotations](#VocabularyExtensibility). If the requested resource has the `null` value but carries additional control information or instance annotations, the request returns [`200 OK`](#ResponseCode200OK) instead but omits the [context URL](#ContextURL) from the representation of the response, which then consists of the other control information and instance annotations only. +A request always returns `204 No Content` if the service applies a +[`return=minimal`](#Preferencereturnrepresentationandreturnminimal) preference. + +With response code `204`, the response body MUST be empty. + As defined in [RFC9110](#rfc9110), a [Data Modification Request](#DataModification) that responds with `204 No Content` MAY include an [`ETag`](#HeaderETag) header with a value reflecting diff --git a/odata-protocol/8 Header Fields.md b/odata-protocol/8 Header Fields.md index d0988a7f8..1ce00e97b 100644 --- a/odata-protocol/8 Header Fields.md +++ b/odata-protocol/8 Header Fields.md @@ -932,18 +932,18 @@ Requests](#AsynchronousBatchRequests). A request returns `204 No Content` if the requested resource has the `null` value and carries no control information [#OData-JSON#ControlInformation] other than what the minimal metadata format [#OData-JSON#metadataminimalodatametadataminimal] -requires and no [instance annotations](#VocabularyExtensibility). - -It also returns `204 No Content` if the service applies a -[`return=minimal`](#Preferencereturnrepresentationandreturnminimal) preference. - -In these cases, the response body MUST be empty. +demands and no [instance annotations](#VocabularyExtensibility). If the requested resource has the `null` value but carries additional control information or instance annotations, the request returns [`200 OK`](#ResponseCode200OK) instead but omits the [context URL](#ContextURL) from the representation of the response, which then consists of the other control information and instance annotations only. +A request always returns `204 No Content` if the service applies a +[`return=minimal`](#Preferencereturnrepresentationandreturnminimal) preference. + +With response code `204`, the response body MUST be empty. + As defined in [RFC9110](#rfc9110), a [Data Modification Request](#DataModification) that responds with `204 No Content` MAY include an [`ETag`](#HeaderETag) header with a value reflecting