Working with API’s is all about JSON these days. Like all these SAAS products, big platforms like Microsoft or Google, all speak Rest and JSON. However, when working with API’s you can find a lot of code in C# or GO or PHP or whatever else that is really odd when you think of it. To be able to generate JSON payload in lets say C# you would generate a ton of new objects, fill those with data just to serialize them at the end and probably have them garbage collected.
While working on a new service, we use to write integrations at Teamwork.com, I actually thought
„Why write C# or Go code, to (de-) serialize it later if we can do it in JSON directly?“
And that’s really true. Taken our recent work on MS Teams and adaptive cards as an example let me show you what I’m talking about:
You can find this probably a lot in source code all around the world
In our example we’re sending a person’s status update to MS Teams and we’re using Adaptive Cards for that. The JSON scheme needed for that is pretty complex if you want to create beautiful cards. The „old“ current approach is that you’d generate multiple objects with item collections and a few text fields filled with actual data from your object.
The approach for C# as taken from various samples and guides, for our card, would probably look similar to this:
This is pretty much what you can find in tons of repositories working with adaptive cards these days. In either C# or any other object oriented language.
Its pretty much always the same. Tons of new objects created, tons lines of code just to serialize everything down at the end. All that uses memory, performance and is not really maintainable on top of it. While working on that, I was searching for a better solution as all that really annoyed me. And, guess what, I found one!
Using razor templates to work with JSON
This is pretty much what you can find in our code quite often now:
We have what we call a „Card Rendering Service“ that does all the work for us to create the JSON scheme needed for the adaptive card and also fills it with actual data.
The service uses less memory, is a lot faster and way easier to maintain than the old class/object/serialization based approach.
The actual card rendering implementation is (thanks to RazorLight) really simple:
Lets dig a bit deeper into this now.
The call to our service await _cardservice.RenderCard(templateKey, template, data); has 3 parameters and is working like usually when using the library made by Todd Adams.With one clear difference. The library was written for Razor HTML templates…..we’re not even remotely talking about that here 🙂
So what we’re actually passing to RazorLight is this:
templateKey -> usually the lastChangeDate of our template file flat as ddMMYYmmss.
RazorLight is caching templates based on the key, so as long as the file does not changed its cached and when the file is changed the cache gets updated. Simple.
template -> our actual JSON template, more on this later
data -> actual object with data we want to render, taken from our example this is the Status object containing the status update and the person information
Based on that, our full implementation of the actual Adaptive Card looks like that now:
As you can see we’re using the JSON template as if it was a normal HTML template. We can do everything we can possibly do in razor just in JSON.
If you need more complexity..no problem..this is more than possible:
Lets do some testing
So…to proof my theory of templates being faster we obviously need to run some tests. That said, I built a small ASPCore service with two endpoints “getGenerated” and “getTemplate” (you can see the actual code here)
After that I’ve built a really small net core console app that did nothing but calling the endpoints 20.000 times in a loop while messuring the time.
Here’s the results:
These are just 20.000 iterations so a pretty small sample size but you can already see the templates being a lot faster. The first iteration is slower on the templates as the first call to the RazorLight engine is not cached and thus taking longer to execute.
On just 20.000 iterations, the template way is already 9 seconds faster!
Working with third party api’s like that and especially with more complex schemes like the one needed for AdaptiveCards, makes things a lot more fun and opens a ton of possible things you can do. We can use the AdaptiveCard builder and just copy and paste our code 1:1 without changes needed. This cuts down development time a lot!!
Also, usually when you want to change a payload or when you want to change the layout of your AdaptiveCard or pretty much any JSON payload you sent, you’d probably need to recompile your code, submit data to Github have it built and all that. Takes quite a while, not easy and by far simple. What we can do with our implementation is a lot more flexible. We can store our templates as files but the JSON templates can also be loaded from a database. (We actually store our payloads in the database, so we can change our Adaptive Cards on the fly without recompilation needed!).
When you combine that with templates stored in the database you can easily change your payloads, change the look of an adaptive card and do not need to rebuilt anything. Just update the template or the file whatever approach you prefer.
On the tech side of things you have a lot less objects created, garbage collection is less busy, no more serializing tons of classes.
The API speaks JSON….just working in JSON suddenly makes things a lot easier
Let me know what you think, would love to hear some feedback!