Scott Hanselman

"It's just a software issue"- Edge.js brings Node and .NET together on three platforms

April 30, '14 Comments [44] Posted in Learning .NET | nodejs | Open Source
Sponsored By
.NET and node together on three platforms

There was an engineer I used to work with who always said "That's just a software issue." No matter how complex the issue, no matter how daunting, they were confident it could be solved with software.

.NET and C# and NuGet and the community have been making some amazing stuff in the last few years like ScriptCS, Chocolately, Boxstarter. Azure Websites now supports ASP.NET, sure, but also PHP, Python, Java (Tomcat or Jetty or your own container), and node.js. Getting these things to work together has been an interesting software issue. Apps can run side-by-side, but they can't really talk to each other in-process. (Mostly one just moves data between universes over JSON and HTTP when need-be.)

However, Tomasz Janczuk has been working on Edge.js (on Github) for a while now. I showed his work at jQuery Portland last year, but this week he's taking it to the next level. He is creating a wormhole between software universes.

Edge.js now lets you run node.js and .NET code in-process on Windows, Mac, and Linux.

The name is great. An edge connects two nodes, and Edge.js is that edge.

node and .NET connected by edge.js

Here's a node app hello world node app calling .NET. Don't sweat that the .NET code is tunneled inside a comment, this is the Hello World proof of concept.

var edge = require('edge');

var helloWorld = edge.func(function () {/*
async (input) => {
return ".NET Welcomes " + input.ToString();
}
*/});

helloWorld('JavaScript', function (error, result) {
if (error) throw error;
console.log(result);
});

Perhaps you have a bunch of CPU intensive work or algorithms in C#, but you've also got a node.js app that needs the result of that work. Edge can help with that.

You can bring in a CS or CSX file into node like this:

var myCSharpCode = edge.func(require('path').join(__dirname, 'myCSharpCode.csx'));

You can bring code from a .NET DLL into a node.js compiled as well.

var clrMethod = edge.func({
assemblyFile: 'My.Edge.Samples.dll',
typeName: 'Samples.FooBar.MyType',
methodName: 'MyMethod'
});

It's not a hack, it's a clear way to marshal between CLR threads and the V8 (the node Javascript engine) thread. It's also interesting from a comp-sci perspective as the CLR can have many threads and V8 has the one.

nodecsharp

Here's Tomasz's own words:

Edge.js provides an asynchronous, in-process mechanism for interoperability between Node.js and .NET.

You can use this mechanism to:

  • access MS SQL from Node.js using ADO.NET more...
  • use CLR multi-threading from Node.js for CPU intensive work more...
  • write native extensions to Node.js in C# instead of C/C++
  • intergate existing .NET components into Node.js applications

Read more about the background and motivations of the project here.

Now, you might ask yourself, what problem does Edge.js solve? The answer is in the Edge.js FAQ.

Go explore what you can do. Edge goes much further than just C# and Node. It works on Windows, OSX, and Ubuntu but you should just "npm install edge" as there's a node package available.

Have fun! You have a lot more power and flexibility than you think. It's just a software problem.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by ORCS Web
Wednesday, April 30, 2014 8:58:49 PM UTC
Aside the little spelling issues: Great post! (Hit "Save Comment" too fast... my bad)
Wednesday, April 30, 2014 10:41:00 PM UTC
Very interesting! I'm still amazed at how much Javascript is taking over. It's everywhere now.
Thursday, May 01, 2014 12:15:50 AM UTC
It's really good to see Node working better every day on Windows. Amazing project.
Thursday, May 01, 2014 1:17:24 AM UTC
Nice informative post as always! I noticed a typo. Shouldn't it be Chocolatey instead of Chocolately?
Thursday, May 01, 2014 12:06:00 PM UTC
I wonder where is the border between fancy projects making lots of noise around it to show how wonderful (lightning-fast, super-efficient, etc.) it is, and projects doing its job in 1000 lines of code less?

Who, in commercial projects, is mixing unix and windows technologies? Some geeks to show others how cool they are, they managed to write another 'hello world' app?

Sorry guys, but honestly I do not buy it. Ok. It is nice of Scott to tell people such technology exists, but for me, a guy being part of programmers team, it is a nightmare sometimes, to find the needle in tons of lines of code used in a hundreds of flavours. I think the pressure of using new techniques is driving towards massive spaghetti code, while in most cases technology could be simple and effective.
Igor
Thursday, May 01, 2014 1:19:34 PM UTC
hopefully to see soon some good IDE for javascript just like the one C# has , so that coding in java become more appealing, for me I still prefer to code in C# because it has a better IDE and you dont have to jump from debugger to debugger to find errors .
Sam
Thursday, May 01, 2014 2:44:03 PM UTC
This is very cool! Node.js excels in moving data around, but doesn't seem like the best tool for intensive computation. Putting .NET and Node together could make a good one-two punch.
Thursday, May 01, 2014 3:38:29 PM UTC
@Igor: ". I think the pressure of using new techniques is driving towards massive spaghetti code, while in most cases technology could be simple and effective."

OK. So you have node, which is capable of serving HTTP Requests with *just a few lines of code*. And now you can use edge to let that HTTP server also execute in-process C# code *with just a simple function call*

How is this complex? It's about as simple as it gets - the edge author has done all of the hard work for you already...and as he tweeted - now it's not "Node vs .NET", it's "Node AND .Net" :)

Perhaps we can't think of a specific practical use right off the top of our heads, but for example imagine someone who has a core library of business logic built in C# that drives an ASP.NET WEB API app, but now they want to switch away from IIS/ASP.NET and use Node (for whatever reason)....suddenly they don't have to rewrite their application core any more. Which is nice.
Stephen
Thursday, May 01, 2014 4:03:23 PM UTC
@Stephen, @Igor - Your group is going to be developing a nodejs application. Unfortunately you either have 1) open source c# code 2) legacy c# code that you just don't have time/interest/understanding to redo in javascript.

And if the Mono/.NET stack is handling the more intensive math, that negates one of the drawbacks of Node, doesn't it? That would be another benefit.

The only real drawback I see, if you're .NET > all, is that it lowers the barrier to entry for migrating off the .NET stack to the NodeJS one (or at least, outside of the intensive bit mentioned before). Microsoft has apparently taken a stance of caring less about the means to the end (the language/platform used) vs trying to lock down developers to the .NET stack as before (they do, however, support and enhance the stack, so I'm not trying to pull a 'Microsoft abandoning .NET' FUD statement here). No, this isn't a Microsoft project, but from what I've seen in the past couple years Microsoft would embrace this, not attempt to shut it down/condemn it/break it/whatever.

I think when younger developers (primarily) are more interested in developing things in a specific way that also deviates quite a bit from the traditional way of the MS stack, that Microsoft is doing things right. You want .NET? Cool, from end to end they'll support you there. You want to do PHP/NodeJS/etc.? They can help you there too. You want to do Java? Please keep it off the desktop (my personal request. Refuse to install that on a desktop again. Which has kind of gimped my ability to do Android development with Android Studio/Eclipse, but collateral damage exists), but from a server aspect they've got you covered there too.
Robert
Thursday, May 01, 2014 4:04:28 PM UTC
perhaps intensive math would be better stated as intensive work, but eh, no edit ability, it is cool.
Robert
Thursday, May 01, 2014 4:20:44 PM UTC
It would be cool if it could expose the node request to .NET as an IDictionary<string, object> with properties filled per the OWIN spec.
Thursday, May 01, 2014 5:25:57 PM UTC
I've been using this in my dev project. We use it to enable grunt tasks to be able to do things otherwise "impossible".


  • Items like query/write to SQL Server
  • Read/Write XLS/XLSX files
  • Parse JSON without crashing all the time (using JSON.NET, instead of the garbage JSON parser inside V8)


Its allowed us to really leverage the best of both new tech being written in node.js as well as the powerful and very useful tech that is well developed and mature in .NET.
Cam Birch
Thursday, May 01, 2014 10:32:04 PM UTC
Wow, now imagine the mess you'll get when you do stuff like that in a real-world-project.
I am really sorry and I have a lot of respect for you, Scott, but why are you pushing stuff like that?

If you need to create a nodeJS-app with .NET-Features/Code, than first of all ask yourself what's the benefit. NodeJS becomes a big number, yes, but productive-wise it's far behind what you'll get from MVC/SignalR... Not to speak off the maintainability.

The second alternative would be to write a CLR-Module and inject it into your v8-instance. But don't write C# as comments in JS-files. This is really the stupidest thing I've seen in a long time and this comes from a person who had to review code from business engineers...
richard
Friday, May 02, 2014 2:40:00 AM UTC
Richard and Igor - Many many production apps uses both .NET and Linux solutions, banks, stackoverflow, raygun.io, and many more. Node as a light JSON webapi and edge, or grunt tasks are just the start.


Again, as I said in the post, the C# in a JavaScript comment tunneling is not what you want to use. Use an assembly. That said, Angular JS puts directives in comments and no one says boo.

If you guys think I'm "pushing" bad solutions, I would respectfully ask you to read closer and consider the increasing number of true polyglot solutions in the real world. Most significant apps are hybrids.
Scott Hanselman
Friday, May 02, 2014 2:45:05 AM UTC
Brilliant combination. Fixes one of the biggest issues I have with node (the whole 'threading is bad' manifesto only takes you so far).

To those saying "what's the point, meat man?" The point is to let people work in the tools they're familiar with, but with the smallest possible gap between integration -- can you go stand up a remote server to do all your .NET/MP work and call that from node? Yeah sure, but what if that's actually totally overkill? It's probably overkill for lots of users.
Chip
Friday, May 02, 2014 2:46:41 AM UTC
Hi Cam Birch,

* Parse JSON without crashing all the time (using JSON.NET, instead of the garbage JSON parser inside V8)

This is a big claim to make about v8 and JSON. I assume you do know what you are doing for sure but it doesn't change my surprise. Have you written / spoken about it in more detail somewhere?
Friday, May 02, 2014 2:52:05 AM UTC
I get the goal, but I'm going to probably want to get any long running CPU intensive task off that Node.js box. I'm looking at all my Node boxes as IO engines, not packed with lots of RAM or CPU power. So, I'm decoupling as best I can through some queued approach.

Although it is cool and this research project should be banged around and put out there for defense as it is.
Friday, May 02, 2014 2:53:26 AM UTC
I think Edge is amazing. Building a full NodeJS service lately right after a C# one I realized I'm more at ease writing the business logic in C#, but I prefer the server interfaces in NodeJS than ASP.Net (Express/Hapi/Koa are miles easier to work with than anything I found in .Net, including Nancy and Simple.Web).

I have yet to work with Edge seriously but it's the kind of technology that allows developers to pick their tools, so while it probably won't ever gain widespread utilisation still has plenty of usages. And from a CompSci point of view it's very interesting seeing all this work together.
Felipe Leusin
Friday, May 02, 2014 2:58:42 AM UTC
@Scott Holodak

Edge.js has had an OWIN adapter since we interviewed Thomas on Herding Code last year. It's pretty slick, lets you plug OWIN compatible objects into an Express.js pipeline.
Friday, May 02, 2014 3:00:48 AM UTC
Edge.js is definitely interesting... but I keep reading things like "use it for CPU-bound work inside node!"

This is fine advice if your node app is a batch process, but I'm not sure its such great advice if you're hosting a REST API or other web-visible functionality. I would expect potential CLR thread starvation issues to result in a high-scale environment, as described here:

http://blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx

(that link isn't node-specific, but I think the same general principle would apply to edge.js code sitting behind a node web api, for example)
Friday, May 02, 2014 3:00:59 AM UTC
I feel like very few appreciate the power of libuv/event loop (esp when mixed with stream based libs). It could be argued that thread per req is antiquated IMO.

We should be thankful that someone has given us the ability to mix the advantages of libuv and the NPM ecosystem AND the advantages of c#/f#.

This is awesome software. Even more awesome that it was accomplished so succinctly/strategically.
Micah Smith
Friday, May 02, 2014 3:04:16 AM UTC
@richard If you're worried about "the mess" this will create, you obviously haven't worked with the right engineers. Tomasz has engineered a great solution to a tough problem and has given people the ability to communicate with fundamentally different ecosystems and architectures. It's fucking brilliant and will serve those who see the potential.

:-)
Vince
Friday, May 02, 2014 3:26:01 AM UTC
But how am I going to comment my C# code running as a comment in my javascript code?
Ajai
Friday, May 02, 2014 3:48:17 AM UTC
Ajai - to be clear. Don't use the "C# in comment" feature for anything but demos.
Scott Hanselman
Friday, May 02, 2014 4:21:54 AM UTC
For anyone who might still be be doubting, do check out the "What problem does Edge.js solve?" section of the Edge.js FAQ that Scott linked. I'm sold! :-)
Friday, May 02, 2014 4:29:11 AM UTC
Igor - Who, in commercial projects, is mixing unix and windows technologies?

I seldom help out a friend who owns a rather large website that consists of dozens of servers that are mixed between Linux and Windows. As well as a mixture of Classic ASP, Node, ASP.NET, Mono.

I'm currently working on a little project of my own where my website is on Windows and all image processing is done on Linux.

So yes people do mix technologies.
Friday, May 02, 2014 9:00:14 AM UTC
@Scott Holodak, @Scott K and @Felipe Leusin
"It would be cool if it could expose the node request to .NET as an IDictionary<string, object> with properties filled per the OWIN spec."

Check out 'connect-owin'that implement node.js connect middleware in .NET using OWIN http://bit.ly/1d6FP9d

Take a look at the samples http://bit.ly/199LLKw
Friday, May 02, 2014 12:14:18 PM UTC
Do every function call start a new net thread?
Seven
Friday, May 02, 2014 1:25:02 PM UTC
The idea is great! But the syntax of tunneled code is ugly which makes me remember spaghetti code like ASP or JSP.
blueaqua
Friday, May 02, 2014 1:46:02 PM UTC
I've been using it in in ApprovalTests.NodeJS to read a registry value.

https://github.com/approvals/Approvals.NodeJS/blob/master/lib/Reporters/visualstudioReporter.js#L10

Was the simplest thing I could come up with.

To get this to run on both platforms I use a custom node install script (specified in package.json) to only install edge on windows. But havring the option to leverage it on both platforms would be great.
Friday, May 02, 2014 1:56:07 PM UTC
What is the color scheme you are using for Visual studio? That looks solid.
Rick
Friday, May 02, 2014 2:27:45 PM UTC
This is really interesting. It seems like a great solution for calling captive web services from within an MVC app for instance.

We currently use node.js to "mock" to our service layer when running a suite of selenium tests from within MSTest. Node.js was perfect for this.
Richard Wagenknecht
Friday, May 02, 2014 4:14:38 PM UTC
Found edge an hour before a flight from PDX to Hawaii. By the time we had touched down, I had IISNode, Edge and Express, and a C# assembly (using Entity Framework) all working hand in hand as the backend API for a simple TODO web app. Fun little exercise!
Josh
Saturday, May 03, 2014 2:41:42 AM UTC
@M.R.Safari,

You might like to take a look at the Screencasts by Ross. If you are running Windows 8/8.1/8.1.1 with Hyper-V enabled, you can install vagrant and configure chef (without installing virtual box et el.).

Once configured, all you need is to run this command in your work directory "vagrant up; vagrant ssh" via PowerShell; to switch the machine. Vagrant provides an easy command line capability to run VMs, while Chef keeps track of your recipes/screen-shots (like recorded macros in Excel/Firefox's Greese monkey) to let you dish out future VMs with everything pre-configured, pre-installed; by merely running a command.

I successfully executed couple of cross-platform projects using the aforementioned Vagrant workflow (well I used VirtualBox as Hyper-V wasn't supported back in the day)
HTH.
Sunday, May 04, 2014 3:04:28 AM UTC
Hi Mohamed Meligy,

The issues with the V8/node JSON parser are well enough known that many many NPM modules have been created trying to solve the various shortcomings in various ways. Most seem to just wrap the JSON.parse inside a try/catch which solves the crashing but sadly doesn't do much to solve the ability to read the file.

The parser does a good enough job to handle computer generated json, but the moment you add any variations like simple trailing commas or comments, everything falls apart and you end up with failure instead of functionality.

Simply using almost any .net json parser and poof instead of frustrating error messages and unreadable files you get useful errors and, wow, actually readable files.

Frankly I find that most javascript engines are perfectly acceptable when everything is perfect, yet you add any variables to perfection and things get less reliable. Given that javascript is generally designed to fail off it makes sense but I do love programming in both C# and node.js so I make do with the tools I've got and make lemonade. Luckily we have edge.js to allow me and many others to quickly fix whatever shortcomings present in the quickest and least time consuming way possible.

I haven't published my quick hack for json yet but I have published a nice simple excel lib and a slightly more advanced SQL library than the basic (yet functional) example that comes with edge.

Github/camMCC/aps-sql and aps-excel

Also a good example on using typescript with edge as well as referencing dlls and using cs code in proper cs files.
Cam Birch
Sunday, May 04, 2014 6:35:17 AM UTC
Is it reliable enough to build premium applications?
Fayez Barbari
Sunday, May 04, 2014 6:23:30 PM UTC
Edge.js is simply amazing.
Sunday, May 04, 2014 10:50:45 PM UTC
@Cam Birch: you are aware that the JSON format is not the same as javascript objects syntax, right ? Blame the format for not supporting the features you want, not the parser for actually doing its job and throwing errors when you give it nonsense. There is no "well known" issues on the V8 parser that I know of.
Nicolas Morel
Monday, May 05, 2014 8:07:48 PM UTC
I am pretty sure it's Chocolatey...not Chocolately.
Nekotakacho
Tuesday, May 06, 2014 6:53:32 PM UTC
Just for clarification. The call to the c# dll will be in a javascript comment. If anyone is worried about that being error prone. Write a test, and then stop worrying. ;)
Adam Wright
Friday, May 09, 2014 5:52:32 AM UTC
I like the idea very much, but I've not understood what is the lifetime of the invoked .Net objects. I need to create an ADO sql, connection do a series of operations, including transactions, BL querying, and at the end close the connection. How to get an "handler" to a connection and reuse it for a serie of operations? Will the created .net object be destroyed after the first call?
More, I'd like to get a sequence of notification from the .net code, in a deferred-fashioned style like JQuery. More, it would be useful to get data in raw format and to send it on the fly as raw format (without providing field name for each object), and then "objectify" it on the client. Is it possible to achieve this with edge-sql?
Thanks in advance
Gaetano Lazzo
Friday, May 09, 2014 1:30:49 PM UTC
In some case, I have try this method in my project. But its seem still any error when the apps running. Any idea how to solve this issue? SO very confuse to solve without guidance.
Monday, June 09, 2014 6:59:01 PM UTC
Software never really has worked right on Windoze to date. That's one of the reasons that *nix took over the real world. And, now there is the opportunity to increase the number of failed operational package interactions by an order of magnitude, and spread it to affect the real world, too? Insane!
So, the same group is providing a robust set of user level, AND system level regression tests, that will identify 85-90% of all the pending failures, right?
Keep the Windoze crap away from the software that actually works, without concern. Otherwise such drivel is handed the keys to open the door, and infect the working world
Douglas Randall
Tuesday, July 15, 2014 9:52:45 PM UTC
Scott - interesting post.

We have been working with Edge over the last week and have been quite happy with the results thus far. That said, we have run into an issue and I was hoping you could assist with shedding some light.

Using Edge from .net, we are spinning up a node instance so we can run in-process via windows service. Everything was working well and we were able to debug the .net assemblies. Today we added the 'cluster' module from node to take advantage of multi-core; however, Edge does not seem to like the implementation. Outside of Edge, all works well.

Do you have any advice on how we might go about debugging the issue or any tips you can pass over?

Thanks,
Mark
Mark Randell
Name
E-mail (will show your gravatar icon)
Home page
 
Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, li, ol, pre, strike, strong, sub, super, u, ul) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.
Live Comment Preview

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.