question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Document creation/update serialization fails when document object implements interface

See original GitHub issue

Describe the bug Document create/update operations fail when implemented in a method that passes an object implementing an interface.

To Reproduce I’ve implemented a method to handle the creation/updating of documents that implement a specific interface. The relevant snippet of code is as follows:

private async Task TryDocumentActionAsync<T>(DocumentAction action, string databaseId, string tableName, T row)
    where T : ICosmosDbItem
{
    ...
    Container container = this.client.GetContainer(databaseId, tableName);
    switch (action)
    {
        case DocumentAction.Create:
            await container.CreateItemAsync(row).ConfigureAwait(false);
            break;
        case DocumentAction.Upsert:
            await container.UpsertItemAsync(row).ConfigureAwait(false);
            break;
    }
    ...
}

DocumentAction is an enum I’ve created.

Expected behavior Depending on the code branch executed, I expect a document to be created or updated in my database.

Actual behavior I receive the following exception (or similar) when executing either SDK method: Could not create an instance of type FraudHunters.Library.Models.IRiskDataRow. Type is an interface or abstract class and cannot be instantiated. Path 'id', line 1, position 6.

Environment summary SDK Version: v3.5.1 OS Version: Windows

Additional context I am currently able to work around this issue by explicitly changing the document type to the underlying implemented class:

doc = Convert.ChangeType(doc, concreteType);

Here’s the relevant portion of the stack trace:

  | 0 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject","level":0,"line":0}
  | 1 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject","level":1,"line":0}
  | 2 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal","level":2,"line":0}
  | 3 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize","level":3,"line":0}
  | 4 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.JsonSerializer.DeserializeInternal","level":4,"line":0}
  | 5 | {"assembly":"Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed","method":"Newtonsoft.Json.JsonSerializer.Deserialize","level":5,"line":0}
  | 6 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosJsonDotNetSerializer.FromStream","level":6,"line":0}
  | 7 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosJsonSerializerWrapper.FromStream","level":7,"line":0}
  | 8 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosResponseFactory.ToObjectInternal","level":8,"line":0}
  | 9 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosResponseFactory.<CreateItemResponseAsync>b__6_0","level":9,"line":0}
  | 10 | {"assembly":"Microsoft.Azure.Cosmos.Client, Version=3.5.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35","method":"Microsoft.Azure.Cosmos.CosmosResponseFactory+<ProcessMessageAsync>d__16`1.MoveNext","level":10,"line":0}
  | 11 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw","level":11,"line":0}
  | 12 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess","level":12,"line":0}
  | 13 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification","level":13,"line":0}
  | 14 | {"assembly":"System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e","method":"System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1+ConfiguredTaskAwaiter.GetResult","level":14,"line":0}
  | 15 | {"assembly":"FraudHuntersLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","method":"FraudHunters.Library.FHDocumentClient+<TryDocumentActionAsync>d__14`1.MoveNext","level":15,"line":273,"fileName":"C:\\vsts-agent\\_work\\2\\s\\FraudHuntersLibrary\\Clients\\FHDocumentClient.cs"}


Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
YohanSciubukgiancommented, Mar 9, 2020

The scenario where an interface is being passed on <T> is working with the SDK v2.

It’s a blocking point to work with a schemaless database and not being able to work with interfaces to insert documents. We could have a <T> being a List<ICompany> where each ICompany has a list of common properties & each concrete has dedicated properties to the current company.

    public interface ICompany
    {
        string Name { get; set; }
    }

    public class CompanyFoo : ICompany
    {
        public string Name { get; set; }
        public decimal FooValue { get; set; }
    }

    public class CompanyBar : ICompany
    {
        public string Name { get; set; }
        public string BarValue { get; set; }
    }

This is the stacktrace I had using the SDK v3 :

  Message: 
    Newtonsoft.Json.JsonSerializationException : Could not create an instance of type CosmosDbConnector.Tests.Dtos.ICompany. Type is an interface or abstract class and cannot be instantiated. Path 'Document[0].Name', line 1, position 21.
  Stack Trace: 
    JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
    JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
    JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
    JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
    JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
    JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
    JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
    JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
    JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
    JsonSerializer.Deserialize(JsonReader reader, Type objectType)
    JsonSerializer.Deserialize[T](JsonReader reader)
    CosmosJsonDotNetSerializer.FromStream[T](Stream stream)
    CosmosJsonSerializerWrapper.FromStream[T](Stream stream)
    CosmosSerializerCore.FromStream[T](Stream stream)
    CosmosResponseFactory.ToObjectInternal[T](ResponseMessage responseMessage)
    CosmosResponseFactory.<CreateItemResponseAsync>b__5_0[T](ResponseMessage cosmosResponseMessage)
    CosmosResponseFactory.ProcessMessageAsync[T](Task`1 cosmosResponseTask, Func`2 createResponse)
    AzureCosmosDbV3Connector.CreateDocumentAsync[T](String databaseId, String collectionId, DocumentBase`1 item) line 77
    TestCosmosDbConnector.SampleTestV3() line 77
    --- End of stack trace from previous location where exception was thrown ---

I created a repository with a sample usage using the SDK v2 & the SDK v3, it’s available here : https://github.com/YohanSciubukgian/CosmosDbConnector

Environment summary Microsoft.Azure.Cosmos : v3.6.0 Microsoft.Azure.DocumentDB.Core : v2.10.1 OS Version: Windows

0reactions
YohanSciubukgiancommented, Mar 9, 2020
Read more comments on GitHub >

github_iconTop Results From Across the Web

Casting interfaces for deserialization in JSON.NET
Make sure that you are using the same settings for serialization and deserialization. I tested it, and it works like a charm, even...
Read more >
1. Document Object Model Load and Save
Overview. This section defines a set of interfaces for loading and saving document objects as defined in [DOM Level 3 Core].
Read more >
Implementing an Interface (The Java™ Tutorials > ...
To declare a class that implements an interface, you include an implements clause ... Consider an interface that defines how to compare the...
Read more >
SAP Advanced Track and Trace for Pharmaceuticals
Report serial number events to authorities and business partners, enabling compliance to international legislation.
Read more >
Object Interfaces - Manual
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found