Moving from Node.js to .NET Core

Jim Wang

Here on Visual Studio App Center, our platform is built as a set of microservices, which has afforded teams to make language and platform choices that work best for them, and ultimately allowed us to move and iterate quickly. Over time, two distinct stacks have emerged: 

  • TypeScript/JavaScript running on Node.js, deployed to AKS (Azure Kubnernetes Service) 
  • .NET Framework (C#) running on Windows Service Fabric 

As we have continued to merge our teams and do more and more cross-team work, it’s become apparent that we should settle on a single choice and unify so that jumping between services is less jarring. The fact that a lot of our customers run non-Windows platforms, and our team runs a mix of Mac, PC, and Linux, led us to explore a new direction. 

Enter .NET Core 

We started investigating .NET Core as a solution because of the cross-platform abilities it offered, and the fact that it works great with VS Code, our cross-platform development solution. We felt like .NET Core allowed us to preserve this flexibility, but not continue diverging our code base, with some new services written in TypeScript, and others in C# on the .NET Framework. This allows us more flexibility when moving work between teams as well. We could have also gone with TypeScript but given the skill set of the majority of the team (C#) and the pain we have seen managing Node.js dependencies, we decided on .NET Core. We’ll discuss the dependency issue in more detail later in this post. For more information on .NET Core, see the docs. 

Our goal with this post isn’t to convince you that .NET Core is better than Node.js: we made our decision primarily based on the skill sets of our teamInstead, we want to share the things that we noticed as we have been starting the porting work, in the hope that if you’re embarking on a similar journey, this information will be helpful. If you’re curious about direct comparisons regarding performance, this site is a good resource that is constantly updated. The .NET Core entry on that list is called aspcoreAnother interesting post exploressaturating 10GbE at 7+ million request/s using .NET Core.  

Also, note that for the purposes of this post we aren’t looking at specific TypeScript features, and on our team, we continue to use TypeScript for new front-end development as there are many benefits to having concrete types on top of JavaScript. 

The Challenge 

We are not embarking on a re-write of all services, but aside from having all new services run on .NET Core targeting AKS, we are looking for opportunities to port over problematic code from either the .NET Framework or Node.js. In this blog post we’ll talk about going from Node.js to .NET Core, by exploring some key differences we noticed as we ported some targeted REST API endpoints. For our take-aways, we are mainly focused on the developer experience, and not necessarily on performance benchmarks or other orthogonal concerns. 

Key Take-Aways We Noticed 

Porting code into a strongly typed language takes time 

In our existing TypeScript code base, we take advantage of dynamic types frequently, and in the C# version of the code we had to define more concrete types. Additionally, the code that we were porting specifically dealt with bit masks, so translating those concepts between JavaScript and C# presented some pain for us. One of the main things we lost was easy parsing of JSON and dynamic object graphs. .NET Core includes JSON parsing out of the box, but it isn’t quite as native as what JavaScript provides. 

Another thing that came up was the need to create more mapping types instead of relying on dynamic mapping, which we didn’t have to handle as much since we were already in TypeScript, but if you are coming from a straight JavaScript project this is something else you will want to consider. 

All in all, if you embark on this journey, be prepared to invest the appropriate amount of time on model classes and other scaffolding that you will need for a successful transition. 

String comparison differences 

In JavaScript, when doing case insensitive string comparisons, we tend towards doing toLowerCase()  prior to doing a ===, where we don’t care about case. Generally speaking, the equivalent C# code uses string.Equals  and passes in a StringComparison enum value to indicate how to handle issues of case sensitivity. A common case is scenarios where you do not care about case and locale, and for those you should use StringComparison.OrdinalIgnoreCase. Here are some useful references for other scenarios that may arise: 

A concrete example of porting where both examples return success under the same conditions: 

JavaScript:

var desiredValue = 'someValue'; 

if (envVar && envVar.toLowerCase() === desiredValue.toLowerCase()) { 

  console.log('Success!'); 


}

Equivalent C#:

var desiredValue = "someValue"; 

if (string.Equals(envVar, desiredValue, StringComparison.OrdinalIgnoreCase)) { 

  Console.WriteLine("Success"); 

}

 

Fewer dependencies in .NET Core 

One thing that has been nice is to manage fewer dependencies (and a shallower dependency tree) in the .NET Core version of the code, and hopefully this means it will be easier to maintain. We have struggled with keeping dependencies up to date and managing many dependencies in our Node.js projects. Additionally, developers on our team prefer NuGet’s policy of “lowest matching version” rather than npm’s encouragement to use “highest matching patch” or “highest matching minor version” (using the ~syntax in package.json by default via npm i). We recognize this is a philosophical difference and opinions on this may vary. The pros of the NuGet approach are more control and explicitness, whereas the npm approach allows for theoretically non-breaking changes to be easily applied. 

Other Thoughts 

There isn’t one right answer, and the purpose of this post isn’t to convince you one way or another, just to shed some light on the process we have gone through recently as a team. As we discover and do more in .NET Core on AKS we will be sure to share along the way! 

16 comments

Discussion is closed. Login to edit/delete existing comments.

  • Cyril Dumange 0

    Don’t know if I would have chosen the same.
    But one think make me tick. The easyness dev in netcore using VS Code. I tried it for a few days and I remember wanted to kill the c# extension that was regulary crasing. Do you have any interesting ressources on creating a stable c# dev env using vsCode ?

    • Jim WangMicrosoft employee 0

      What operating system were you on at the time? There have been issues with OmniSharp but I believe things are much better now than they used to be.

    • Richard Collette 0

      Forget VSCode.  Spend a few measly bucks and use Rider.  Stable.  Great refactoring.  “Code cleanup” could use speed improvement but it still does so way better than VS or VS Code.  I can get far closer to StyleCop “compliance” using Rider.  Microsoft should have bought that product out for MacOS the same way Google adopted IntelliJ for Android (Android Studio).As a script editor.  VSCode works fine.  As a full-on IDE for multi-file, multi-project editing, it has a way to go.  It’s odd to me that C# editing was outsourced to Omni-Sharp.   Makes no sense other than they couldn’t bear to compete with themselves (w/ VS).

  • Mike-E 0

    Great to hear that MSFT is abandoning its silly TypeScript/JavaScript fascination and finally recognizing where the real code is at with .NET Core.  We’ll have a laugh about this unfortunate and embarrassing chapter in MSFT history at some point, I am sure.

    • Chris Threatt 0

      Michael, Microsoft is not abandoning TypeScript, which has gained widespread adoption in the industry.  This post is about one team replacing a node.js backend with a .NET Core backend.
      SPAs running on modern JavaScript frameworks like Angular and React will continue to dominate client side development.  A fact that Microsoft has embraced.  The dotnet CLI tool has generators for both Angular and React.

      • Mike-E 0

        Spoken as if you are defending the next Silverlight, which as it turns out: you are.

      • Mike-E 0

        (Administrators: fix your broken blog software.  It appears that a comment I edited is no longer displaying, even though it is in my history.  The laughable irony of a software giant who cannot even implement the most basic of blogging fundamentals — from WordPress, no less!)

    • PandaSharp 0

      kind of agree this new JS (webapps and fraweworks) trend is a mess, at least with typescript is a bit better… but still not comparable to c# and .Net

      • Mike-E 0

        Right… while MSFT might not be giving up on TypeScript as an external product, the internal tide has clearly shifted internally, where managers and team members alike are now recognizing the sheer cost involved of developing and managing two codebases that cannot leverage the encapsulated knowledge afforded between the two.  What, you don’t like to write things once in each language?  What, don’t you like to fix twice the amount of bugs, each with their own challenges and idiosyncrasies derived from each system?  We thought you liked to code!

    • Richard Collette 0

      Typescript absolutely has a place in the browser.  Buy yeah, core blows away Node on the server.

      • Mike-E 0

        Heh heh, part of the undertone here is that MSFT could have done the innovative (like that have been recently with Blazor) and continued Silverlight in the browser by transpiling .NET into JavaScript rather than accommodating JavaScript with a brand new construct altogether — this introduced confusion and was EXPENSIVE.  With Silverlight, you were 100% .NET, so you became an expert in .NET.  If you introduce JavaScript (or any other non-.NET language), you become a generalist in .NET and not an expert, which means lower quality software and resulting solutions — which ultimately impacts a company’s bottom line.  IMO true innovation occurs at expert quality, not generalist quality.

  • Tony Henrique 0

    This is very cool!When .NET 5 arrive, I think that the tendency is that more code will be written in .NET and also use some cross-platform Universal XAML that will run on Web, Mobile, Desktop and IoT.In my opinion, F# can absorb some JS philosophy: F# can evolve to be used with a complete dynamic, and also a strong typed model. Some steps indicate this, like the cool new F# Anonymous Record. Doing this, F# will be easy choice for javaScript and C# developers.

  • Greg Veres 0

    I have been doing .Net (not core) with typescript on the front end for a few years now. You mentioned having more model classes. I assume you mean to handle the transition of data from the C# back end to the TS front end (or maybe between microservices). I have found using Typewriter with the appropriate template files provides an excellent way to create those mode classes in C# and have them available in TS. (https://frhagn.github.io/Typewriter/).
    I use an attribute on the classes I want to show up in TS and as soon as I save the C# file, the TS file is generated for me. It is a huge time saver and prevents so many “out of sync” errors!

  • Musfiq Fahad Amin 0

    More maintainability as less dependancy, more control as more explicit package manager, drastic performance improvements and finally C#, one of the most well-designed languages out there. If these fulfill your project requirements and you’ve a competent team with enough time, why wouldn’t you migrate?!

  • Renato Fontes Tapia 0

    They are 2 completely different things. Why does this exist? 😂

Feedback usabilla icon