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.