diff --git a/graph/patterns/subtypes.md b/graph/patterns/subtypes.md index c5c6a098..aad10593 100644 --- a/graph/patterns/subtypes.md +++ b/graph/patterns/subtypes.md @@ -2,7 +2,7 @@ Microsoft Graph API Design Pattern -*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.* +*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.* ## Problem @@ -27,9 +27,9 @@ You can consider related patterns such as [facets](./facets.md) and [flat bag of ## Issues and considerations When introducing a new subtype to the hierarchy, developers need to ensure that -the new subtype doesn't change the semantic of the type hierarchy with its implicit constraints. +the new subtype doesn't change the semantic of the type hierarchy or collections of the specified base type with implicit constraints. -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. +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. There are a few considerations to take into account when new subtypes are introduced: @@ -52,65 +52,99 @@ and groups stored in Azure Active Directory. Because any directoryObject object - - + + ``` Groups and users are derived types and modeled as follows: ```XML -  -        + + ... -        -… + + ... ``` An API request to get members of a group returns a heterogeneous collection of users and groups where each element can be a user or a group, and has an -additional property @odata.type for a variant subtype: +additional `@odata.type` property that specifies the subtype: ``` -GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members?$select=id,displayName +GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members -Response payload shortened for readability: +Response payload shortened for readability. The deletedDateTime property from the base type is a non-default property and is only returned if explicitly requested. { "@odata.context": -"https://graph.microsoft.com/v1.0/\$metadata\#directoryObjects", -    "value": [ -        {           +"https://graph.microsoft.com/v1.0/$metadata#directoryObjects", + "value": [ + { "@odata.type": "#microsoft.graph.user", "id": "37ca648a-a007-4eef-81d7-1127d9be34e8", - "displayName": "John Cob" + "jobTitle": "CEO", + ... }, { "@odata.type": "#microsoft.graph.group", "id": "45f25951-d04f-4c44-b9b0-2a79e915658d", - "displayName": "Department 456" + "description": "Microsoft Graph API Reviewers", + ... }, ... -    ] + ] +} +``` + +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`. + +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. + +``` +GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members?$filter=microsoft.graph.user/jobTitle eq 'CEO' + +Response payload shortened for readability: + +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#directoryObjects", + "value": [ + { + "@odata.type": "#microsoft.graph.user", + "id": "37ca648a-a007-4eef-81d7-1127d9be34e8", + "jobTitle": "CEO", + ... + }, + { + "@odata.type": "#microsoft.graph.group", + "id": "45f25951-d04f-4c44-b9b0-2a79e915658d", + "description": "Microsoft Graph API Reviewers", + ... + }, + ... + ] } ``` -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. +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. + +The following query returns only users that are members of group a94a666e-0367-412e-b96e-54d28b73b2db and whose jobTitle is CEO. ``` -GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members/microsoft.graph.user?$select=displayName,jobTitle +GET https://graph.microsoft.com/v1.0/groups/a94a666e-0367-412e-b96e-54d28b73b2db/members/microsoft.graph.user?$filter=jobTitle eq 'CEO' Response payload shortened for readability: { - "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(displayName,jobTitle)", + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users", "value": [ { - "displayName": "John Cob", - "jobTitle": "RESEARCHER II" + "id": "37ca648a-a007-4eef-81d7-1127d9be34e8", + "jobTitle": "CEO", + ... }, ... ] @@ -124,9 +158,7 @@ POST https://graph.microsoft.com/v1.0/directoryObjects { "@odata.type": "#microsoft.graph.group", - "displayName": "Library Assist", - "mailEnabled": false, - "mailNickname": "library", - "securityEnabled": true + "description": "Microsoft Graph API Reviewers", + ... } ```