From 34cd37364da1cef8be67dd6c92a388978674b717 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 10:03:58 -0700
Subject: [PATCH 1/9] Create encoded-ids.md
---
graph/patterns/encoded-ids.md | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 graph/patterns/encoded-ids.md
diff --git a/graph/patterns/encoded-ids.md b/graph/patterns/encoded-ids.md
new file mode 100644
index 00000000..26336e73
--- /dev/null
+++ b/graph/patterns/encoded-ids.md
@@ -0,0 +1,30 @@
+# Pattern name
+
+Microsoft Graph API Design Pattern
+
+*Provide a short description of the pattern.*
+
+
+## Problem
+
+*Describe the business context relevant for the pattern.*
+
+*Provide a short description of the problem.*
+
+## Solution
+
+*Describe how to implement the solution to solve the problem.*
+
+*Describe related patterns.*
+
+## When to use this pattern
+
+*Describe when and why the solution is applicable and when it might not be.*
+
+## Issues and considerations
+
+*Describe tradeoffs of the solution.*
+
+## Example
+
+*Provide a short example from real life.*
From 84b2d7cbd1325e675d95c75661c8e724dcf00982 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 10:04:41 -0700
Subject: [PATCH 2/9] Update and rename encoded-ids.md to encoded-keys.md
---
graph/patterns/{encoded-ids.md => encoded-keys.md} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename graph/patterns/{encoded-ids.md => encoded-keys.md} (95%)
diff --git a/graph/patterns/encoded-ids.md b/graph/patterns/encoded-keys.md
similarity index 95%
rename from graph/patterns/encoded-ids.md
rename to graph/patterns/encoded-keys.md
index 26336e73..043f7668 100644
--- a/graph/patterns/encoded-ids.md
+++ b/graph/patterns/encoded-keys.md
@@ -1,4 +1,4 @@
-# Pattern name
+# Encoded Key Properties
Microsoft Graph API Design Pattern
From c5ecbafd81beaf3159ac0e56310091e89fb60b98 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 10:07:58 -0700
Subject: [PATCH 3/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index 043f7668..20795c20 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -2,7 +2,7 @@
Microsoft Graph API Design Pattern
-*Provide a short description of the pattern.*
+Key properties should be encoded with [base64url encoding](https://datatracker.ietf.org/doc/html/rfc4648#section-5) when their values can include the `/` character.
## Problem
From ee9398195f0e9df23e08c3300841002b54550b8c Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 10:32:54 -0700
Subject: [PATCH 4/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index 20795c20..fc054a37 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -7,9 +7,9 @@ Key properties should be encoded with [base64url encoding](https://datatracker.i
## Problem
-*Describe the business context relevant for the pattern.*
-
-*Provide a short description of the problem.*
+OData URLs that identify an individual entity within a collection will contain the key for that entity.
+These keys can sometimes include reserved URL characters, and the [OData standard](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_URLParsing) indicates that these characters should be percent-encoded.
+Due to a long-standing bug in Microsoft Graph, and one that cannot be fixed in order to maintain backwards compatibility, percent-encoding the `/` character is not possible for Microsoft Graph APIs.
## Solution
From 2f5c3c537c6378e89fd171a4fa598c71db36c555 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 10:55:05 -0700
Subject: [PATCH 5/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index fc054a37..dbdd550a 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -10,20 +10,23 @@ Key properties should be encoded with [base64url encoding](https://datatracker.i
OData URLs that identify an individual entity within a collection will contain the key for that entity.
These keys can sometimes include reserved URL characters, and the [OData standard](https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_URLParsing) indicates that these characters should be percent-encoded.
Due to a long-standing bug in Microsoft Graph, and one that cannot be fixed in order to maintain backwards compatibility, percent-encoding the `/` character is not possible for Microsoft Graph APIs.
+This means that key properties cannot contain the `/` character, which can be limiting to the API design.
## Solution
-*Describe how to implement the solution to solve the problem.*
-
-*Describe related patterns.*
+A key property that may contain the `/` character should be base64url encoded, and each instance of the property should be encoded regardless if that particular value contains the `/` character.
+The entity may additionally include a non-key property that contains the plaintext of the key property.
+This property should have the same name as the key property with `Plaintext` appended.
+The collection may also support filtering on the plaintext property.
## When to use this pattern
-*Describe when and why the solution is applicable and when it might not be.*
+This pattern should be used whenever the value of a key property may contain a `/` character.
## Issues and considerations
-*Describe tradeoffs of the solution.*
+Encoding a key property often obfuscates the natural way that a client identifies an entity, particularly entities that are related to extenal services or standards.
+A plaintext property that allows filtering can help to reduce this impact, but filtering itself has semantic limitations in OData (for example, if the client wants to navigate to a navigation property of the entity, using a filter does not allow this).
## Example
From 35b9a9c3c17fca1de8be0f205fe0f5ac4d0ce543 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 14:33:26 -0700
Subject: [PATCH 6/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 47 +++++++++++++++++++++++++++++++++-
1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index dbdd550a..3cb6ce2f 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -30,4 +30,49 @@ A plaintext property that allows filtering can help to reduce this impact, but f
## Example
-*Provide a short example from real life.*
+```xml
+
+
+
+
+
+
+
+
+ ...
+
+```
+```json
+GET /foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
+
+200 OK
+{
+ "id": "dGhpcyBpcyBhbiBpZCB3aXRoIC8",
+ "idPlaintext": "this is an id with /",
+ ...
+}
+```
+```json
+GET /foos('dGhpcyBpcyBhbiBpZCB3aXRoIC8')
+
+200 OK
+{
+ "id": "dGhpcyBpcyBhbiBpZCB3aXRoIC8",
+ "idPlaintext": "this is an id with /",
+ ...
+}
+```
+```json
+GET /foos?$filter=idPlaintext eq 'this is an id with /'
+
+200 OK
+{
+ "value": [
+ {
+ "id": "dGhpcyBpcyBhbiBpZCB3aXRoIC8",
+ "idPlaintext": "this is an id with /",
+ ...
+ }
+ ]
+}
+```
From 1e3ab8540722085e236d69d19ffca17a5fc539be Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 14:35:48 -0700
Subject: [PATCH 7/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index 3cb6ce2f..a57899f6 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -43,7 +43,7 @@ A plaintext property that allows filtering can help to reduce this impact, but f
```
```json
-GET /foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
+GET https://www.test.com/foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
200 OK
{
From aa99e009eaf48c4b0d2a194b2db19ee4ab26de19 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 14:37:23 -0700
Subject: [PATCH 8/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index a57899f6..eef1f954 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -42,7 +42,7 @@ A plaintext property that allows filtering can help to reduce this impact, but f
...
```
-```json
+```http
GET https://www.test.com/foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
200 OK
@@ -52,7 +52,7 @@ GET https://www.test.com/foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
...
}
```
-```json
+```http
GET /foos('dGhpcyBpcyBhbiBpZCB3aXRoIC8')
200 OK
@@ -62,7 +62,7 @@ GET /foos('dGhpcyBpcyBhbiBpZCB3aXRoIC8')
...
}
```
-```json
+```http
GET /foos?$filter=idPlaintext eq 'this is an id with /'
200 OK
From 5ca2e24d265b4a8d9adac1e07946e6084625a238 Mon Sep 17 00:00:00 2001
From: Garrett DeBruin <16618938+corranrogue9@users.noreply.github.com>
Date: Fri, 22 Sep 2023 14:37:54 -0700
Subject: [PATCH 9/9] Update encoded-keys.md
---
graph/patterns/encoded-keys.md | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/graph/patterns/encoded-keys.md b/graph/patterns/encoded-keys.md
index eef1f954..a18b9c2e 100644
--- a/graph/patterns/encoded-keys.md
+++ b/graph/patterns/encoded-keys.md
@@ -39,17 +39,15 @@ A plaintext property that allows filtering can help to reduce this impact, but f
- ...
```
```http
-GET https://www.test.com/foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
+GET /foos/dGhpcyBpcyBhbiBpZCB3aXRoIC8
200 OK
{
"id": "dGhpcyBpcyBhbiBpZCB3aXRoIC8",
- "idPlaintext": "this is an id with /",
- ...
+ "idPlaintext": "this is an id with /"
}
```
```http
@@ -58,8 +56,7 @@ GET /foos('dGhpcyBpcyBhbiBpZCB3aXRoIC8')
200 OK
{
"id": "dGhpcyBpcyBhbiBpZCB3aXRoIC8",
- "idPlaintext": "this is an id with /",
- ...
+ "idPlaintext": "this is an id with /"
}
```
```http
@@ -70,8 +67,7 @@ GET /foos?$filter=idPlaintext eq 'this is an id with /'
"value": [
{
"id": "dGhpcyBpcyBhbiBpZCB3aXRoIC8",
- "idPlaintext": "this is an id with /",
- ...
+ "idPlaintext": "this is an id with /"
}
]
}