Uploaded image for project: 'C# Driver'
  1. C# Driver
  2. CSHARP-1296

StackOverflowException when serializing a class C that implements IEnumerable<C>

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 2.1
    • Affects Version/s: None
    • Component/s: Serialization
    • Labels:
      None

      If the object that is being inserted has a dynamic type with a JObject type in it (this is the default type used by JSON.NET for deserialize the JSON), then the InsertOneAsync method throws the StackOverflowException.

      It would be OK if driver does not support JObject and throws an appropriate exception, but since the StackOverflowException crashes the application and is very hard to debug, at very least the driver should not cause this type of exception.

      This is the code to replicate it:

      async Task Main()
      {
      string msg = @"

      { ""PayrollId"":463236,""Message"":""Fine"",""Success"":true,""MessageCode"":200,""IsError"":false }

      ";
      dynamic details = Newtonsoft.Json.JsonConvert.DeserializeObject(msg);

      var data = new DomainEventData()

      { AggregateId = Guid.NewGuid(), TenantId = Guid.NewGuid(), AggregateName = "Just a test", EventName = "payrollunit-schedule-missed", Details = details }

      ;

      MongoClient client = new MongoClient("mongodb://localhost/tests");
      IMongoDatabase mongo = client.GetDatabase("tests");
      IMongoCollection<DomainEventData> items = mongo.GetCollection<DomainEventData>("entries");

      await items.InsertOneAsync(data);
      }

      // Define other methods and classes here
      [Serializable]
      public class DomainEventData
      {
      public Guid Id

      { get; set; }
      [BsonElement("eventName")]
      public string EventName { get; set; }

      [BsonElement("tenantId")]
      public Guid TenantId

      { get; set; }
      [BsonElement("aggregateId")]
      public Guid AggregateId { get; set; }

      [BsonElement("aggregateName")]
      public string AggregateName

      { get; set; }
      [BsonElement("details")]
      public dynamic Details { get; set; }

      [BsonElement("utcTimestamp")]
      [BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
      public DateTime UtcTimestamp

      { get; set; }

      public DomainEventData()

      { this.Id = Guid.NewGuid(); this.TenantId = Guid.Empty; this.AggregateId = Guid.Empty; this.EventName = string.Empty; this.UtcTimestamp = DateTime.UtcNow; this.AggregateName = string.Empty; }

      }

      BTW, changing the:
      dynamic details = Newtonsoft.Json.JsonConvert.DeserializeObject(msg);
      to:
      dynamic details = Newtonsoft.Json.JsonConvert.DeserializeObject<ExpandoObject>(msg);
      solves the issue, but if application is dealing with unknown data coming in, this might not be an option.

            Assignee:
            robert@mongodb.com Robert Stam
            Reporter:
            lennygran Lenny Granovsky
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: