skip to Main Content

I’m making a GET request call to get back all application with their Id, and password expiration date. I’ve been working with the Graph Explore that Microsoft offers and has been a lot of help. The code I have gets the http request back and then It try’s to deserialize it blows up with the given error below. I’ve spent a good while on SOF looking at similar post but nothing seems to work. I feel I might be missing something simple here or going about it the wrong way.

I’m also stuck on an older version of the Graph Nugget pkg v4.41.0 and Core is at v2.0.13. I went to update them and there were a lot of breaking changes thru out the app and I don’t have time to rewrite everything yet.

I get the following error:

"Message": "An error has occurred.", 
"ExceptionMessage": "Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Microsoft.Graph.Application]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.rnTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.rnPath '['@odata.context']', line 1, position 18.",
"ExceptionType": "Newtonsoft.Json.JsonSerializationException",
"StackTrace": "   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)rn   at Newtonsoft.Json.Serialization...
        public async Task<List<Microsoft.Graph.Application>> GetAppExpList()
        {
           List<Microsoft.Graph.Application> apps = null;                       

           // query string for url call
           var url = this.GetGraphUrl($"{Consts.GraphUrl}?$select=id,passwordCredentials&$format=json");
           
           // tried to do this with the built in Graph methods
           List<QueryOption> options = new List<QueryOption>
           {
            new QueryOption("$select", "id,DisplayName,passwordCredentials"), 
            new QueryOption("$format", "json")
           };

           // Here I wanted to see what was brought back. No PasswordCreds for some reason 
           var test = await _graphClient.Applications.Request(options).GetAsync();


          // GET request to the Applications Graph Api
          var response = await this.HttpHandler.SendGraphGetRequest(url);            
        
          // Returns JSON data 
          if (response.IsSuccessStatusCode)
          {
            // Shows the correct data in JSON Format
            var rawData = await response.Content.ReadAsStringAsync();

            // Throws error above.    
            apps = JsonConvert.DeserializeObject<List<Microsoft.Graph.Application>>(rawData);
                            
          }

         return apps; 
    }

Here is the JSON that comes back for the var rawData = await response.Content.ReadAsStringAsync();

{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#applications(id,passwordCredentials)"
 ,"value":[
 {
    "id":"00000000-0000-0000-0000-000000000000",
    "displayName":"App 1 name Here",
    "passwordCredentials":[]
 },
 {
    "id":"00000000-0000-0000-0000-000000000001",
    "displayName":" App 2 name here",
    "passwordCredentials":[]
 },
 {
    "id":"00000000-0000-0000-0000-000000000002",
    "displayName":"App 3 name here",
    "passwordCredentials":[
       {
        "customKeyIdentifier":null,
        "displayName":"secret",
        "endDateTime":"2025-01-30T14:46:40.985Z",
        "hint":"oHI",
        "keyId":"00000000-0000-0000-0000-0000000000",
        "secretText":null,
        "startDateTime":"2023-01-31T14:46:40.985Z"
        }
     ]
  }
]

}

2

Answers


  1. Deserialization of List<Microsoft.Graph.Application> will not work, because the response is not a JSON object, not a JSON array.
    Try to deserialize the response as GraphServiceApplicationsCollectionPage

    if (response.IsSuccessStatusCode)
    {
        // Shows the correct data in JSON Format
        var rawData = await response.Content.ReadAsStringAsync();
    
        var response = JsonConvert.DeserializeObject<GraphServiceApplicationsCollectionPage>(rawData);
        
        apps = response.CurrentPage.ToList();
                                
    }
    
    Login or Signup to reply.
  2. try code below to convert the string result.

    var rawData = await response.Content.ReadAsStringAsync();
    dynamic obj = JsonConvert.DeserializeObject<dynamic>(rawData);
    var appList = obj.value;
    List<Application> apps = JsonConvert.DeserializeObject<List<Application>>(appList.ToString());
    

    By the way, I still recommend using Graph sdk to get the result. It looks like that you are trying to use V5 Graph SDK, you might try my codes below. Codes and configurations in Program.cs and appsettings.json are the same, the required nuget packages and GraphClient codes have some differences.

    <ItemGroup>
      <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" NoWarn="NU1605" />
      <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="8.0.0" NoWarn="NU1605" />
      <PackageReference Include="Microsoft.Identity.Web" Version="2.15.2" />
      <PackageReference Include="Microsoft.Identity.Web.UI" Version="2.15.2" />
      <PackageReference Include="Microsoft.Identity.Web.DownstreamApi" Version="2.15.2" />
        <PackageReference Include="Microsoft.Identity.Web.GraphServiceClient" Version="2.15.2" />
    </ItemGroup>
    
    //UserCollectionResponse
    var users = await _graphServiceClient.Users.GetAsync();
    //ApplicationCollectionResponse
    var apps = await _graphServiceClient.Applications
                    .GetAsync(requestionConfiguration =>
                    {
                        requestionConfiguration.QueryParameters.Select = new string[] { "Id", "DisplayName", "passwordCredentials" };
                    }
                    );
    

    enter image description here

    If you are using client credential flow which using Application Api permission, then you can try codes below.

     var scopes = new[] { "https://graph.microsoft.com/.default" };
     var tenantId = "tenantId";
     var clientId = "clientId";
     var clientSecret = "clientSecret";
     var clientSecretCredential = new ClientSecretCredential(
                     tenantId, clientId, clientSecret);
     var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
     //UserCollectionResponse
     var users = await graphClient.Users.GetAsync();
     //ApplicationCollectionResponse
     var apps = await graphClient.Applications
                     .GetAsync(requestionConfiguration =>
                     {
                         requestionConfiguration.QueryParameters.Select = new string[] { "Id", "DisplayName", "passwordCredentials" };
                     }
                     );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search