You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|:heavy_check_mark:**MUST** use POST to create new entities in insertable entity sets or collections.<BR>This approach requires the service to produce a system-generated key, or for a caller to provide a key in the request payload. |
254
-
|:ballot_box_with_check:**SHOULD** additionally use PATCH to create new entities in insertable entity sets or collections.<BR>This [Upsert](./patterns/upsert.md) approach requires the caller to provide a key. |
254
+
|:ballot_box_with_check:**SHOULD** additionally use PATCH to create new entities in insertable entity sets or collections.<BR>This [Upsert](./patterns/upsert.md) approach requires the caller to provide a key in the request URL. |
255
255
|:heavy_check_mark:**MUST** use PATCH to edit updatable resources. |
256
256
|:heavy_check_mark:**MUST** use DELETE to delete deletable resources. |
257
257
|:heavy_check_mark:**MUST** use GET for listing and reading resources. |
Copy file name to clipboardExpand all lines: graph/patterns/upsert.md
+60-26Lines changed: 60 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -21,18 +21,18 @@ Additionally, IaC code scripts or templates usually employ client-provided names
21
21
22
22
The solution is to use an `Upsert` pattern, to solve for the non-idempotent creation and client-provided naming problems.
23
23
24
-
* For IaC scenarios, resources must use `Upsert` semantics with a client-provided key:
25
-
* Use `PATCH` with a client-provided key:
26
-
* If there is a natural client-provided key that can serve as the primary key, then the service should support `Upsert` with that key.
27
-
* If the primary key is service-generated, the client-provided key should use an [alternate key](./alternate-key.md) to support idempotent creation.
28
-
* For a non-existent resource (specified by the client-provided key) the service must handle this as a "create". As part of creation, the service must still generate the primary key value, if appropriate.
24
+
*`Upsert` uses `PATCH` with a client-provided key in the URL:
25
+
* If there is a natural client-provided key that can serve as the primary key, then the service should support `Upsert` with that key.
26
+
* If the primary key is service-generated, the client-provided key should use an [alternate key](./alternate-key.md) to support idempotent creation.
27
+
* For a non-existent resource (specified by the client-provided key) the service must handle this as a "create" (aka insert). As part of creation, the service must still generate the primary key value, if appropriate.
29
28
* For an existing resource (specified by the client-provided key) the service must handle this as an "update".
30
-
* Any new alternate key, used for IaC scenarios, should be called `uniqueName`, if there isn't already a more natural existing property that could be used as an alternate key.
31
-
* NOTE: the service must also support `GET` using the alternate key pattern.
29
+
* If using an alternate key, then
30
+
* for IaC scenarios, the alternate key should be called `uniqueName`, if there isn't already a more natural existing property that could be used as an alternate key.
31
+
* the service must also support `GET` using the alternate key pattern.
32
32
* Services should always support `POST` to the collection URL.
33
33
* For service-generated keys, this should return the server generated key.
34
-
* For client-provided keys, the client should provide the key as part of the request payload.
35
-
* If a service does not support `Upsert`, then a `PATCH` call against a non-existent resource must result in an HTTP "409 conflict" error.
34
+
* For client-provided keys, the client can provide the key as part of the request payload.
35
+
* If a service does not support `Upsert`, then a `PATCH` call against a non-existent resource must result in an HTTP "404 not found" error.
36
36
37
37
This solution allows for existing resources that follow Microsoft Graph conventions for CRUD operations to add `Upsert` without impacting existing apps or functionality.
38
38
@@ -44,9 +44,12 @@ This pattern should be adopted for resources that are managed through infrastruc
44
44
45
45
## Issues and considerations
46
46
47
-
* The addition of this new pattern (with an alternate key) to an existing API does not represent a breaking change.
48
-
However, some API producers may have concerns about accidental usages of this new pattern unwittingly creating many new resources when the intent was an update.
49
-
As a result, API producers can use the `Prefer: idempotent` to require clients to opt-in to the Upsert behavior.
47
+
* Services with existing APIs that use a client-defined key that want to start supporting the `Upsert` pattern may have concerns about backwards compatibility.
48
+
API producers can require clients to opt-in to the `Upsert` pattern, by using the `Prefer: create-if-missing` HTTP request header.
49
+
*`Upsert` can also be supported against singletons, using a `PATCH` to the singleton's URL.
50
+
* Services that support `Upsert` should allow clients to use the:
51
+
*`If-Match=*` request header to explicitly treat an `Upsert` request as an update and not an insert.
52
+
*`If-None-Match=*` request header to explicitly treat an `Upsert` request as an insert and not an update.
50
53
* The client-provided alternate key must be immutable after being set. If its value is null then it should be settable as a way to backfill existing resources for use in IaC scenarios.
51
54
* API producers could use `PUT` operations to create or update, but generally this approach is not recommended due to the destructive nature of `PUT`'s replace semantics.
52
55
* API producers may annotate entity sets, singletons and collections to indicate that entities can be "upserted". The example below shows this annotation for the `groups` entity set.
@@ -61,11 +64,9 @@ As a result, API producers can use the `Prefer: idempotent` to require clients t
61
64
</EntitySet>
62
65
```
63
66
64
-
*`Upsert` can also be supported against singletons, using a `PATCH` to the singleton's URL.
65
-
66
67
## Examples
67
68
68
-
For these examples we'll use the `group` entity type, which defines both a primary (service-generated) key (`id`) and an alternate (client-provided) key (`uniqueName`).
69
+
For these examples we'll use the `group` entity type, which defines both a primary (service-generated) key (`id`) and an alternate (client-provided) key (`uniqueName`).
69
70
70
71
```xml
71
72
<EntityTypeName="group">
@@ -99,7 +100,7 @@ Create a new group, with a `uniqueName` of "Group157". In this case, this group
0 commit comments