Unable to create an instance of type Microsoft.Graph.Message
I tried getting a Message object from Graph using an Access Token I got from the Office.js API from an Outlook Add-In. The request itself works. When I use GetResponseAsync() the StatusCode is 200, the string content is also filled and the information inside is correct.
However, I only get following error message when trying to deserialize the response object into the correct type (using API methods): Unable to create an instance of type Microsoft.Graph.Message
Expected behavior
Calling GetAsync() on the request directly or calling GetResponseObjectAsync() on the response should return a deserialized object of type Message. The content should be serialized correctly. The string content looks correct after all.
I logged the content and it looks like:
{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users('SOMEGUID')/messages(from)/$entity",
"@odata.etag":"W/\"SOMEID\"",
"id":"SOMEITEMID",
"from":{"emailAddress":{"name":"SOME NAME","address":"SOME ADDRESS"}
}
Actual behavior
When I use GetAsync() on the request directly or try to use GetResponseObjectAsync() on the Response, I get following exception:
System.AggregateException: One or more errors occurred. ---> Microsoft.Graph.ServiceException: Code: generalException
Message: Unable to create an instance of type Microsoft.Graph.Message, MY_NAMESPACE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c18082dd7fc434a1.
at Microsoft.Graph.DerivedTypeConverter`1.Read(Utf8JsonReader& reader, Type objectType, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& state, JsonConverter converterBase)
at System.Text.Json.JsonSerializer.<ReadAsync>d__20`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Microsoft.Graph.Serializer.DeserializeObject[T](Stream stream)
at Microsoft.Graph.ResponseHandler.<HandleResponse>d__2`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.Graph.GraphResponse`1.<GetResponseObjectAsync>d__1.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
MYCODE
---> (Inner Exception #0) Status Code: 0
Microsoft.Graph.ServiceException: Code: generalException
Message: Unable to create an instance of type Microsoft.Graph.Message, MY_NAMESPACE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c18082dd7fc434a1.
at Microsoft.Graph.DerivedTypeConverter`1.Read(Utf8JsonReader& reader, Type objectType, JsonSerializerOptions options)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonReaderState& readerState, Boolean isFinalBlock, ReadOnlySpan`1 buffer, JsonSerializerOptions options, ReadStack& state, JsonConverter converterBase)
at System.Text.Json.JsonSerializer.<ReadAsync>d__20`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at Microsoft.Graph.Serializer.DeserializeObject[T](Stream stream)
at Microsoft.Graph.ResponseHandler.<HandleResponse>d__2`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Microsoft.Graph.GraphResponse`1.<GetResponseObjectAsync>d__1.MoveNext()<---
This seems to be throwing in the Read method inside the DerivedTypeConverter during serialization. Not in the Create method but rather line 97 when instance == null. Github DerivedTypeConverter.cs
Steps to reproduce the behavior
When I instead get a User for example, everything works fine, including serialization.
I am calling this inside an IPlugin implementation running in a Dataverse environment. There can be replication problems in Dynamics plugins, but these kind of problems would normally throw a System.MethodAccessException instead.
The whole project is registered to Dataverse within a single assembly, merged with ILRepack.
The serialization is not problematic using custom DTO types (mirroring the SDK's types). Something with the DerivedTypeConverter seems to be incompatible with Xrm IPlugins. Maybe it is some reflection problem after all. For now, using custom types works for me as a workaround, but another more elegant solution would be nice.
Based on the @odata.context, I assume that this is a select query on "from" field. I tried to reproduce the problem in isolation, the deserialization works fine with generated Graph models. I think the context in your application might be causing the problem as you pointed out.
We are publishing the symbols of Microsoft.Graph.Core package. @christoph-burker is there any chance you can step into DerivedTypeConverter to see if the Type passed into Read is from the correct assembly i.e. Microsoft.Graph with correct version information. When I force instance to be null, I get the correct version information from the nuget package, e.g. 4.15.0 as opposed to 1.0.0 in the error message you are getting.
I think repacking the assembly might be breaking our assumption that there is a separate assembly for Microsoft.Graph.dll.
The reason User is working is that it doesn't go through DerivedTypeConverter and is deserialized directly in https://github.com/microsoftgraph/msgraph-sdk-dotnet-core/blob/8627e580c931c10c9f00bb603b326d8456f85db2/src/Microsoft.Graph.Core/Serialization/Serializer.cs#L49-L57
Hi @christoph-burker . Thanks for taking the time to raise this issue and bring this scenario to our attention.
Is repacking into one assembly required to the Dataverse? If not, why did you choose to do it? I would like to understand more about your scenario.
This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.
Based on the
@odata.context, I assume that this is a select query on "from" field. I tried to reproduce the problem in isolation, the deserialization works fine with generated Graph models. I think the context in your application might be causing the problem as you pointed out.We are publishing the symbols of
Microsoft.Graph.Corepackage. @christoph-burker is there any chance you can step intoDerivedTypeConverterto see if theTypepassed intoReadis from the correct assembly i.e.Microsoft.Graphwith correct version information. When I forceinstanceto benull, I get the correct version information from the nuget package, e.g.4.15.0as opposed to1.0.0in the error message you are getting.I think repacking the assembly might be breaking our assumption that there is a separate assembly for Microsoft.Graph.dll.
The reason
Useris working is that it doesn't go throughDerivedTypeConverterand is deserialized directly inhttps://github.com/microsoftgraph/msgraph-sdk-dotnet-core/blob/8627e580c931c10c9f00bb603b326d8456f85db2/src/Microsoft.Graph.Core/Serialization/Serializer.cs#L49-L57
Thanks for your answer!
Yes, it is most likely the repacking / merging into one assembly, that is causing this issue! I understand this is a very specific scenario.. Based on that assumption, in an attempt to reproduce this in a separate project, it could suffice to merge the Graph DLL into the main one to "break" it.
Unfortunately I am not able to live debug and step into the converter in this scenario.
Hi @christoph-burker . Thanks for taking the time to raise this issue and bring this scenario to our attention.
Is repacking into one assembly required to the Dataverse? If not, why did you choose to do it? I would like to understand more about your scenario.
Hi, thanks for your answer!
Unfortunately merging the assemblies is required in my scenario. I think this is due to the Sandbox Isolation in Online Dynamics CRM instances, some security measure. So when I upload library DLLs separately, I cannot access them from my Plugin DLL.
This is resolved by using the latest Kiota preview versions of the SDK.
This is because, the DerivedTypeConverter has now been dropped in favor of taking advantage of the discriminator information available in the metadata and generation of the serialization/deserialization code in the models themselves. Due to this, the deserialization no longer uses the assembly info (such as the assembly name here ) which can be modified by a scenario like that described in this issue but simply involves calling a function present in the model itself which already has the type references for the derived types needed as shown in the link below.
https://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/c74d125488846e41b48ddc28167938638ff92887/src/Microsoft.Graph/Generated/Models/Message.cs#L169