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.