I’ve been building web applications forever. The first ones were more websites than web applications but you get the point. I’ve used Perl, PHP, ASP, ASP.NET, Node.JS and, ASP.NET Core in production and Node.JS has been the longest run. We recently decided to switch some of our new development to .NET Core and it looks like this decision will stick. I’ll try to explain why we are doing this and how we think about the process so far.

Note that this was not even an option a couple of years ago. We’ve been working exclusively on unix based platforms. We host stuff on Linux servers and have been doing development on macOS for more than 10 years at this point. I always loved C# and .NET in general but it was out of our reach due to being exclusively a Windows based technology.

.NET Core changes this. It is open source, multi platform and not in a sloppy way. It is properly a multi platform technology and I don’t feel like I’m missing anything working on macOS. This is fantastic news because as I just mentioned, I love C#!

But I digress, going back to the point;

Dependency Management

One of the pain points with Node.JS has always been dependency management for us. It is a universally accepted fact at this point is that node_modules become a bloated mess. Dependencies get out of control and become stale at some point.

Now, this has multiple reasons but one important reason is that Node.JS offers a really thin standard library. Pushing almost everything out into user space packages. And don’t get me wrong, Node has a fantastic repository of packages. It’s just a little too much for our liking.

Another issue with this is that Node.JS runs JavaScript and JS is not a strongly typed language. When you upgrade / modify a package version you have to check the changelogs, maybe sometimes the package code to see if there are any backward incompatible changes. The semver is a solid idea that rarely is reliable. While this still applies to .NET, there is an important difference, the strongly typed interfaces / types / methods make sure that you will catch any backward incompatible changes to those during compile time. I’ll talk about the strongly typed aspect a little more but this is the basic idea.

Contrary to node, .NET has an extensive standard library. It is huge and covers a lot of ground. Especially the ASP.NET base assemblies and the extensions together create a behemoth of functionality without any third party dependencies. These follow a clear versioning scheme and are easily upgradable (also, documented by Microsoft).

I just love being able to depend on the standard library of the platform itself instead of user code maintained by some poor, abused open source developers on the brink of collapse. This is a huge plus for .NET.

Specificity of experience

There might be a term for this but English is not my native language so I’m gonna need to explain what I mean.

Node.JS does not really force a lot of opinionated approaches. You generally have tons of options, modules and design patterns when you are faced with a problem. And it seems like everyone does things their way.

Say you need to access an RDBMS. Some will use a low level client and SQL strings. Some will use an ORM. A lot of people will invent an ORM / basic SQL hybrid worst-of-all solution. And even if you decide to use an ORM now you have a million options with different tradeoffs. Even if you go with SQL strings, there are a million ways to build SQL queries, each db client has its own API etc. This means that a developer with RDBMS experience on Node.JS can be anything and might not fit into your approach easily.

I know DB access is a solved problem at this point but I chose this because there is a nice contrast. .NET has direct SQL access obviously (I guess you can find MySQL libraries for Commodore 64 at this point so this should not be a surprise.). And there is Entity Framework Core. Now, I know there are other ORM solutions but the EF is the de facto standard and you can expect developers to know about it. You can migrate experience from one project to another, people will know how to access stuff, they will just need to learn about your data model.

Linq applies to all enumerables! Both remote (database tables etc) and local (arrays, lists..). It is beyond fantastic for someone who used things like underscore because the JS standard library does not even provide basic enumerable methods.

Performance

This is mostly one of the major points when people compare platforms so I have a section for Performance, just to say that it does not matter.

We’ve been building web applications, and most of the application time is spent on waiting for IO. Both Node and .NET performed great on our use cases so, whatever.

C#

We have been using TypeScript for our Node.JS development and haven’t used much bare JavaScript for years now. However, we never could commit completely to strict TypeScript due to a lack of typings or errors in typings for external dependencies. At some point, one or two any types creep into the code base and then it gets messed up quickly.

We still try to have decent type definitions for all our TypeScript code. However, it is at best a band-aid solution compared to a completely strongly typed language like C#. C# is mature and a fantastic language to work with. Also, the tooling is generally better.

I’ve been using Rider for development on macOS and it is top-notch.

Standard library

As I mentioned in the Dependency Management section, the standard library is a major plus for .NET. While it is great for decreasing third party dependencies, it also provides decent defaults to build things on.

For example, we never bothered with dependency injection in Node.JS, it is right there in the foundation of any ASP.NET Core application. Configuration management has been an issue on Node. There are a couple of modules doing different stuff and we never settled on a good solution. Again, create an ASP.NET Core application and you have the configuration management system right there, ready for action. The exact same thing applies to logging and testing and I guess many other aspects too.

Overall, .NET is a freaking giant when it comes to APIs available.

Random Bits

  • .NET builds are slow on my mac. For some reason a similarly specced windows machine can build projects much faster. This makes iteration slower than Node.JS. When built, apps run just as fast though.

  • VSCode extension for .NET is shit. I’ve been using Code for Node.JS development and it has been fine but it is not viable for .NET. You need to use a proper IDE like Rider. Fortunately Rider is pretty good.

  • You need to use NuGet a lot less as per the Dependency Management section, however it is not the best experience when you need to.

  • ASP.NET has a documentation problem because of all the versions it has seen, the .NET Framework WebForm versions are still in widespread use and a lot of documentation is written for that variant.

  • Some of the built in functionality can be a little overkill for simple applications (Like authorization.)

Conclusion

I’ll probably add more bits of information as we go along however so far we are pretty happy with the transition and I personally would not start another project in Node.JS in anytime soon. You should note that most of the advantages of .NET over Node.JS for us also pply to other platforms, such as Go. However we found .NET to be the most pleasant to work with and there is a huge talent pool, unlike Go.

I hope this article sheds some light on our decision for this transition. If you spot any mistakes or think that I’m an idiot, just drop an email.