With so much JavaScript development on the client side, it only makes sense that developers and organizations would want to develop server side applications using JavaScript as well. Node.js has become a popular choice for building server side applications using JavaScript because of its asynchronous event-driven model and many libraries and extensions that are available.
But sometimes, JavaScript is not the best choice for what you need to do, even in a Node.js application.
There is a package for Node.js that allows you to invoke .NET code in-process from a Node.js application – Edge.js.
Edge.js is supported on Windows, Linux and OS X with .NET Framework 4.5 or Mono 3.4.0. Edge.js works with a variety of .NET languages including C#, F#, IronPython and LISP. It also works with T-SQL and Windows PowerShell. It was created by Tomasz Janczuk.
Here are some reasons for using .NET with Node.js:
- Integrating/reusing existing .NET components
- Accessing a SQL Server database using ADO.NET
- Using CLR threading for CPU intensive processing
- Writing native extensions to Node.js using a .NET language instead of C/C++.
- Use your imagination… you’ll come up with something
Installation is easy, just use the node package manager to run the command:
npm install edge
This installs the core Edge.js module with support for C#. Additional Edge.js modules are required for other languages:
- T-SQL: edge-sql
- F#: edge-fs
- LISP: edge-lsharp
- Windows Powershell: edge-ps
- IronPython: edge-py
Functions
The first thing you will probably want to do is create a JavaScript proxy to some C# code. In Edge.js, functions in C# are defined as Func <object, task<object>>
where the first parameter is the input and the second parameter is the callback function. The edge.func()
function will create the JavaScript proxy to your C# code that can be executed synchronously or asynchronously from your Node.js code.
I’ll show how to do this with C# code inline with JavaScript, using a multi-line lamdba expression and a Startup
class with an Invoke
method. The downside of these methods are that you are writing code inside the comment block, so you don’t get the benefits of intellisense and syntax checking. You can also reference a pre-compiled assembly or C# in a separate file. Both examples below show a reference to the Linq assembly but you can reference any external assemblies you need.
Multi-line Lambda
var edge = require('edge');
var add = edge.func(
{
source: function() {},
references: ["System.Linq.dll"]
});
add({ a: 5, b: 10}, function (error, result) {
console.log(result);
});
Startup Class With Invoke Method
var edge = require('edge');
var add = edge.func(
{
source: function() {},
references: ["System.Linq.dll"]
});
add({ a: 5, b: 10}, function (error, result) {
console.log(result);
});
Asynchronous vs. Synchronous Execution
add({a: 10, b:20 }, function(error, result) {
});
var result = add({a: 10, b:20 }, true)
Data Marshalling
Edge.js can marshal any JSON data between Node.js and .NET. JavaScript objects are represented as dynamics in .NET that can be cast to an IDictionary<string, object>
. Arrays in JavaScript become object arrays in .NET. For binary data, a Node Buffer will get translated into a .NET byte array. When marshalling data from .NET back to Node.js, classes and anonymous types that are JSON serializable will both get converted to JavaScript objects. Be careful to avoid circular references in your object graphs as these will most likely result in a stack overflow.
This example shows how you might pass data to a legacy component that would save an order. The Invoke
method also returns an asynchronous function so the .NET code will run on a separate thread and not block Node.js.
var edge = require('edge');
var submitOrder = edge.func({
source: function() {},
references: ["System.Collections.dll"]
});
var order = {
customerId: 1001,
items: [
{ name: 'XBox One Console', price: 329.95, quantity: 1 },
{ name: 'Madden NFL 15', price: 49.95, quantity: 1}
]
};
submitOrder(order, function (error, result) {
if (error)
console.log(error);
else
console.log(result);
});
On Windows, you can debug .NET code in your Node.js applications. To debug C# code from a Node.js application, you first need to set the environment variable EDGE_CS_DEBUG=1
. After starting node.exe, you simply attach your .NET managed code debugger to the node.exe process.
Should you have a need to script Node.js code from a .NET app, there is also an Edge.js NuGet package that enables this.
Final Thoughts
As you can see, there is a lot of flexibility with using Edge.js as an interop layer between Node.js and .NET. If you are building Node.js apps and have existing .NET code you want to reuse (or find something you think would just be a lot easier/quicker to code in .NET than JavaScript), you probably want to give Edge.js a try.
For more information and examples, see https://github.com/tjanczuk/edge/ and http://tjanczuk.github.io/edge
— Brian Wetzel, asktheteam@keyholesoftware.com