Which is better: ASP.NET Core or Node.JS? (Based on Experience)
Experience on working with ASP.Net (Core) and Node.JS
I’ve been victimization the ASP.Net stack for five years currently, each professionally as a backend developer and designer, and in person for open and closed-source aspect comes. I do largely net applications however additionally work with massive information stacks.
After some years of tinkering with the PHP system, and an inexpensive quantity of your time spent doing Java, the C# language appealed to Pine Tree State for each its effectiveness and its pleasantness to figure with. it’s consistent, totally designed, and Visual Studio is to Pine Tree State the foremost developer-friendly IDE (when operating with C#). Moreover, the ASP.Net framework contains everything a developer has to develop ASP.NET applications while not requiring further frameworks or libraries.
The only problems with the ASP.Net system to Pine Tree State were of the moral matter: the language and framework were closed-source, and also the system was terribly Microsoft-oriented (even tho’ Mono provided a pleasant various to run on UNIX operating system, however with a relentless gap in supported features).
That’s why, when Node.js began to get traction within the early 2013’s, I couldn’t facilitate however have a glance, albeit my colleagues unbroken trashing JavaScript as a dysfunctional language and Node.js as a buzz. I used to be excited with learning concerning the single-threaded request system, I enjoyed victimization ExpressJS to form REST Apis simply and really quick.
Then Microsoft declared the ASP.Net Core, that carried hopes of natively cross-platform and ASCII text file ASP.Net surroundings. That’s once I begin to travel back and forth between the 2 technologies for cross-platform backend development.
What follows area unit my insights on the variations between the 2 platforms in terms of the event surroundings and options. I gathered these items of knowledge when a few years of victimization these tools, and that they facilitate Pine Tree State to settle on the most effective tool for the task once I begin a brand new project. Hopefully, they’ll assist you therein consider well.
Request handling model
- The Node.js model
Node.js is famously known for its single-threaded callback handler. What does that mean? It means that instead of handling every new HTTP request inside a dedicated thread or process (like Apache does), it does it inside a single thread.
That makes the request handling in Nodejs single-threaded, whereas in Apache/PHP it is multi-threaded for instance. But Node.js takes advantages of that because it uses asynchronous system IO calls that does not block the request thread. When an IO call is made by the request thread, the IO call is executed on its own thread, and the request thread keeps going. When the IO call is done, a callback is fired on the request thread to handle the response.
This makes Node.js well-suited for IO bound applications, but also introduces the so-called “callback hell”, which can introduce cyclomatic complexity to your code. Hopefully, since v7.6, Node.js implements native support for async/await of promises which makes your code far more readable and maintainable.
The single-thread request handling can be clustered using Node.js native clustering, Nginx load-balancing with multiple application processes, or Node.js process managers such as PM2, which makes use of all the server cores to start up as many application processes as the CPU can handle.
- The old ASP.Net way (synchronous)
Historically, ASP.Net MVC (or WebApi) handles requests the traditional way, which is the Apache / PHP way: each request is processed through its own thread inside a thread pool. And each IO call is then processed synchronously inside that thread.
This makes the synchronous ASP.Net model less suitable than Node.js for IO bound applications, which is most of the modern applications front side.
Hopefully, since ASP.Net Framework 4.5 (08/12), C# makes use of the async/await pattern, which introduces asynchronous programming for request handling.
- The new ASP.Net way (asynchronous)
The async/await pattern introduces asynchronous programming for request handling. Indeed, each request handlers can be tagged as asynchronous, and IO calls can be awaited, which means every request will run on its own thread, and each IO call inside the request handling will be non-blocking.
This Task-based model can make use of callbacks, promise, or async/await programming models.
ASP.Net Core advocates the use of the async/ await pattern when writing IO bound web applications.
- Node.js async/await VS ASP.Net Core async/await
Node.js code for asynchronous database query :
const express = require(’express’)
const app = express()
const MongoClient = require(’mongodb’).MongoClient
const url = 'mongodb://localhost:27017/example'
app.get('/', async (req, res) => {
const db = MongoClient.connect(url);
const col = db.collection('data'); const results = await col.find({}).toArray();
res.json(results); })
The equivalent ASP.Net Core code (without boilerplate startup code):
using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; using System.Linq; using MongoDB.Driver;
namespace TodoApi.Controllers { [Route("api/[controller]")] public class TodoController : Controller { [HttpGet] public async Task<IHttpActionResult> GetAll() { var client = new MongoClient("mongodb://localhost:27017"); var database = client.GetDatabase("example"); var collection = database.GetCollection<BsonDocument>("data"); return Ok(await collection.Find(new BsonDocument()).ToListAsync()); } } }
The difference between the two process model is that on the highly concurrent environment, ASP.Net Core will handle more requests because requests are handled in parallel. Although the context switching between threads can have its cost when using a lot of thread-shared variables. In that situation, Node.js could be faster.
Many “mainstream” modern languages such as C# implements some sort of asynchronous IO mechanism, which is often misunderstood by the Node.js developer community and can generate an unexpected outcome.
Programing language
- Features and safety
Coming from a C# background means that I’ve been exposed to a lot of criticisms regarding Javascript dynamic typings and surprising boolean conversions. Must of these criticisms still lay on solid grounds, considering that JavaScript built in 10 days as a “glue” language to bring dynamic features to HTML pages.
On the other hand, the language has evolved a lot since then, and the new specifications for JavaScript (ES6/7), for which most of the key features are implemented in Node.js, brings a lot to the table, such as:
- Classes
- New identifiers (const, let) that increases code safety
- Arrow functions
- String interpolation
- Generators
- Object exploration (which looks like C# reflection features)
C# is far more powerful I think because it makes use of all the benefits of having a strongly-typed object-oriented programing language. The Visual Studio IDE is quite something and provides the best integration for a language (at least that’s what I think).
But for a large majority of cases, and with the growing popularity of the micro-services pattern, a lot of these awesome features are not necessary for small to medium code bases.
- Learning curve
Coming from classic MVC frameworks, the Node.js / Express combo take some time to get used to, as the new middleware-pattern can be new to some developers. The event-driven paradigm is also specific to Node.js and can take time to digest completely. Everything else in the language is quite straightforward as it is simple Javascript.
What can be complicated at first when working on a medium to the large application is the patterns to use for code refactoring and code architecture. Since the Node.js frameworks such as Express.js are very flexible, choosing the right architecture and file structure can be cumbersome, but a must-have to enhance evolutivity and maintainability of your application.
The ASP.Net (Core) MVC / WebApi framework provides the developer with an already made code structure, dependency management, and code architecture. The developer still has some code-organization to make such as separating the database layer from the web one, but overall far-less time is needed to think of that. Developers used to POO paradigms will feel at ease rapidly.
For simpler web apps such as light REST APIs, the Expressjs/Node.js is very straightforward and easier to start with as the boilerplate template is only one small js file and a package.json file.
- Prolificacy
I found that writing simple code is a bit faster for me in Node.js than in C#. To me, that is because most simple applications (REST APIs, console application, helpers, …) take advantage of having more flexibility, as you are not designing a lot of the app ahead of development.
More and more studies question the relevancy of static typing to reduce the number of bugs in an application. If such studies happen to hold some truth, then using a strongly-typed language can be more of a drawback than a benefit.
On the other hand, I’ve found that large code bases tend to be far more readable when working with C# than with JavaScript. To me, that mainly comes from the fact that strong OOP paradigms, promoted by the C# patterns, enhance cohesion and decoupling of the code.
Regarding debugging and Unit testing, the C# / Visual Studio combo still provides the best experience, but the Node.js / Visual Studio Code with extensions are not lagging far behind. The building time is also smaller for a Node.js application.
The ecosystem
That is the aspect where the two technologies differ the most. Node.js relies on a very large community writing a lot of modules in its main package management system (NPM). Most of the popular frameworks and libraries rely on a lot of small packages to work.
This provides new developers with a lot of available modules to respond to the always-shrinking development time. But it can also have side-effects on the entire ecosystem when a package is updated or pulled off. A lot of these packages are also not well maintained and error-prone.
The ASP.Net Core framework, on the other hand, is developed by a dedicated Microsoft team entirely, and provide everything you need to build a fully functional website. Third-party packages are often well built and backed by large companies.
One good example is the field of ORM (Object-relational mapping) tools. Entity Framework, the official ORM for ASP.Net, offers a full set of features such as code-first database modeling, auto-generated migrations, and support for the main engines. Node.js is lacking behind with very few ORMs available and far fewer features supported. Sequelize is getting closer to it though…
This might come from the historic affinity of Node.js with MongoDB and the MEAN stack. MongoDB being a NoSQL flexible JSON data store, a full-featured ORM has no meaning with it.
Deploy & Run
This is the area where Node.js really shines. Node.js is open source, cross-platform, docker-ready and most PaaS compatible. This means you can host your code fast and easy on the following platforms:
- Your own Linux, Windows or Mac server. You just need a node engine running and a reverse-proxy (Nginx is the most popular and really fast)
- A Docker container: there is an official docker image (23Mo for the Alpine-based image)
- Most PaaS cloud providers (AWS, Google App Engine, Azure, Heroku, …). These offer you everything you need to host your app to let you focus on the development
- There is also Now, which offers a one-liner for Node.js deployment with no configuration.
There is also a lot of CI&CD platform that can build, test and deploy your Node.js code with ease (Travis, Codeship, Circle CI).
ASP.Net, on the other hand, is a bit harder to handle in terms of deploy & run. Although the ASP.Net Core framework is cross-platform, there is not yet the same amount of self-hosted and cloud tools for CI, CD, and hosting. At the current time here are the hosting platforms known to me:
- Your own Windows Server with IIS for ASP.Net classic applications
- Your own Linux server (main distributions) with a reverse proxy: this is getting better for ASP.Net core but the package is still very large and updates are not always handled nicely (for .Net core 1.x at least)
- A Docker container on Windows (ASP.Net classic and Core) or Linux (ASP.Net Core only): this works nice, but is still quite heavy (120Mo for the latest ASP.net Core Linux image)
- Some PaaS cloud providers: mostly Azure, but some unofficial build packs exist on Heroku
For CI & CD, I only know of Visual Studio Team Services that do that in the cloud.
Conclusion
- The Node.js asynchronous event-driven request handling model is not that far from the ASP.Net async/await multi-threaded one.
- Node.js performances are not always better than ASP.Net Core ones. They even tend to be worse, even though the difference might not matter for common apps. CPU-bound apps will generate bottlenecks.
- The JavaScript language is not that bad (getting better !), and combined with Node.js, can lead to fast development cycles.
- ASP.Net (Core) is mostly preferred for large code-base as it provides ready-made software architecture and tooling that fits most needs.
- For micro-services or small to medium-sized REST APIs, Node.js provides a nice alternative for lean development with many hosting and CI&CD services available.
- As always, there is not a better tool for each scenario, try and pick the one that fits your requirements.
Looking for ASP.NET Core hosting?
While choosing a new web host, make sure you don’t make the same common mistakes that most beginners do. A few of my favorite web hosts are ASPHostPortal, HostForLIFE, UKWindowsHostASP.NET. I recently reviewed ASPHostPortal and in my opinion, they’re the best-shared host out there out of the large lot of hosts I’ve tested. If you’re curious as to why I never had to switch to another host since 2014, give my ASPHostPortal review a read.
A great place to look for a new web host is WebHostingTalk. Their members are very helpful and new members get proper guidance on choosing a web host.