NodeServices: Where Javascript and .NET Meet Back on the Other Side
Tags: c, javascript, node, dotnet
Published: 2017-09-14 14:01:06

---
title: "NodeServices: Where Javascript and .NET Meet Back on the Other Side"
description: A post that introduces the .NET NodeServices project and how it can be used to easily integrate existing Node code or packages from npm directly within your .NET applications.
tags: c#, javascript, node, dotnet
cover_image: https://thepracticaldev.s3.amazonaws.com/i/65ue3dg7c8pvgmxxo8a9.jpg
published: true
---

_This was originally posted on [my blog](http://rion.io)._

Javascript is everywhere. It's in the browser, on the server, and it's climbing through your windows and snatching your people up. And because it's a fairly trivial language to pick up (but impossible to master), it can be extremely useful when you want to do something _on_ the server.

This was and still is the real appeal of technologies like Node.js, however it's quite easy to do within the realm of .NET. This post is going to provide a very basic overview of how to target and execute some arbitrary Javascript code within .NET without ever touching the browser.

##What is/are NodeServices?

I'll let the creator, Steve Sanderson, explain it as follows:

- NodeServices provides a fast and robust way for .NET code to run JavaScript on the server inside a Node.js environment. You can use this to consume arbitrary functionality from NPM packages at runtime in your ASP.NET Core app.

- Most applications developers don't need to use this directly, but you can do so if you want to implement your own functionality that involves calling Node.js code from .NET at runtime.

You can [find the project itself on GitHub](https://github.com/aspnet/JavaScriptServices) as well, which goes far beyond just interacting with just Node in .NET.

##Setting Up NodeServices

This particular example of NodeServices depends on .NET Core 2.0, which [you will want to install from here](https://www.microsoft.com/net/download/core) if you want to follow along. The steps _may_ work with earlier versions, but if you run into issues, consider trying 2.0.

In this example, we will build a simple Web API that will rely on NodeServices to perform some operations. So to get started, we'll first need to create a new project:

```
dotnet new webapi
```

If you aren't a command line person, [Visual Studio 2017 Update 3](https://www.visualstudio.com/vs/preview/) _should_ have the necessary tools to create .NET Core 2.0 applications through the traditional GUI.

##Configuring NodeServices

Getting started with NodeServices is dead simple. You basically just need to include the `Microsoft.AspNetCore.NodeServices` NuGet package within your application via the following command:

```
dotnet add package Microsoft.AspNetCore.NodeServices
```

You should then see it within your project definition as well:

```language-xml
<ItemGroup>
    <!-- Others omitted for brevity -->
    <PackageReference Include="Microsoft.AspNetCore.NodeServices" Version="2.0.0" />
</ItemGroup>
```

Then, you'll need to configure the necessary middleware to handle using the service within your application in the `ConfigureServices()` method of your `Startup.cs` file:

```language-csharp
public void ConfigureServices(IServiceCollection services)
{
    // This will configure the NodeServices service
    services.AddNodeServices();
}
```

After  configuring the services, you'll now be able to use dependency-injection to handle injecting this into your application at the controller level:

```language-csharp
public class ValuesController : Controller
{
        private readonly INodeServices _nodeServices;

        public ExampleController(INodeServices nodeServices)
        {
            _nodeServices = nodeServices;
        }

        // Other actions here
}
```

Or at a single method/action level with the `[FromServices]` attribute:

```language-csharp
public async Task<IActionResult> Example([FromServices] INodeServices nodeServices)
{
       // TODO: Cool stuff
}
```

Now that we have the actual Node Services wired up, let's look at what has to be done on the Javascript side of things get the two sides to play nicely with one another.

## Actually Using NodeServices

Since we are going to be calling Javascript code from within .NET, we will first need to define the actual code that we want to call. So to get started, we will **create a new Scripts folder at the root of the current project and a new file called Add.js within it**:

![add.js-in-solution](http://rion.io/content/images/2017/06/node-services-example.png)

This Add.js file is going to function as a single module that will export a function which will be called by our C# code. For the sake of simplicity, we will start by simply adding two numbers together and returning the result via a callback:

```language-javascript
module.exports = function(a, b, callback) { 
  let result = a + b;
  callback(result); 
};
```

Jumping back to the .NET side of things, we can configure our service to point to our new Javascript file using the `InvokeAsync<T>()` method, which expects the path to the file being invoked and a type to indicate the expected return type:

```language-csharp
public async Task<long> Add(int x = 11, int y = 31)
{
    return await _nodeServices.InvokeAsync<long>("Scripts/Add.js", x, y);
}
```

After running your application and hitting that endpoint, you'll quickly see the expected result and that no client-side Javascript was harmed during the creation of the response:

![add-example](http://rion.io/content/images/2017/08/add-example.gif)

Now, if you are familiar with Javascript, then you know that it can do all sorts of _crazy_ things, especially when you use really dangerous functions like `eval()`. We'll create another file called Eval.js to add to our existing Scripts folder that looks like this:

```language-javascript
module.exports = function (callback, x) {
    let result = eval(x);
    callback(null, result);
};
```

For demonstration purposes, let's create another method that accepts some arbitrary text and evaluates it within our Web API controller:

```language-csharp
public async Task<string> Eval(string expression = "6 * 7")
{
    return await _nodeServices.InvokeAsync<string>("Scripts/Eval.js", expression);
}
```
We can see this in action below:

![eval-example](http://rion.io/content/images/2017/08/eval-example.gif)

NodeServices really shines in scenarios where you might not be able to find the perfect NuGet package that you are looking for, but one exists [on npm or somewhere else in the vast Javascript ecosystem](https://www.npmjs.com/). Simply grab the code that you need, or pull down the actual npm package itself (along with its required dependencies) and use it just as you would expect.

Let's see how something like that might work if we decide to use a fancy npm package to generate QR codes using a bit of text. First, we'll need to install the appropriate npm package:

```
npm install qr-image
```

Again - if you aren't a command line fan, you can [download it directly from the source on GitHub](https://github.com/alexeyten/qr-image) or using some other package manager of your choice.

Once you have the QR package downloaded, you can create a new file within your Scripts folder called QR.js. Since we are now in a Node world, you'll just need to wire up the appropriate dependencies via a `require()` statement that points to your package and add the following code:

```language-javascript
let qr = require('./qr-image');
module.exports = function (callback, text) {
    var result = qr.imageSync(text, { type: 'png' });

    var data = [];
    result.forEach(i => {
        data.push(i);
    });

    callback(null, data);
};
```

This does the following:

- Wires up our QR package for use.
- Uses the string data passed in to generate a QR code image.
- Reads the image data into a byte[] that our C# code will consume.

At this point, we can write the corresponding method with our API:

```language-csharp
public async Task<IActionResult> QR(string text = "42")
{
    var data = await _nodeServices.InvokeAsync<byte[]>("Scripts/QR.js", text);
    return File(data, "image/png");
}
```

And when we hit that method, we see that the values return as expected:

![qr-example](http://rion.io/content/images/2017/08/qr-example.gif)

This is really just the tip of the iceberg, but it demonstrates just how easy it is to integrate the entire Node ecosystem within .NET to build all sorts of applications.

##Give it a shot!

As mentioned earlier in the post, the npm and Node ecosystems are _huge_ and there are tons of useful packages that you can now pull down and integrate into your ASP.NET applications with ease.

If you don't want to walk through all of these steps by hand, feel free to pull down the code from this demo or check out Steve Sanderson's additional examples found on the NodeServices repo as well:

 - [See these examples on GitHub](https://github.com/rionmonster/NodeServicesExample/)
 - [Check out Steve Sanderson's Examples on GitHub](https://github.com/aspnet/JavaScriptServices/tree/dev/samples/misc/NodeServicesExamples)