Thursday, January 30, 2014

NodeJS mit Visual Studio 2013

image

Einleitung

Wäre es nicht eine tolle Geschichte, wenn sowohl auf der Client- als auch auf der Server-Seite mit JavaScript entwickelt werden könnte? Genau das ermöglicht Node.js. Dabei handelt es sich um einen JavaScript-Server aufbauend auf Googles V8 JavaScript Engine, was uns den Vorteil beschert, dass wir auf der Serverseite unabhänging von der Browser-JavaScript-Engine Version sind. Bei einem aktuelleren JavaScript-Standard, können wir nun einfach upgraden, ohne auf irgendwelche Browser-Hersteller warten zu müssen.
Jetzt sollte das noch alles mit Visual Studio laufen und wir wären glücklich.
Nun, dann will ich nicht eurem Glück im Wege stehen und wir versuchen das doch einfach einmal.

Den kompletten Beispiel-Code findet ihr hier

Setup

Um loslegen zu können, müssen wir unser System noch vorbereiten.
Dazu benötigen wir Download und Installation von:
  • NodeJS von hier: http://nodejs.org
  • Das sollte dann nach der Installation so bei euch aussehen:
    image
  • Node.js Tools für Visual Studio von hier: https://nodejstools.codeplex.com/
    Das sollte dann wiederum nach der Installation so bei euch aussehen:
    image
  • Optional noch einen Microsoft SQLServer, falls Ihr Daten von eurem Server darstellen wollt.
Damit wären wir bereit eine kleine NodeJS Applikation in Visual Studio zu bauen.

Ein einfaches Code-Beispiel mit NodeJS

Zuerst benötigen wir ein neues Projekt. Dazu nehmen wir am Besten das “Blank Node.js Console Application Template”.
Gebt eurem Projekt einen Namen (ich habe mich für NodejsFirstConsoleApp entschieden) und klickt auf OK.
image
Das Resultat ist ein NodeJS Projekt, das sollte dann so bei euch aussehen:
image
Jetzt wollen wir das gleich einmal testen. Öffnet dazu die app.js-Datei und schreibt dort folgendes hinein:
==================================================
var http = require('http');
var port = process.env.PORT;
var httpServer = http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type''text/plain'});
    res.write("node " + process.version + " " + process.arch + ".\n");
    res.end("You are up and running!!");
});
httpServer.listen(port);
console.log('Server running at localhost:'+port);
==================================================
Danach lassen wir das Projekt einfach laufen (F5), das sollte dann so aussehen:
image
Jetzt benötigen wir noch einen Browser und dort gehen wir gleich einmal auf die URL:
http://localhost:1337/, das sollte uns dann das gewünscht Ergebnis liefern.
image
Soweit sieht das alles sehr gut aus und war eigentlich auch recht einfach.
Nun wollen wir doch gleich noch Daten aus dem SQLServer abfragen.

SQLServer mit NodeJS

Dazu benötigen wir den “Microsoft Driver for NodeJS”, Infos dazu findet Ihr hier:
https://npmjs.org/package/msnodesql
Momentan gibt es noch Probleme den Treiber mit Visual Studio 2013 zu builden,
darum empfehle ich euch eine bereits gebuildete Version herunterzuladen und diese zu verwenden.
(z. B. diese hier: https://github.com/jorgeazevedo/node-sqlserver-binary
In der Zip-Datei findet Ihr ein node_modules Verzeichnis, dieses werden wir gleich in unserem Projekt benötigen).
Schaltet jetzt am Besten gleich einmal “Show all Files” mit dem Button image ein.
Nun kopiert Ihr das “node_modules” Verzeichnis mit dem File Explorer in eurer Projekt.
NodeJS verwendet dieses Verzeichnis, für Module – also ähnlich unserer Referenzen in einem .NET Projekt.
Wenn Ihr das gemacht habt, dann ändert sich umgehend eure Projekt-Ansicht in Visual Studio,
da Visual Studio automatisch alle Änderungen am File System mitbekommt.
Das msnodesql Modul ist somit erfolgreich eingebunden.
image
Ändert nun euer Skript, damit das so wie nachfolgend aussieht.
Falls euer SQLServer nicht lokal installiert ist, dann müsst Ihr die Verbindung anpassen, ich
habe (local) für den lokalen SQLServer und master für die Datenbank gewählt.
==================================================
var sql = require('msnodesql');
var connectionString = "Driver={SQL Server Native Client 11.0};Server={(local)};Database={master};Trusted_Connection={Yes};";
var testQuery = "SELECT 1";
if(!connectionString) {
    console.log("This script cannot run without a connection string");
    return;
}
var http = require('http');
var port = process.env.PORT;
 
var httpServer = http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type''text/plain'});
    res.write("node " + process.version + " " + process.arch + ".\n");
    sql.query(connectionString, testQuery, function(err, result) {
        if(err)
            res.end("Query Failed \n");
        else
            res.end("Query result: " + result[0]['Column0'] + " \n");
    });
});
httpServer.listen(port);
console.log('Server running at localhost:'+port);
==================================================
Ich würde euch empfehlen den Web-Browser bei Ablauf der Applikation automatisch mitlaufen zu lassen,
das könnt Ihr in den Projekt—Eigenschaften aktivieren:
image
Lassen wir die Applikation wiederum laufen, dann öffnet sich gleich der Browser und wir sehen das Resultat unserer Abfrage:
image
Hinweis: Falls Ihr eine Exception wie die untenstehende bekommt, so ignoriert diese (ich habe ein 64-bit System) und drückt Continue:
image
Hier können wir übrigens auch gleich sehen, wie tief die Integration von NodeJS in Visual Studio geht – dazu wählt einfach den
Menüpunkt Debug->Exceptions an. Dort seht Ihr, dass hier nun auch NodeJS auftaucht und Ihr könnt das Anhalten des Debuggers
bei einer NodeJS Exception auch ausschalten.
image
OK, das war eine nette Geschichte, aber jetzt wollen wir aber auch wirklich Daten sehen.

Dazu ändere ich die Verbindung auf die AdventureWorks-Datenbank
und passe noch die Abfrage an, das - in JavaScript Code gegossen - dann so aussieht:
==================================================
var connectionString = "Driver={SQL Server Native Client 11.0};Server={(local)};Database={AdventureWorks2012};Trusted_Connection={Yes};";
...
...
sql.query(connectionString, "SELECT [DepartmentID],[Name],[GroupName] FROM [HumanResources].[Department]", 
    function (err, results) { 
        if (err) { 
            console.log("Error running query!"); return; 
        } 
        for (var i = 0; i < results.length; i++) 
        { 
            res.write("Id: " + results[i].DepartmentID + " Name: " + results[i].Name + " " +  results[i].GroupName + " \n"); 
        }
        res.end(""); 
    });
==================================================
Das Resultat sieht bei mir dann so aus:
image
Sehr gut, die Daten werden am Client angezeigt, aber wenn man heutzutage Daten ausliest, sollten die idealerweise als JSON-String übertragbar sein.
Mal sehen, ob wir das auch hinbekommen.

REST-Service mit SQLServer und NodeJS

Dazu benötigen wir ein weiteres Modul, nämlich restify, Infos dazu findet Ihr hier:
https://npmjs.org/package/restify
Dieses Mal fügen wir das Modul gleich direkt in Visual Studio 2013 hinzu. Dazu drücken wir die rechte Maustaste an dem image Node im Solution Explorer und wählen “Manage npm Modules” aus.
image
Es öffnet sich ein neues Fenster, und wir suchen nun nach restify im npm Repository.
image
Abschließend clicken wir auf “Install Locally” und nach ein paar Sekunden wir haben das Modul zu unserer Solution hinzugefügt.
image
Jetzt kann es also losgehen. Wir wollen den gleichen query wie zuvor verwenden, allerdings soll die Abfrage durch REST geschehen und das Resultat ein JSON-String sein. In JavaScript gegossen sieht das dann folgendermassen aus:
==================================================
var sql = require('msnodesql');
var restify = require('restify');
var connectionString = "Driver={SQL Server Native Client 11.0};Server={(local)};Database={AdventureWorks2012};Trusted_Connection={Yes};";
var testQuery = "SELECT 1";
if(!connectionString) {
    console.log("This script cannot run without a connection string");
    return;
}
var restify = require('restify');
var server = restify.createServer();
server.listen(8080, function () {
    console.log('%s listening at %s', server.name, server.url);
});
server.get('/Departments', Departments);
function Departments(req, res, next) {
    res.header("Content-Type: application/json");
    sql.query(connectionString, "SELECT [DepartmentID],[Name],[GroupName] FROM [HumanResources].[Department]", 
    function (err, results) { 
        if (err) { 
            console.log("Error running query!"); return; 
        } 
        var result = []; 
        for (var i = 0; i < results.length; i++) 
        { 
            result.push({ id: results[i].DepartmentID, Name: results[i].Name, GroupName: results[i].GroupName });
        }
        res.send(result);
    });
}
==================================================
Wenn wir das wiederum ablaufen lassen und wir mit unserem Browser auf die Adresse http://localhost:8080/Departments gehen, dann sehen wir das gewünschte Resultat.
image

Zusammenfassung

Visual Studio 2013 und NodeJS bilden ein starkes Team. Es steht einer erfolgreichen serverseitigen JavaScript Entwicklung nichts mehr im Wege.

CSharpCodeFormatter