Share via


Execute JavaScript code from ASP.NET Core back-end using NodeServices

Not many are familiar with this awesome feature of .NET Core. ASPNET team is actively maintaining a project named JavascriptServices; Along with other packages, it includes the NodeServices package. Using this package, one can easily create an instance of node and execute JavaScript code (function) in the backend. If you think of it right now, you can see that it actually opens up a wide variety of development opportunities. By opportunities I mean; the ASP.NET core project is trying hard to make its package eco-system (NuGet) rich but while doing it, why not get advantages of other package eco-system as well, right? When I talk about other than NuGet package manager, the first name that comes to my mind is Npm (node package manager). Npm is the largest package manager out there on this very day and it's growing rapidly. By using NodeServices package we can now use (not all of the npm packages but) most of the npm packages in our backend development. So, let me show you how to configure NodeServices in your ASP.NET core project and use it to execute javascript code on the backend.

For demo purpose, I’m using the barebone ASP.NET web application.

Install the NodeServices packages from NuGet (Microsoft.AspNetCore.NodeServices) and add it as a service like the following:

public void ConfigureServices(IServiceCollection services){    // Add framework services.    services.AddMvc();    services.AddNodeServices();}

By default, npm will not be initialized in this project so go to your application’s root directory and open up a command prompt then initialize npm with the following command:

npm init -y
N.B: -y flag will take the default options while initializing npm.

Let’s use the most starred npm package: lodash (A modern JavaScript utility library delivering modularity, performance & extras) to manipulate some data in our application.

Install lodash with the following command,

npm install lodash –save

Create a folder where all of your server-side JavaScript code will go. Add a JavaScript file named lodash.js and copy and paste the following line of code in it:

var _ = require('lodash'); module.exports = {    sortBy: function (callback, data, option) {        var result = _.sortBy(data, [option]);        callback(null, result);    }};

Now to use this sortBy method of this lodash module we have to use the InvokeExportAsync<T> method of a NodeServices instance. A typical GET API for returning a list of sorted users can be like:

public class User{    public string Name { get; set; }    public int Age { get; set; }} [Produces("application/json")][Route("api/Users")]public class UsersController : Controller{    [HttpGet("GetSortedUsers")]    public async Task<IActionResult> SortedUsers([FromServices] INodeServices nodeServices, string sortBy)    {        var data = new User[]        {            new User {Name = "fred", Age = 48},            new User {Name = "barney", Age = 36},            new User {Name = "fred", Age = 40},            new User {Name = "barney", Age = 34}        };         var sortedUsers = await nodeServices.InvokeExportAsync<User[]>("./Node/lodash", "sortBy", data, sortBy);         return Ok(sortedUsers);    }}

Notice that we are getting an instance of INodeServices ([FromServices] INodeServices nodeServices) from our configured service. sortBy is sorting criteria that we will pass through the query string. To cast the returned result back to an array of User object we changed the generic return type of InvokeExportAsync to User[]. To invoke this GET action, simply browse to your application URL and make a request like the following:

Another thing I must include is that since we are defining a function with a name in the lodash module, we have to use the InvokeExportAsync function and define the function name in its second parameter. If we would have returned a single function directly from the module we would have used the InvokeAsync<T> method instead.

Let me give you an example to clarify what I just said. The following is a addNumbers.js module:

module.exports = function (callback, first, second) {    var result = first + second;    callback(/* error */ null, result);};

To invoke this function attached to the module.exports directly, we have to write something like this:

var result = await nodeServices.InvokeAsync<int>("./addNumbers", 1, 2);

And that’s it! This is how you can execute JavaScript code in your ASP.NET core backend using the NodeServices package.