I have been working on a side project since couple of weeks, and the 1st choice I had to make, was to decide what language to use. The project was going to be command line application, so any language would have sufficed. Among the languages that I am comfortable with, I chose C# with .net core. Reasons for my choice were:

  • I wanted to write C# for a change. After working with C# for 5yrs l, I had been working with nodejs for more than a year now professionally. I wanted to give .net core a try so I chose C#.
  • I wanted to see how good is the cross platform development of command line application with .net core.
  • Because why not.

This worked great, my application was up & running after few days of working lazily. And I was pretty happy with my choice. Later on I had a requirement of creating a set of APIs hosted on lambda. Again I went with C# because, like I said earlier, I was pretty happy with it.

This is where I started to face problems with my choice. Setting up the initial project structure with serverless framework took some time, but I was up & running with a dummy api in a day. I found out few blogs with example of how to do it right. My problems really started to appear when I started writing the logic to my application.

I had chosen mongodb as my choice of database, because I was getting free hosting from Mongodb Atlas. Plus my data was little dynamic so using nosql database seemed like the right choice. Little did I know of the struggle ahead of me. I started the tutorial on the official asp.net website to create my model. Since my model also had a dynamic property which was going to be a JSON object, I followed the documentation, and declared my dynamic property as a BsonDocument.

public class Image {
    public ObjectId Id { get; set; }        
    public string Url { get; set; }        
    public BsonTimestamp Timestamp { get; set; }                                
    public string Title { get; set; }                
    public BsonDocument WikimediaData { get; set; }    
}

When I made the POST request to my web api, I got an error response:

"Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into
type'MongoDB.Bson.BsonDocument' because the type requires a JSON array 
(e.g. [1,2,3])to deserialize correctly.\r\nTo fix this error either change the JSON
to a JSONarray (e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NETtype (e.g. not a primitive type like integer, not a collection type like an
array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute
can also be added to the type to force it to deserialize from a JSON object.
\r\nPath 'WikimediaData.something', line 5, position 14."

I was passing a JSON body, and the webapi was not able to deserialize the JSON into the model. The JSON I was passing was:

{
    "Url": "https://something.example.com/images/abc.png",
    "Title": "Something is nothing",
    "WikimediaData": {
        "something": "nothing",
        "what": true,
        "that": 24,
        "and": {
            "this": "ok"
        }
    }
}

In my model, the WikimediaData was declared as BsonDocument, and that is where de-serialization was failing. So I tried changing it from BsonDocument to dynamic & object. In both the cases, deserialization worked, but what was saved in Mongodb was not at all useful.

{
  "_id": "5c28f0f84a11073aa8fae5da",
  "Url": "https://something.example.com/images/abc.png",
  "Timestamp": "6640822598500352001",
  "Title": "Something is nothing",
  "WikimediaData": {
    "_t": "Newtonsoft.Json.Linq.JObject, Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed",
    "_v": {
      "something": {
        "_t": "JValue",
        "_v": []
      },
      "what": {
        "_t": "JValue",
        "_v": []
      },
      "that": {
        "_t": "JValue",
        "_v": []
      },
      "and": {
        "_t": "JObject",
        "_v": [
          {
            "_t": "JProperty",
            "_v": [
              {
                "_t": "JValue",
                "_v": []
              }
            ]
          }
        ]
      }
    }
  }
}

As you can see all the information got lost when the property was declared as dynamic or object. Next few days I spent figuring out to configure a custom deserializer to parse the JSON body BsonDocument. Since webapi uses JSON.NET I figured out I can create a custom JsonConverter and use that to deserialize. Finally it worked, even though the data saved in MongoDB was not perfect, it was better then nothing

{
  "_id": "5c30f6e31667101138d9fb3d",
  "Url": "https://something.example.com/images/abc.png",
  "Timestamp": "6643080905189490689",
  "Title": "Something is nothing",
  "WikimediaData": {
    "_t": "MongoDB.Bson.BsonDocument, MongoDB.Bson",
    "_v": {
      "something": "nothing",
      "what": true,
      "that": 24,
      "and": {
        "this": "ok"
      }
    }
  }
}

Now that data was getting saved, I created another api endpoint to retrieve the data. That's where 2nd problem appeared.I was able to easily read data from MongoDB, but when sending the object as json in response, I was getting error. After some google-fu I found out that native mongodb datatypes are not serialized correctly, even though the documentation claims it to be the case.

In the end, I decided that even though there are workarounds available to make it work, it seemed like too much of an effort for a simple CRUD API for a side project. And when I already know that with nodejs there are no such issues, it was time to go back to nodejs.