Skip to content

Commit 75385be

Browse files
authored
Merge pull request #532 from microsoft/ImproveSubtypes
Clarify: cast is not required in order to see properties of derived types.
2 parents c6331c4 + 7482838 commit 75385be

File tree

1 file changed

+60
-28
lines changed

1 file changed

+60
-28
lines changed

graph/patterns/subtypes.md

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Microsoft Graph API Design Pattern
44

5-
*A frequent pattern in Microsoft Graph is to have a small type hierarchy, a base type with a few subtypes. This lets us model collections of resources that have slightly different metadata and behavior.*
5+
*A frequent pattern in Microsoft Graph is to have a small type hierarchy, a base type with a few subtypes. This lets us model collections of resources that have slightly different properties and behavior.*
66

77
## Problem
88

@@ -27,9 +27,9 @@ You can consider related patterns such as [facets](./facets.md) and [flat bag of
2727
## Issues and considerations
2828

2929
When introducing a new subtype to the hierarchy, developers need to ensure that
30-
the new subtype doesn't change the semantic of the type hierarchy with its implicit constraints.
30+
the new subtype doesn't change the semantic of the type hierarchy or collections of the specified base type with implicit constraints.
3131

32-
To retrieve properties specific for a derived type, an API request URL might need to include casting to the derived type. If the type hierarchy is very deep, then the resulting URL might become very long and not easily readable.
32+
To reference properties specific to a derived type, an API request URL might need to include a segment casting to the derived type. If the type hierarchy is very deep, then the resulting URL might become very long and not easily readable.
3333

3434
There are a few considerations to take into account when new subtypes are introduced:
3535

@@ -52,65 +52,99 @@ and groups stored in Azure Active Directory. Because any directoryObject object
5252
</Key>
5353
<Property Name="id" Type="Edm.String" Nullable="false" />
5454
</EntityType>
55-
<EntityType *Name*="directoryObject" *BaseType*="graph.entity" />
56-
<Property *Name*="deletedDateTime" *Type*="Edm.DateTimeOffset" />
55+
<EntityType Name="directoryObject" BaseType="graph.entity" />
56+
<Property Name="deletedDateTime" Type="Edm.DateTimeOffset" />
5757
<EntityType/>
5858
```
5959

6060
Groups and users are derived types and modeled as follows:
6161

6262
```XML
63-
 <EntityType Name="group" BaseType="graph.directoryObject" />
64-
        <Property Name="accessType" Type="graph.groupAccessType"
65-
63+
<EntityType Name="group" BaseType="graph.directoryObject" />
64+
<Property Name="description" Type="Edm.String" />
65+
...
6666
</EntityType>
6767
<EntityType Name="user" BaseType="graph.directoryObject">
68-
        <Property Name="aboutMe" Type="Edm.String" />
69-
68+
<Property Name="jobTitle" Type="Edm.String" />
69+
...
7070
</EntityType>
7171
```
7272

7373
An API request to get members of a group returns a heterogeneous collection of
7474
users and groups where each element can be a user or a group, and has an
75-
additional property @odata.type for a variant subtype:
75+
additional `@odata.type` property that specifies the subtype:
7676

7777
```
78-
GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members?$select=id,displayName
78+
GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members
7979
80-
Response payload shortened for readability:
80+
Response payload shortened for readability. The deletedDateTime property from the base type is a non-default property and is only returned if explicitly requested.
8181
8282
{
8383
"@odata.context":
84-
"https://graph.microsoft.com/v1.0/\$metadata\#directoryObjects",
85-
    "value": [
86-
        {          
84+
"https://graph.microsoft.com/v1.0/$metadata#directoryObjects",
85+
"value": [
86+
{
8787
"@odata.type": "#microsoft.graph.user",
8888
"id": "37ca648a-a007-4eef-81d7-1127d9be34e8",
89-
"displayName": "John Cob"
89+
"jobTitle": "CEO",
90+
...
9091
},
9192
{
9293
"@odata.type": "#microsoft.graph.group",
9394
"id": "45f25951-d04f-4c44-b9b0-2a79e915658d",
94-
"displayName": "Department 456"
95+
"description": "Microsoft Graph API Reviewers",
96+
...
9597
},
9698
...
97-
    ]
99+
]
100+
}
101+
```
102+
103+
Addressing a property of the subtype, for example, in `$filter` or `$select`, requires prefixing the property with the fully-qualified name of the subtype (or type derived from the subtype) on which it is defined. To filter on the `jobTitle` for the user type, you need to qualify the property with `microsoft.graph.user`.
104+
105+
The following query returns all groups that are members of group a94a666e-0367-412e-b96e-54d28b73b2db, as well as users that are members and whose jobTitle is CEO.
106+
107+
```
108+
GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members?$filter=microsoft.graph.user/jobTitle eq 'CEO'
109+
110+
Response payload shortened for readability:
111+
112+
{
113+
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects",
114+
"value": [
115+
{
116+
"@odata.type": "#microsoft.graph.user",
117+
"id": "37ca648a-a007-4eef-81d7-1127d9be34e8",
118+
"jobTitle": "CEO",
119+
...
120+
},
121+
{
122+
"@odata.type": "#microsoft.graph.group",
123+
"id": "45f25951-d04f-4c44-b9b0-2a79e915658d",
124+
"description": "Microsoft Graph API Reviewers",
125+
...
126+
},
127+
...
128+
]
98129
}
99130
```
100131

101-
An API request for a subtype-specific property requires type casting to the subtype; that is, to retrieve the jobTitle property enabled for the user type, you need to cast from the directoryObject collection items to the `microsoft.graph.group` derived type.
132+
An entire collection can be cast to a particular subtype by appending the fully-qualified subtype name to the URL. Doing so filters the collection to members of (or derived from) that particular subtype, and makes the properties of that subtype available without casting. In this case, the `@odata.type` attribute is not returns for records of the specified subtype because the `@odata.context` indicates that the entire collection is consists of the particular subtype. Types derived from that subtype do still have the `@odata.type` attribute.
133+
134+
The following query returns only users that are members of group a94a666e-0367-412e-b96e-54d28b73b2db and whose jobTitle is CEO.
102135

103136
```
104-
GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members/microsoft.graph.user?$select=displayName,jobTitle
137+
GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members/microsoft.graph.user?$filter=jobTitle eq 'CEO'
105138
106139
Response payload shortened for readability:
107140
108141
{
109-
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(displayName,jobTitle)",
142+
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users",
110143
"value": [
111144
{
112-
"displayName": "John Cob",
113-
"jobTitle": "RESEARCHER II"
145+
"id": "37ca648a-a007-4eef-81d7-1127d9be34e8",
146+
"jobTitle": "CEO",
147+
...
114148
},
115149
...
116150
]
@@ -124,9 +158,7 @@ POST https://graph.microsoft.com/v1.0/directoryObjects
124158
125159
{
126160
"@odata.type": "#microsoft.graph.group",
127-
"displayName": "Library Assist",
128-
"mailEnabled": false,
129-
"mailNickname": "library",
130-
"securityEnabled": true
161+
"description": "Microsoft Graph API Reviewers",
162+
...
131163
}
132164
```

0 commit comments

Comments
 (0)