Click here to Skip to main content
15,884,836 members
Articles / All Topics

Node.js Meets .NET – Edge.js

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
6 Jan 2015CPOL4 min read 24.3K   12   1
Node.js Meets .NET – Edge.js

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

C#
var edge = require('edge');

var add = edge.func(
    {
        source: function() {/*
            async (dynamic input) =>
	     {
	         return (int)input.a + (int)input.b;
	     }
	  */},
	  references: ["System.Linq.dll"]
    });

add({ a: 5, b: 10}, function (error, result) {
	console.log(result);
});

Startup Class With Invoke Method

C#
var edge = require('edge');

var add = edge.func(
    {
        source: function() {/*
            using System.Threading.Tasks;

            public class Startup
            {
                public async Task<object> Invoke(dynamic input)</object>
                {
                    int a = (int)input.a;
                    int b = (int)input.b;
                    return MathHelper.Add(a, b);
                }
            }

            static class MathHelper
            {
                public static int Add(int a, int b)
                {
                    return a + b;
                }
            }
        */},
        references: ["System.Linq.dll"]
    });

add({ a: 5, b: 10}, function (error, result) {
    console.log(result);
});

Asynchronous vs. Synchronous Execution

C#
// asynchronous execution with a callback
add({a: 10, b:20 }, function(error, result) {
});

// synchronous execution with a return value
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.

C#
var edge = require('edge');

var submitOrder = edge.func({
    source: function() {/*
        using System.Threading.Tasks;
        using System.Collections.Generic;

        public class Order
        {
            public string orderNumber { get; set; }
            public int customerId { get; set; }
            public double total { get; set; }
            public List<OrderItem> items { get; set; }
        }

        public class OrderItem
        {
            public string name { get; set; }
            public double price { get; set; }
            public int quantity { get; set; }
        }

        public class Startup
        {
            public async Task<object> Invoke(dynamic input)
            {
                // returning the async function here
                // allows the .NET code to run on a
                // separate thread that doesn't block Node.js
                return await Task.Run<object>(async () => {

                    var order = new Order
                    {
                        orderNumber = System.DateTime.Now.Ticks.ToString(),
                        customerId = (int)input.customerId,
                        items = new List<OrderItem>()
                    };

                    dynamic [] items = input.items;
                    foreach (var item in items)
                    {
                        var orderItem = new OrderItem
                        {
                            name = (string)item.name,
                            price = (double)item.price,
                            quantity = (int)item.quantity
                        };

                        order.items.Add(orderItem);
                        order.total += orderItem.price;
                    }

                    // ... invoke legacy code to save order here

                    return order;
                });
            }
        }
    */},
    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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Keyhole Software
United States United States
Keyhole is a software development and consulting firm with a tight-knit technical team. We work primarily with Java, .NET, and Mobile technologies, specializing in application development. We love the challenge that comes in consulting and blog often regarding some of the technical situations and technologies we face. Kansas City, St. Louis and Chicago.
This is a Organisation

3 members

Comments and Discussions

 
GeneralMy vote of 5 Pin
Krys Everydev8-Jan-15 12:12
Krys Everydev8-Jan-15 12:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.