googleapis / google-api-dotnet-client

Google APIs Client Library for .NET
https://developers.google.com/api-client-library/dotnet
Apache License 2.0
1.35k stars 525 forks source link

Cannot set chrome.networks.wifi.Details.NetworkDetails using chromepolicy.v1 client library #2656

Closed pnogas closed 9 months ago

pnogas commented 9 months ago

Environment details

Steps to reproduce

  1. import the library and use it to create my own Web API wrapper. My controller uses the same request and response types from the library

    [HttpPost]
    [Route("network")]
    public GoogleChromePolicyVersionsV1DefineNetworkResponse CreateNetwork(
    string enterpriseReferenceId,
    [FromBody] GoogleChromePolicyVersionsV1DefineNetworkRequest defineNetworkRequest)

    which will eventually call:

    Google.Apis.ChromePolicy.v1.ChromePolicyService.Customers.Policies.Networks.DefineNetwork(
    defineNetworkRequest,
    "customers/my_customer")
    .Execute()

    with no modifications are made to the request.

  2. Use Postman to test the behaviour. See attached error. PostmanBug

  3. Copy and paste json structure into the "[try this method]"(https://developers.google.com/chrome/policy/reference/rest/v1/customers.policies.networks/defineNetwork) dialog on the API reference page. It works fine.

Notes

we are using the same approach for

Google.Apis.Admin.Directory.directory_v1.DirectoryService.Get("my_customer", path).Execute()

and it works fine

I see that V1DefineNetworkRequest has Settings typed to V1NetworkSetting.

But Settings has value being IDictionary<string, object> instead of what I would expect to be something like IDictionary<string, chrome.networks.cellular.Details.NetworkDetails>

Here are screenshots of what I see coming into my Controller and what I see going out using debugger: ControllerReceived

SentFromClientLib

If there's some way to just tweak my Postman to make it work, it would be sufficient. (although it would be nice to keep it the same as on the "try this method" dialog on the API reference page. It works fine.

amanda-tarafa commented 9 months ago

You seem to have assigned a JsonElement (from System.Text.Json I'm assuming) to the value associated with the "details" key. See that has a "ValueKind" field?

When that whole object is being serialized by Newtonsoft.Json (which is the JSON packge that we use internally) to send on the request, the "ValueKind" field is tagging along, because that's what System.Text.Json.JsonElement.ToString does (see dotnet/runtime#31408), and Newtonsoft.Json will treat System.Text.Json.JsonElement as it would any other "general" object, i.e. it calls ToString for serialization.

The service is just complaining about an unknown field in the request.

You are not showing the code in which you initialize the request object, but if you assign the JSON string to the dictionary value instead of a JsonElement it will work (this is effectively what you did when you copy-pasted that into the "Explore this method" UI). You can actually assign any object whose ToString returns the exact JSON string you want to include in the request.

pnogas commented 9 months ago

Thanks to your comment I was able to solve it. I just needed to switch from

services.AddControllers(options =>
{
  //...
});

to

services.AddControllers(options =>
{
  //...
}).AddNewtonsoftJson();