Jericho / ZoomNet

.NET client library for the Zoom.us REST API v2
MIT License
69 stars 46 forks source link

NotSupportedException in .NET 7 #241

Closed Enngage closed 1 year ago

Enngage commented 1 year ago

Hey guys,

Using the .NET 7.0.0-rc.1 we get the following exception:

Exception:

Metadata for type 'System.Nullable`1[ZoomNet.Models.TimeZones]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'. If using source generation, ensure that all root types passed to the serializer have been indicated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically. The unsupported member type is located on type 'System.Text.Json.Nodes.JsonObject'. Path: $.
---> System.NotSupportedException: Metadata for type 'System.Nullable`1[ZoomNet.Models.TimeZones]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'. If using source generation, ensure that all root types passed to the serializer have been indicated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically. The unsupported member type is located on type 'System.Text.Json.Nodes.JsonObject'. Path: $.
---> System.NotSupportedException: Metadata for type 'System.Nullable`1[ZoomNet.Models.TimeZones]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'. If using source generation, ensure that all root types passed to the serializer have been indicated with 'JsonSerializableAttribute', along with any types that might be serialized polymorphically.
at System.Text.Json.ThrowHelper.ThrowNotSupportedException_NoMetadataForType(Type type, IJsonTypeInfoResolver resolver)
at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, Boolean ensureConfigured, Boolean resolveIfMutable)
at System.Text.Json.JsonSerializer.GetTypeInfo(JsonSerializerOptions options, Type inputType)
at System.Text.Json.JsonSerializer.GetTypeInfo[T](JsonSerializerOptions options)
at System.Text.Json.JsonSerializer.Serialize[TValue](Utf8JsonWriter writer, TValue value, JsonSerializerOptions options)
at System.Text.Json.Nodes.JsonValueNotTrimmable`1.WriteTo(Utf8JsonWriter writer, JsonSerializerOptions options)
at System.Text.Json.Nodes.JsonObject.WriteTo(Utf8JsonWriter writer, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
--- End of inner exception stack trace ---
at System.Text.Json.ThrowHelper.ThrowNotSupportedException(WriteStack& state, NotSupportedException ex)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonTypeInfo jsonTypeInfo)
at System.Text.Json.JsonSerializer.WriteStringAsObject(Object value, JsonTypeInfo jsonTypeInfo)
at ZoomNet.Json.ZoomNetJsonFormatter.Serialize(Type type, Object value, Stream stream, HttpContent content, TransportContext transportContext)
at Pathoschild.Http.Client.Formatters.MediaTypeFormatterBase.WriteToStreamAsync(Type type, Object value, Stream stream, HttpContent content, TransportContext transportContext)
--- End of stack trace from previous location ---
at System.Net.Http.HttpContent.g__WaitAsync|56_0(ValueTask copyTask)
at Pathoschild.Http.Client.FluentClientExtensions.CloneAsync(HttpContent content)
at Pathoschild.Http.Client.FluentClientExtensions.CloneAsync(HttpRequestMessage request)
at Pathoschild.Http.Client.FluentClient.SendImplAsync(IRequest request)
at Pathoschild.Http.Client.FluentClient.b__22_0(IRequest req)
at Pathoschild.Http.Client.Retry.RetryCoordinator.ExecuteAsync(IRequest request, Func`2 dispatcher)
at ZoomNet.Utilities.ZoomRetryCoordinator.ExecuteAsync(IRequest request, Func`2 disp

This seems to be related to https://github.com/dotnet/aspnetcore/issues/43236 and a potential workaround is also mentioned at https://github.com/dotnet/runtime/issues/71714

Would be great if you could release a preview with this fix as it's currently preventing users from using ZoomNet in .NET 7 :-)

Enngage commented 1 year ago

Maybe this is related to https://github.com/aspnet/Announcements/issues/494 which should be fixed in rc-2

Jericho commented 1 year ago

I have to admit that I haven't beta tested NET7. Give me some time to review the links you have provided and run the test under NET7.

By the way, do you have a code,sample to help me reproduce the problem?

Enngage commented 1 year ago

Thanks for a quick response!

The code I tested is pretty simple:

var connectionInfo = new JwtConnectionInfo(config.ApiKey, config.ApiSecret);
var client = new ZoomClient(connectionInfo);

await zoomClient.Meetings.CreateScheduledMeetingAsync(
                zoomTrainer.Email,
                appointment.DisplayName,
                appointment.Notes,
                appointment.StartDate,
                appointment.AppointmentLength,
                TimeZones.UTC
            );

This fails with the exception above. This didn't happen on .NET 6. I've migrated straight to rc-1 so I'm not sure if previous versions worked well, but given the accouncement (https://github.com/aspnet/Announcements/issues/494) I would think that this might very well get fixed in rc-2 by the .NET team.

Jericho commented 1 year ago

I am only starting my investigation but I thought I would share my thoughts and findings so far:

I think the root of the problem you are highlighting is that the .NET team made a breaking change in System.Text.Json in .NET7: they are no longer falling back to reflection based serialization when a type is not explicitly specified in the serialization context. It so happens that all model classes are specified in ZoomNet's custom serialization context BUT (and this is important) none of the enum types are listed (such as TimeZones for example, which is the type in the exception you reported).

I haven't tested this yet but I'm pretty sure this problem will go away if I explicitly specify all the enum types in the context.

Jericho commented 1 year ago

I finally have my workstation configured with .NET7 and I am able to reproduce the problem simply by running the unit tests and the integration tests. In fact, what I am observing is even worse than I originally imagined: it's not just the enum that I need to add to the serialization context but also for every specified type, I also need to specify "array of T", "nullable of T", etc.

For example, despite the fact that Recording, ChatChannelMember, MeetingSummary and PhoneNumber are specified in our custom serialization context, I am getting the following exceptions:

Metadata for type 'ZoomNet.Models.Recording[]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'.
Metadata for type 'ZoomNet.Models.ChatChannelMember[]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'.
Metadata for type 'ZoomNet.Models.MeetingSummary[]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'.
Metadata for type 'System.Collections.Generic.IEnumerable`1[ZoomNet.Models.PhoneNumber]' was not provided by TypeInfoResolver of type 'ZoomNet.Json.ZoomNetJsonSerializerContext'.

I tried the TypeInfoResolver = JsonTypeInfoResolver.Combine(ZoomNetJsonSerializerContext.Default, new DefaultJsonTypeInfoResolver()) workaround suggested in one of the articles you linked but it had no effect at all.

Jericho commented 1 year ago

I published a beta package on my MyGet feed for .NET7

I think it should solve all the Metadata for type 'foo' was not provided but let me know if you find that I missed anything.

Enngage commented 1 year ago

Thanks so much @Jericho ! I've installed 0.51.0-net7-0006 and it works great! Thanks again for such a quick response and resolution :-)

Jericho commented 1 year ago

Thanks for confirming. I'll work on merging the changes into the main branch so it gets included in the next release.

Jericho commented 1 year ago

:tada: This issue has been resolved in version 0.51.1 :tada:

The release is available on:

Your GitReleaseManager bot :package::rocket: