Nodejs and the MEAN stack for the .NET developer part 2

In the previous article we’ve set up the web application skeleton with Express for the reMember application and we wrote a first test to see if we can actually save an object to the database with Mongoose.

In an Express generated app, ‘app.js’ is the starting point of the application. (Like Global.asax or WebApiConfig in an ASP.NET MVC app).

Since the goal of this article is to write an api, we can clean it up a little.

  • We will not be using jade at this time, so we can clean out references to the view.
  • We can also clean out the ‘user’ lines because we are not going to use these.
  • We will comment out the routes as well and create a new default route to an index.html file
var express = require('express');

//!!don't need this:
//var routes = require('./routes');
//var user = require('./routes/user');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);

//!!don't need this, we're going to serve plain html:
//app.set('views', path.join(__dirname, 'views'));
//app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);

//!!change this as well to reflect our new folderstructure:
app.use(express.static(path.join(__dirname, '../public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

//!!don't need this (yet)
//app.get('/', routes.index);
//app.get('/users', user.list);

//!!add a default route
app.all('/', function(req, res) {
  res.sendfile('index.html', { root: "../public" });
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Now create an index.html file in /public:

<html>
<head>
<title>Still empty</title>
</head>
<body>
<h1>Still empty..</h1>
<p>But we're getting there..</p>
</body>
</html>

And start up the server with node app.js
You should now be able to browse to localhost:3000 and see the index.html.

Debugging

But what if you don’t and you see something like this:

/home/jacqueline/apps/reMember/server/app.js:37
});
^
SyntaxError: Unexpected token }
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:902:3
jacqueline@linuxlab:~/apps/reMember/server$ 

Then you probably forgot to close a curly brace or a quote. Stop node (ctrl+c), correct the changes and start again.
But wait, there’s an easier method.
With nodemon it is possible to debug changes on the fly.
Install it globally with npm install -g nodemon.

Now start app.js with nodemon app.js

Everytime you change and save a file the node server is automatically restarted. It crashed when something is from and it starts running as soon as you correct your mistakes:

nodemon

Take a look at http://localhost:3000 now:

stillempty

So that works.

Are we going to write that API or what?

Yes we are.
Delete all the files in the routes folder.
Create new file called api.js


//!!the C# equivalent would be: 
//using mongoose; 
//using member;

var mongoose = require('mongoose');
var Member = require('../models/Member');


//!! /members GET  (in ASP.NET MVC: public IEnumerable Get())

exports.members = function(req,res) {
  Member.find({}, function(err, data) {
      res.send(data);
    });
};

I’ve written the C#/.NET equivalents in the comments for convenience.

The Mongoose ‘find’ method signature is written in their API. For example:

// executes immediately, passing results to callback
MyModel.find({}, function (err, docs) {});

The result of the query will be put in ‘docs’, which is always the 2nd parameter.

The Mongoose API docs are a very good read and helped me enormously to understand how it works.

Mapping the mongoose functions to a route in app.js

We now need to map the exports.members function to the route /members.
This happens in app.js.

var express = require('express');
var http = require('http');
var path = require('path');

//!!add the Mongoose module:
var mongoose = require('mongoose');

var Member = require('./models/Member');

//!!add the path to the api.js file:
var api = require('./routes/api');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, '../public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

//!!connect to mongo:
mongoose.connect('mongodb://localhost:27017/local');

//!! map the /members route to the api.members function:

app.get('/members', api.members);

//default route
app.all('/', function(req, res) {
  res.sendfile('index.html', { root: "../public" });
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Restart node (or don’t of you’re running nodemon) and browse to http://localhost:3000/members.

grimm

I’ve added some Grimm characters.

Tip: use Postman to test the API.

The github repo for reMember is here.

Next time we’ll start building the frontend with Angularjs. (The ‘A’ in the MEAN stack).

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: