Skip to content
This repository has been archived by the owner on Jul 12, 2020. It is now read-only.

CosmosStore.AddAsync with RequestOptions throws RuntimeBinderException when using TypeNameHandling.All #116

Open
BjornDeRijcke opened this issue Oct 7, 2019 · 4 comments

Comments

@BjornDeRijcke
Copy link

I'm trying to save a document in the database that has a '$type$' property. I thought about using the Request options parameter of the AddAsync method, however this appears to cause a exception.

Given the Add operation on a store: await store.AddAsync(entity, requestOptions, cancellationToken);

If you pass:

var jsonSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
requestOptions = new RequestOptions { JsonSerializerSettings = jsonSettings };

An exception is thrown:
The best overloaded method match for 'Newtonsoft.Json.Linq.JTokenReader.JTokenReader(Newtonsoft.Json.Linq.JToken)' has some invalid arguments

This happens in the code file: https://github.com/Elfocrash/Cosmonaut/blob/develop/src/Cosmonaut/Extensions/CosmonautHelpers.cs in the method ToCosmonautDocument

The code that is causing the issue is:

var document = JsonConvert.DeserializeObject<dynamic>(JsonConvert.SerializeObject(obj, settings), settings);
new JTokenReader(document)

@Elfocrash
Copy link
Owner

Hey @BjornDeRijcke thanks for raising this.

Can you try something out so I can pinpoint the issue? Does the same thing happen if you set the TypeNameHandling as All on the top level serializer as well?

@BjornDeRijcke
Copy link
Author

BjornDeRijcke commented Oct 8, 2019

Yes, the same exception is still thrown. I believe it has something to do with the serialization and deserialization into the dynamic.

When TypeNameHandling is Auto or Full, the resulting object is the class specified by the "$type$" field. When it is None, the resulting object is a JToken.

The JTokenReader only accepts a JToken, so it works when TypeNameHandling is None, but fails when a type is added. (because no constructor exists to accept the dynamic which at runtime is a custom class)

@Elfocrash
Copy link
Owner

Ah I see. I actually hate that this dynamic conversion is there in the first place. I don't know what I was thinking at the time, but I haven't found a reliable replacement that doesn't break backwards compatibility. Any ideas?

@BjornDeRijcke
Copy link
Author

BjornDeRijcke commented Oct 8, 2019

Specifying the generic type as a JToken seems to work for my cases. The resulting object is a JToken.

JsonConvert.DeserializeObject<JToken>(JsonConvert.SerializeObject(entity, settings), settings);

Don't know about all use cases though in light of compatibility.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants