microsoftgraph / msgraph-sdk-serviceissues

Tracks service issues for follow up.
5 stars 0 forks source link

Group Members method vs. contacts #73

Open mtmjansen opened 5 years ago

mtmjansen commented 5 years ago

Please provide the following (and please check them off the list with [x]) before submitting this issue:

Expected behavior

The described behaviour is: Link to API method The Graph method to list members of a group should respond with a collection of directoryObject objects (i.e. users or child groups)

Also returning contacts is kinda expected, eventually.

Actual behavior

(Since I think I know what's going on I kinda skipped the Fiddler exercise and just used postman instead, at the risk of having to add the Fiddler stuff later.)

Next to users and groups it the API also returns contacts. Contacts are not derived from directoryObjects.

Using Postman to send a get-members-of-group-request, all goes well. Please notice one of the members is a contact. postman-request

response headers reposnse-headers

SDK

When we make the same request using the .NET SDK v1.12 we get an exception: ArgumentException: The value 'Microsoft.Graph.Contact' is not of type 'Microsoft.Graph.DirectoryObject' and cannot be used in this generic collection. Parameter name: value

`public static async Task IEnumerable GetAllGroupMembers(GraphServiceClient client,string groupId) { const int pageSize = 512; var result = new List();

    // This will throw when one or more members are of @odata.type "#microsoft.graph.contact"
    var members = await client.Groups[groupId].Members.Request().Select("id").Top(pageSize).GetAsync();

    result.AddRange(members);

    while (members.NextPageRequest != null)
    {
        members = await members.NextPageRequest.GetAsync();
        result.AddRange(members);
    }

    return result;

} `

The response type for the GetAsync method is IGroupMembersCollectionWithReferencesPage : ICollectionPage<DirectoryObject> Given that Microsoft.Graph.Contact is not derived from DirectoryObject, hence the exception.

Steps to reproduce the behavior

Add a contact to a group. Try to list the members of the group.

AB#7320

MIchaelMainer commented 5 years ago

@mtmjansen Crafted issues get immediate responses. Thank you for the thorough repro instructions! The service is neither in sync with the documentation nor the metadata.

MIchaelMainer commented 5 years ago

I think the workaround will be to:

  1. Get the HttpRequestMessage from client.Groups[groupId].Members.Request().Select("id").Top(pageSize).GetHttpRequestMessage()
  2. Create IGroupMembersCollectionWithReferencesPage2 : ICollectionPage<Entity> to deserialize the response. We should take this on if the Contact entity is intentional in that response. I will follow up..
  3. Send request, get response. I don't think NextPageRequest will be populated so the nextLink URL will need to be extracted to make the next paged request.

We are adding a paging iterator to make paging a bit more straightforward. I'll be considering this scenario.

Related: https://github.com/microsoftgraph/microsoft-graph-docs/issues/4238

mtmjansen commented 5 years ago

ended up writing ...

ghelyar commented 4 years ago

Just to add to this

Both of these include users, groups and contacts with exactly the same response

https://graph.microsoft.com/beta/groups/{groupId}/members
https://graph.microsoft.com/beta/groups/{groupId}/members/microsoft.graph.directoryObject

The response indicates that contacts are directory objects:

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#directoryObjects(id)",
    "value": [
        {
            "@odata.type": "#microsoft.graph.contact",
            "id": "..."
        }
    ]
}

This only includes users

https://graph.microsoft.com/beta/groups/{groupId}/members/microsoft.graph.user

This only includes groups

https://graph.microsoft.com/beta/groups/{groupId}/members/microsoft.graph.group

This returns a 400 bad request error, indicating that contacts are not directory objects:

https://graph.microsoft.com/beta/groups/{groupId}/members/microsoft.graph.contact
{
    "error": {
        "code": "BadRequest",
        "message": "The type 'microsoft.graph.contact' specified in the URI is neither a base type nor a sub-type of the previously-specified type 'microsoft.graph.directoryObject'.",

Also, this seems to only occur on the /beta endpoint. Contacts are not returned in the /v1.0 endpoint.

darrelmiller commented 4 years ago

This has been fixed and should be rolling out soon. You should start seeing the OData.Type as microsoft.graph.orgContact which does derive from directoryObject.

ghelyar commented 4 years ago

This seems to have got worse. Now you can't list members at all, which prevents the workaround from working.

Just submitting a group membership request for a group that has contacts as members now returns a bad request error from the server, instead of a response that contains the contacts that the client was failing to deserialize.

https://graph.microsoft.com/beta/groups/{groupId}/members

{"@odata.context":"https://graph.microsoft.com/beta/$metadata#directoryObjects","value":[... actual values omitted ...]}{
  "error": {
    "code": "BadRequest",
    "message": "A resource of type 'microsoft.graph.contact' was found in a resource set that otherwise has entries of type 'microsoft.graph.directoryObject'. In OData, all entries in a resource set must have a common base type.",
    "innerError": {
      "request-id": "c5a82ebc-3f0f-4eec-824a-20e6c167748d",
      "date": "2019-09-19T09:33:13"
    }
  }
}

Note that there was nothing wrong with this request, it was the data on the server that was bad.

darrelmiller commented 4 years ago

/cc @dkershaw10

antonGritsenko commented 4 years ago

Same story with IServicePrincipalOwnersCollectionWithReferencesRequest:

System.ArgumentException: The value 'Microsoft.Graph.User' is not of type 'Microsoft.Graph.DirectoryObject' and cannot be used in this generic collection. (Parameter 'value')
   at Newtonsoft.Json.Utilities.CollectionWrapper`1.VerifyValueType(Object value)
   at Newtonsoft.Json.Utilities.CollectionWrapper`1.System.Collections.IList.Add(Object value)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Populate(JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerProxy.PopulateInternal(JsonReader reader, Object target)
   at Newtonsoft.Json.Converters.CustomCreationConverter`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Microsoft.Graph.Serializer.DeserializeObject[T](String inputString)
   at Microsoft.Graph.ResponseHandler.HandleResponse[T](HttpResponseMessage response)
   at Microsoft.Graph.BaseRequest.SendAsync[T](Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Microsoft.Graph.ServicePrincipalOwnersCollectionWithReferencesRequest.GetAsync(CancellationToken cancellationToken)

Workaround with overriding IServicePrincipalOwnersCollectionWithReferencesPage and ServicePrincipalOwnersCollectionWithReferencesResponse works fine.

SimSpfx commented 3 years ago

Hello,

Just wondering: is this fixed already? I get the same errors on the next endpoint:

https://graph.microsoft.com/v1.0/me/transitiveMemberOf/microsoft.graph.group?$count=true

"message": "A resource of type 'microsoft.graph.directoryRole' was found in a resource set that otherwise has entries of type 'microsoft.graph.group'. In OData, all entries in a resource set must have a common base type.",

If this is not the right location i will create a new issue. But i think it is related.

Kind regards Simon

exaiwitmx commented 3 years ago

Hello,

I get a similar error related to Messages - see: https://stackoverflow.com/q/65094807/13039722

Is this the same problem or should I create a new issue?

Thanks.

MIchaelMainer commented 3 years ago

@SimSpfx That looks like a separate issue. Open an issue on that and provide a requestId and the datetime from the error response.

@exaiwitmx This is a different but related issue. I've responded on StackOverflow. The service should not be returning an OutlookItem.

davidkarlsen commented 3 years ago

Seems to be same issue as https://github.com/microsoftgraph/msgraph-sdk-java/issues/586 - AD is drunk :-)

petrhollayms commented 3 months ago

Thank you for reporting this issue. This appears to be an issue or limitation with the service APIs. Unfortunately, as the Microsoft Graph SDK team, we do not have ownership of the APIs that are causing you issues. We invite you to create a question about the service API to Microsoft Q&A and tagged with one of the [microsoft-graph-*] tags, that way it will get routed to the appropriate team for them to triage:

https://aka.ms/msgraphsupport or directly https://aka.ms/askgraph

For now, we will close the issue on our side but feel free to open it in the relevant repository if you think the issue is specific to SDK. Please let us know if this helps!

Note: We will close this repository on April 19, 2024.