Friday, June 8, 2018

Avoid error “Invalid property 'responseHeaders'” when try to update Azure AD group using Graph client library

Some time ago we faced with interesting problem: when tried to update group using UnifiedGroupsUtility.UpdateUnifiedGroup() method from OfficeDevPnP we got the following error:

HTTP/1.1 400 Bad Request

ef
{
  "error": {
    "code": "Request_BadRequest",
    "message": "Invalid property 'responseHeaders'.",
    "innerError": {
      "request-id": "...",
      "date": "..."
    }
  }
}

Under the hood this method uses .Net Graph client library:

var graphClient = CreateGraphClient(accessToken, retryCount, delay);

var groupToUpdate = await graphClient.Groups[groupId]
	.Request()
	.GetAsync();

if (!String.IsNullOrEmpty(description) && groupToUpdate.Description != description)
{
	groupToUpdate.Description = description;
	updateGroup = true;
}

bool existingIsPrivate = groupToUpdate.Visibility == "Private";
if (existingIsPrivate != isPrivate)
{
	groupToUpdate.Visibility = isPrivate == true ? "Private" : "Public";
	updateGroup = true;
}

if (updateGroup)
{
	var updatedGroup = await graphClient.Groups[groupId]
		.Request()
		.UpdateAsync(groupToUpdate);
}

When I checked in Fiddler request details of UpdateAsync() call I found that JSON representation of group object which is passed to HTTP PATCH method really has responseHeaders property:

PATCH https://graph.microsoft.com/v1.0/groups/{id}

{
  "classification": "Internal",
  "createdDateTime": "...",
  "description": "test",
  "displayName": "...",
  "groupTypes": [
    "Unified"
  ],
  "mail": "...",
  "mailEnabled": true,
  "mailNickname": "...",
  "proxyAddresses": [
    "SMTP:..."
  ],
  "renewedDateTime": "...",
  "securityEnabled": false,
  "visibility": "Public",
  "id": "...",
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups/$entity",
  "deletedDateTime": null,
  "onPremisesLastSyncDateTime": null,
  "onPremisesProvisioningErrors": [],
  "onPremisesSecurityIdentifier": null,
  "onPremisesSyncEnabled": null,
  "preferredDataLocation": null,
  "resourceBehaviorOptions": [],
  "resourceProvisioningOptions": [],
  "responseHeaders": {
    "Transfer-Encoding": [
      "chunked"
    ],
    "request-id": [
      "..."
    ],
    "client-request-id": [
      "..."
    ],
    "x-ms-ags-diagnostic": [
      ...
    ],
    "OData-Version": [
      "4.0"
    ],
    "Duration": [
      "100.3015"
    ],
    "Strict-Transport-Security": [
      "max-age=31536000"
    ],
    "Cache-Control": [
      "private"
    ],
    "Date": [
      "..."
    ]
  },
  "statusCode": "OK"
}

Not sure why responseHeaders property is now added to the group object when it is first returned from graph. In order to avoid this error I used the following workaround: construct new Group object, specify group id and only those properties which should be updated. I.e. update object with minimal required specified properties:

var graphClient = CreateGraphClient(accessToken);
var existingGroup = await graphClient.Groups[groupId].Request().GetAsync();

var groupToUpdateMinimal = new Group();
groupToUpdateMinimal.Id = groupId;

bool updateGroup = false;
if (!string.IsNullOrEmpty(description) && existingGroup.Description != description)
{
	groupToUpdateMinimal.Description = description;
	updateGroup = true;
}

bool existingIsPrivate = existingGroup.Visibility == "Private";
if (isPrivate != null && existingIsPrivate != isPrivate.Value)
{
	groupToUpdateMinimal.Visibility = isPrivate.Value ? "Private" : "Public";
	updateGroup = true;
}

if (updateGroup)
{
	await graphClient.Groups[groupId].Request().UpdateAsync(groupToUpdateMinimal);
}

In this case only id, description and visibility properties are passed to HTTP PATCH method:

{
  "description": "test",
  "visibility": "Public",
  "id": "..."
}

and group is successfully updated.

No comments:

Post a Comment