SlideShare a Scribd company logo
Building production 
websites with Node.js 
on the Microsoft stack 
(aka “How I Learned to Stop Worrying 
and Love edge.js”) 
Dan Polivy 
dan@cellartracker.com 
@DanPolivy
CellarTracker is the world's largest collection of wine reviews, 
tasting notes and personal stories from people who love wine. 
1.7M+ wines, 4.5M+ tasting notes (community and professional), 300,000+ registered users
Why Node.js?
Our “current” stack
Yes, that’s VBScript 
Front End IIS 
Business 
Data 
Classic ASP 
(VBScript) 
MS SQL 
Server
11 years of legacy… 
• Two web experiences built on Classic ASP/VBScript 
• Desktop and “Classic” 
• 170+ SQL tables, 25+ SQL Views 
• Existing infrastructure 
• Physical rack in Seattle datacenter 
• Virtualized on VMWare, guests running Windows Server
Mobile: not again! 
With limited resources (e.g., me), how can we modernize our 
stack to support next generation mobile web and apps 
without sacrificing our existing investments?
Node.js to the rescue? 
 We already use a lot of JavaScript for our client side 
 Lightweight development model (no compilation) 
 Async nature seems well-suited to our workload (lots of blocking DB 
queries) 
 It is (was) the new hot-ness (circa March 2013) 
? Integration with IIS 
 iisnode! 
? Integration with SQL 
 Tedious, MS NodeSQL, edge.js!
Will it blend? 
0 100 200 300 400 500 600 700 
iisnode 
Standalone 
Simulated Requests/sec 
Edge.js MS Node SQL Tedious Classic ASP 
HTTP Request returning HTML wine detail page with 5 SQL queries for data
Conclusion: Yes! 
• Async is a HUGE win for higher throughput & lower latency compared 
to serial systems like Classic ASP (and even Rails) 
• Contrary to what you might think, loading .NET in-process to talk to 
SQL yields significant performance gains vs pure JS or native (C++) 
drivers 
• Offloading heavy DB/computation lifting into .NET thread pool frees up 
Node.js’ main thread for other work 
• Marshalling data between JS and .NET has incremental cost 
• iisnode adds some (latency) overhead, but adds many useful features
iisnode 
A native IIS module that allows hosting of Node.js applications in IIS on Windows 
https://github.com/tjanczuk/iisnode
Process 
Management 
Side-by-Side Scalability 
Integrated 
Debugging 
Auto-update 
Process 
Management 
(forever) 
Side-by-Side 
(nginx) 
Scalability 
(cluster) 
Integrated 
Debugging 
(node-inspector) 
Auto-update 
(supervisor) 
Benefits
How does it work? 
Client 
• Initiates HTTP Request, e.g. ‘GET /m’ 
IIS 
• URL Rewrite rule routes request to app, e.g. ‘GET /m/server.js’ 
• iisnode handler spawns process as necessary and fwds request 
node.exe 
• Receives request via named pipe port (process.env.PORT) 
• Otherwise, works exactly the same as if it were standalone!
Why is this awesome? 
• Node.js app runs side-by-side with existing Classic ASP (or 
ASP.NET/etc) site 
• With URL rewrite module, enable IIS to serve up static content (e.g. 
client JS, CSS, images)  more performant 
• X-Forwarded-For/X-Forwarded-Proto headers can be added so you 
know the true source of the request 
• app.set('trust proxy', true); 
• Lifecycle management gracefully drains/recycles processes when JS 
changes
Integrated Debugging
edge.js and SQL 
.NET and Node.js in-process 
https://github.com/tjanczuk/edge
SQL Requirements 
• Parameterized queries 
• Input, output parameters and RETURN values 
• Call SPROCs (EXEC sp_FetchWineData) 
• Typically require multiple queries to fetch all data to render a page 
ADO.NET
Data model 
Proxy 
.NET assembly 
Bottles 
Notes 
Wines 
… 
SQL Client 
index.js 
node module 
Bottles 
Notes 
Wines 
… 
SQL Client 
edge.js 
• Separate C# assembly for data model, wrapped in JS API 
• Utilize .NET threadpool and C# async/await to parallelize queries 
• More efficient to write queries in C# and return JSON data
Example: Fetching a tasting note 
express.js route handler for /m/notes
Example: Fetching a tasting note 
cellartracker-sql.notes.getNote JS API
Example: Fetching a tasting note 
C# Notes.GetNote method
Example: Fetching a tasting note 
{ 
"Note": { 
"iNote": 3122730, 
"iWine": 1314868, 
"iUser": 60873, 
"Name": "I", 
"Favorite": 0, 
"Rating": 95, 
"TastingDate": "October 25, 2012", 
"TastingNotes": "Dark red body. Subtle perfumed nose. A beautifully elegant body 
full of plum, black cherry, and darker spices. This is a powerful wine with a long, 
lingering finish. Refined tannins, good acids and structure. This is a really nice wine 
right now, and will only get better with time!", 
"LikeIt": true, 
"AllowComments": true, 
"Votes": 1, 
"Views": 1234, 
"Defective": false, 
}, 
"Comments": [ 
{ 
"iComment": 5056, 
"iUser": 1, 
"Name": "Eric", 
"Comment": "Yum, serious wines!", 
"PostedDate": "11/13/2012 4:58pm", 
"LastEditDate": "11/13/2012 4:58pm" 
} 
], 
"Wine": { 
"iWine": 1314868, 
"Wine": "Gaja Langhe Nebbiolo Sorì San Lorenzo", 
"Vintage": "2009", 
"iProducer": 91, 
"Producer": "Gaja", 
"Locale": "Italy, Piedmont, Langhe, Langhe DOC", 
"Type": "Red", 
"Varietal": "Nebbiolo", 
"DisplayVintage": "2009", 
"FullWineName": "2009 Gaja Langhe Nebbiolo Sorì San Lorenzo", 
"SplitLocale": [ 
"Italy", 
"Piedmont", 
"Langhe", 
"Langhe DOC" 
] 
} 
} JSON Data returned from C#
General Purpose SQL Class 
• Support for SELECT, INSERT, UPDATE, DELETE, EXEC (SPROCs) 
• Parameters 
• Fully parameterized queries 
• Type (if not default) 
• Direction (in, out, inout, return) 
• Recordset Processors 
• Default: dump each row as JSON object in array 
• Return single JSON object (first row) 
• Return scalar value 
• Offset/Multiple recordsets
Error Handling 
1. Return empty JSON objects/arrays 
2. .NET Exceptions  JavaScript Error objects 
• Standard node callback signature: callback(error, result) 
• Exception is packaged up as standard Error object 
{ 
[System.AggregateException: One or more errors occurred.] 
message: 'One or more errors occurred.', 
name: 'System.AggregateException', 
InnerExceptions: 'System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]', 
Message: 'One or more errors occurred.', 
Data: 'System.Collections.ListDictionaryInternal', 
InnerException: 
{ [System.Exception: Sample exception] 
message: 'Sample exception', 
name: 'System.Exception', 
Message: 'Sample exception', 
Data: 'System.Collections.ListDictionaryInternal', 
TargetSite: 'System.Reflection.RuntimeMethodInfo', 
StackTrace: ' at Startup.<<Invoke>b__0>d__2.MoveNext() in c:UsersUser.NameSourceReposeCash2testedge2.js:line 7rn--- End of stack trace from previous location where 
exception was thrown ---rn at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn at 
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()rn at 
Startup.<Invoke>d__4.MoveNext() in c:UsersUser.NameSourceReposeCash2testedge2.js:line 5', 
Source: 'cp2luegt', 
HResult: -2146233088 
}, 
HResult: -2146233088 
}
So, where are we now?
express + 
ADO.NET (C#) 
IIS 
Classic ASP 
SQL Server 
iisnode 
ADO
Apps 
• Built using Cordova framework 
• Leverage investment in mobile web 
• Backend completely powered by node.js 
• Remotely serve script to allow faster iteration 
• Add native capabilities where necessary/viable 
• Barcode scanning 
• Label image upload
Traffic 
Last 30 days: 1.6M+ page views served up by 
node.js! 
Nearly 6M page views served by Classic ASP 
on the same server. 
Mobile App Page Views/week 
Mobile Web Page Views/month
Tips, Tricks, and Lessons Learned
Encoding: UTF8 vs Windows 1252 
Our database uses Windows 1252 encoding. JavaScript uses UTF8. 
What to do? 
If only http://howfuckedismydatabase.com/ had a joke about this…
Encoding: UTF8 vs cp1252 
• Database 
• Characters with codes > 256 are HTML entity encoded, as are < and > (XSS 
prevention) 
• Classic ASP 
• Most pages set codepage to 1252, so ASP automatically does conversion/encoding 
for incoming values 
• All URLs on our desktop site are URL encoded using 1252 values 
• Node.js 
• Natively deal in UTF8, and convert when going to/from the DB 
• Edge.js/.NET handle much of it automatically, BUT we must do proper HTML entity encoding 
ourselves 
• Some manual character substitution is required (e.g. some chars have high codepoints in 
UTF8, but are below 256 in 1252) 
• Mobile URLs all use UTF8 encoding
Log file management 
• IIS logs 
• All node traffic ends up in IIS logs, so you have unified log for the server 
• BUT, you can’t tell which traffic is actually handled by node (unless you use 
paths) 
• express/node logs 
• Handled automatically by iisnode: console and stderr 
• One per node process, with a handy index.html 
• Still trying to figure out best management strategy (tips welcome!)
Git 
• Git and GitHub for Windows work great! 
• git-posh: PowerShell add-ins make life easier 
• Managing line-endings a small challenge 
• Most modules use unix endings; most of our code uses Windows 
• For now (but not ideal): set core.autocrlf to false 
• ‘git pull’ deploy 
• iisnode’s auto-refresh will automatically detect changes to JS and gracefully 
recycle processes while draining existing traffic
Other libraries 
• Testing 
• mocha 
• should 
• supertest 
• Build/automation 
• grunt 
• Front-end 
• express 
• handlebars (hbs)
Q + A
Thanks! 
Questions? Curious to learn more? Brave enough to try this yourself? Email me! 
dan@cellartracker.com

More Related Content

What's hot (20)

PDF
Play framework
Andrew Skiba
 
PDF
12 Factor Scala
Joe Kutner
 
PDF
Laravel 8 export data as excel file with example
Katy Slemon
 
PDF
Chef at WebMD
adamleff
 
PDF
Practical ERSync
WO Community
 
KEY
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 
PDF
Os Harkins
oscon2007
 
PDF
Deployment of WebObjects applications on FreeBSD
WO Community
 
PDF
React server side rendering performance
Nick Dreckshage
 
PDF
Node.js, toy or power tool?
Ovidiu Dimulescu
 
PPTX
Node.js Development with Apache NetBeans
Ryan Cuprak
 
PPTX
Bosh 2.0
Johannes Engelke
 
PDF
RESTful Web Applications with Apache Sling
Bertrand Delacretaz
 
PPT
Introduction to Play Framework
Warren Zhou
 
PDF
FITC - Here Be Dragons: Advanced JavaScript Debugging
Rami Sayar
 
PDF
Into The Box 2018 Ortus Keynote
Ortus Solutions, Corp
 
PDF
Apache Cayenne for WO Devs
WO Community
 
PPTX
Batching and Java EE (jdk.io)
Ryan Cuprak
 
PDF
Developing Modern Java Web Applications with Java EE 7 and AngularJS
Shekhar Gulati
 
PPTX
Faster Java EE Builds with Gradle
Ryan Cuprak
 
Play framework
Andrew Skiba
 
12 Factor Scala
Joe Kutner
 
Laravel 8 export data as excel file with example
Katy Slemon
 
Chef at WebMD
adamleff
 
Practical ERSync
WO Community
 
modern module development - Ken Barber 2012 Edinburgh Puppet Camp
Puppet
 
Os Harkins
oscon2007
 
Deployment of WebObjects applications on FreeBSD
WO Community
 
React server side rendering performance
Nick Dreckshage
 
Node.js, toy or power tool?
Ovidiu Dimulescu
 
Node.js Development with Apache NetBeans
Ryan Cuprak
 
RESTful Web Applications with Apache Sling
Bertrand Delacretaz
 
Introduction to Play Framework
Warren Zhou
 
FITC - Here Be Dragons: Advanced JavaScript Debugging
Rami Sayar
 
Into The Box 2018 Ortus Keynote
Ortus Solutions, Corp
 
Apache Cayenne for WO Devs
WO Community
 
Batching and Java EE (jdk.io)
Ryan Cuprak
 
Developing Modern Java Web Applications with Java EE 7 and AngularJS
Shekhar Gulati
 
Faster Java EE Builds with Gradle
Ryan Cuprak
 

Viewers also liked (7)

PPTX
Microsoft Web Technology Stack
Lushanthan Sivaneasharajah
 
PDF
Technology Stack KUDO.co.id
Muhammad Singgih Z.A
 
PDF
Texas Association of Enterprise Architects Feb. Meeting
Mike Walker
 
PPT
SOA in Financial Services
Mike Walker
 
PPTX
DevOps-as-a-Service: Towards Automating the Automation
Keith Pleas
 
PPT
Technology stack behind Airbnb
Rohan Khude
 
PDF
Microservices Technology Stack
Eberhard Wolff
 
Microsoft Web Technology Stack
Lushanthan Sivaneasharajah
 
Technology Stack KUDO.co.id
Muhammad Singgih Z.A
 
Texas Association of Enterprise Architects Feb. Meeting
Mike Walker
 
SOA in Financial Services
Mike Walker
 
DevOps-as-a-Service: Towards Automating the Automation
Keith Pleas
 
Technology stack behind Airbnb
Rohan Khude
 
Microservices Technology Stack
Eberhard Wolff
 
Ad

Similar to Building production websites with Node.js on the Microsoft stack (20)

PPTX
NodeJS
Alok Guha
 
PDF
Node.js
Matt Simonis
 
PDF
Nodejs - Should Ruby Developers Care?
Felix Geisendörfer
 
KEY
Practical Use of MongoDB for Node.js
async_io
 
PDF
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
PPT
Node js
Chirag Parmar
 
PPTX
Building and Scaling Node.js Applications
Ohad Kravchick
 
PPTX
Nodejs
Bhushan Patil
 
PPTX
StrongLoop Overview
Shubhra Kar
 
PPTX
Node.js on Azure
Sasha Goldshtein
 
PDF
Node azure
Emanuele DelBono
 
PDF
NodeJS for Novices - 28/Oct/13 - Winnipeg, MB
David Wesst
 
PDF
NodeJS for Beginner
Apaichon Punopas
 
PDF
Why Choose Node.js for Backend Development?
Sterling Technolabs
 
PDF
Nodejs - A quick tour (v5)
Felix Geisendörfer
 
PPTX
Meanstack overview
Adthasid Sabmake
 
PDF
Building Scalable Apps With Redis And Nodejs Joshua Johanan
hyuryubettie60
 
PPTX
Beginners Node.js
Khaled Mosharraf
 
ODP
Introduce about Nodejs - duyetdev.com
Van-Duyet Le
 
PPT
Node and Azure
Jason Gerard
 
NodeJS
Alok Guha
 
Node.js
Matt Simonis
 
Nodejs - Should Ruby Developers Care?
Felix Geisendörfer
 
Practical Use of MongoDB for Node.js
async_io
 
Nodejs - A quick tour (v6)
Felix Geisendörfer
 
Node js
Chirag Parmar
 
Building and Scaling Node.js Applications
Ohad Kravchick
 
StrongLoop Overview
Shubhra Kar
 
Node.js on Azure
Sasha Goldshtein
 
Node azure
Emanuele DelBono
 
NodeJS for Novices - 28/Oct/13 - Winnipeg, MB
David Wesst
 
NodeJS for Beginner
Apaichon Punopas
 
Why Choose Node.js for Backend Development?
Sterling Technolabs
 
Nodejs - A quick tour (v5)
Felix Geisendörfer
 
Meanstack overview
Adthasid Sabmake
 
Building Scalable Apps With Redis And Nodejs Joshua Johanan
hyuryubettie60
 
Beginners Node.js
Khaled Mosharraf
 
Introduce about Nodejs - duyetdev.com
Van-Duyet Le
 
Node and Azure
Jason Gerard
 
Ad

Recently uploaded (20)

PPTX
An Introduction to ZAP by Checkmarx - Official Version
Simon Bennetts
 
PDF
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PPTX
Equipment Management Software BIS Safety UK.pptx
BIS Safety Software
 
PPTX
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
PDF
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
PDF
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
PDF
Powering GIS with FME and VertiGIS - Peak of Data & AI 2025
Safe Software
 
PDF
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
PPT
MergeSortfbsjbjsfk sdfik k
RafishaikIT02044
 
PPTX
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
PPTX
Engineering the Java Web Application (MVC)
abhishekoza1981
 
PPTX
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
PDF
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
PPTX
Java Native Memory Leaks: The Hidden Villain Behind JVM Performance Issues
Tier1 app
 
PDF
Efficient, Automated Claims Processing Software for Insurers
Insurance Tech Services
 
PDF
Executive Business Intelligence Dashboards
vandeslie24
 
PDF
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
PPTX
Comprehensive Guide: Shoviv Exchange to Office 365 Migration Tool 2025
Shoviv Software
 
DOCX
Import Data Form Excel to Tally Services
Tally xperts
 
An Introduction to ZAP by Checkmarx - Official Version
Simon Bennetts
 
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
Equipment Management Software BIS Safety UK.pptx
BIS Safety Software
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
Powering GIS with FME and VertiGIS - Peak of Data & AI 2025
Safe Software
 
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
MergeSortfbsjbjsfk sdfik k
RafishaikIT02044
 
Migrating Millions of Users with Debezium, Apache Kafka, and an Acyclic Synch...
MD Sayem Ahmed
 
Engineering the Java Web Application (MVC)
abhishekoza1981
 
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
Java Native Memory Leaks: The Hidden Villain Behind JVM Performance Issues
Tier1 app
 
Efficient, Automated Claims Processing Software for Insurers
Insurance Tech Services
 
Executive Business Intelligence Dashboards
vandeslie24
 
Alexander Marshalov - How to use AI Assistants with your Monitoring system Q2...
VictoriaMetrics
 
Comprehensive Guide: Shoviv Exchange to Office 365 Migration Tool 2025
Shoviv Software
 
Import Data Form Excel to Tally Services
Tally xperts
 

Building production websites with Node.js on the Microsoft stack

  • 1. Building production websites with Node.js on the Microsoft stack (aka “How I Learned to Stop Worrying and Love edge.js”) Dan Polivy [email protected] @DanPolivy
  • 2. CellarTracker is the world's largest collection of wine reviews, tasting notes and personal stories from people who love wine. 1.7M+ wines, 4.5M+ tasting notes (community and professional), 300,000+ registered users
  • 5. Yes, that’s VBScript Front End IIS Business Data Classic ASP (VBScript) MS SQL Server
  • 6. 11 years of legacy… • Two web experiences built on Classic ASP/VBScript • Desktop and “Classic” • 170+ SQL tables, 25+ SQL Views • Existing infrastructure • Physical rack in Seattle datacenter • Virtualized on VMWare, guests running Windows Server
  • 7. Mobile: not again! With limited resources (e.g., me), how can we modernize our stack to support next generation mobile web and apps without sacrificing our existing investments?
  • 8. Node.js to the rescue?  We already use a lot of JavaScript for our client side  Lightweight development model (no compilation)  Async nature seems well-suited to our workload (lots of blocking DB queries)  It is (was) the new hot-ness (circa March 2013) ? Integration with IIS  iisnode! ? Integration with SQL  Tedious, MS NodeSQL, edge.js!
  • 9. Will it blend? 0 100 200 300 400 500 600 700 iisnode Standalone Simulated Requests/sec Edge.js MS Node SQL Tedious Classic ASP HTTP Request returning HTML wine detail page with 5 SQL queries for data
  • 10. Conclusion: Yes! • Async is a HUGE win for higher throughput & lower latency compared to serial systems like Classic ASP (and even Rails) • Contrary to what you might think, loading .NET in-process to talk to SQL yields significant performance gains vs pure JS or native (C++) drivers • Offloading heavy DB/computation lifting into .NET thread pool frees up Node.js’ main thread for other work • Marshalling data between JS and .NET has incremental cost • iisnode adds some (latency) overhead, but adds many useful features
  • 11. iisnode A native IIS module that allows hosting of Node.js applications in IIS on Windows https://github.com/tjanczuk/iisnode
  • 12. Process Management Side-by-Side Scalability Integrated Debugging Auto-update Process Management (forever) Side-by-Side (nginx) Scalability (cluster) Integrated Debugging (node-inspector) Auto-update (supervisor) Benefits
  • 13. How does it work? Client • Initiates HTTP Request, e.g. ‘GET /m’ IIS • URL Rewrite rule routes request to app, e.g. ‘GET /m/server.js’ • iisnode handler spawns process as necessary and fwds request node.exe • Receives request via named pipe port (process.env.PORT) • Otherwise, works exactly the same as if it were standalone!
  • 14. Why is this awesome? • Node.js app runs side-by-side with existing Classic ASP (or ASP.NET/etc) site • With URL rewrite module, enable IIS to serve up static content (e.g. client JS, CSS, images)  more performant • X-Forwarded-For/X-Forwarded-Proto headers can be added so you know the true source of the request • app.set('trust proxy', true); • Lifecycle management gracefully drains/recycles processes when JS changes
  • 16. edge.js and SQL .NET and Node.js in-process https://github.com/tjanczuk/edge
  • 17. SQL Requirements • Parameterized queries • Input, output parameters and RETURN values • Call SPROCs (EXEC sp_FetchWineData) • Typically require multiple queries to fetch all data to render a page ADO.NET
  • 18. Data model Proxy .NET assembly Bottles Notes Wines … SQL Client index.js node module Bottles Notes Wines … SQL Client edge.js • Separate C# assembly for data model, wrapped in JS API • Utilize .NET threadpool and C# async/await to parallelize queries • More efficient to write queries in C# and return JSON data
  • 19. Example: Fetching a tasting note express.js route handler for /m/notes
  • 20. Example: Fetching a tasting note cellartracker-sql.notes.getNote JS API
  • 21. Example: Fetching a tasting note C# Notes.GetNote method
  • 22. Example: Fetching a tasting note { "Note": { "iNote": 3122730, "iWine": 1314868, "iUser": 60873, "Name": "I", "Favorite": 0, "Rating": 95, "TastingDate": "October 25, 2012", "TastingNotes": "Dark red body. Subtle perfumed nose. A beautifully elegant body full of plum, black cherry, and darker spices. This is a powerful wine with a long, lingering finish. Refined tannins, good acids and structure. This is a really nice wine right now, and will only get better with time!", "LikeIt": true, "AllowComments": true, "Votes": 1, "Views": 1234, "Defective": false, }, "Comments": [ { "iComment": 5056, "iUser": 1, "Name": "Eric", "Comment": "Yum, serious wines!", "PostedDate": "11/13/2012 4:58pm", "LastEditDate": "11/13/2012 4:58pm" } ], "Wine": { "iWine": 1314868, "Wine": "Gaja Langhe Nebbiolo Sorì San Lorenzo", "Vintage": "2009", "iProducer": 91, "Producer": "Gaja", "Locale": "Italy, Piedmont, Langhe, Langhe DOC", "Type": "Red", "Varietal": "Nebbiolo", "DisplayVintage": "2009", "FullWineName": "2009 Gaja Langhe Nebbiolo Sorì San Lorenzo", "SplitLocale": [ "Italy", "Piedmont", "Langhe", "Langhe DOC" ] } } JSON Data returned from C#
  • 23. General Purpose SQL Class • Support for SELECT, INSERT, UPDATE, DELETE, EXEC (SPROCs) • Parameters • Fully parameterized queries • Type (if not default) • Direction (in, out, inout, return) • Recordset Processors • Default: dump each row as JSON object in array • Return single JSON object (first row) • Return scalar value • Offset/Multiple recordsets
  • 24. Error Handling 1. Return empty JSON objects/arrays 2. .NET Exceptions  JavaScript Error objects • Standard node callback signature: callback(error, result) • Exception is packaged up as standard Error object { [System.AggregateException: One or more errors occurred.] message: 'One or more errors occurred.', name: 'System.AggregateException', InnerExceptions: 'System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]', Message: 'One or more errors occurred.', Data: 'System.Collections.ListDictionaryInternal', InnerException: { [System.Exception: Sample exception] message: 'Sample exception', name: 'System.Exception', Message: 'Sample exception', Data: 'System.Collections.ListDictionaryInternal', TargetSite: 'System.Reflection.RuntimeMethodInfo', StackTrace: ' at Startup.<<Invoke>b__0>d__2.MoveNext() in c:UsersUser.NameSourceReposeCash2testedge2.js:line 7rn--- End of stack trace from previous location where exception was thrown ---rn at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)rn at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)rn at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()rn at Startup.<Invoke>d__4.MoveNext() in c:UsersUser.NameSourceReposeCash2testedge2.js:line 5', Source: 'cp2luegt', HResult: -2146233088 }, HResult: -2146233088 }
  • 25. So, where are we now?
  • 26. express + ADO.NET (C#) IIS Classic ASP SQL Server iisnode ADO
  • 27. Apps • Built using Cordova framework • Leverage investment in mobile web • Backend completely powered by node.js • Remotely serve script to allow faster iteration • Add native capabilities where necessary/viable • Barcode scanning • Label image upload
  • 28. Traffic Last 30 days: 1.6M+ page views served up by node.js! Nearly 6M page views served by Classic ASP on the same server. Mobile App Page Views/week Mobile Web Page Views/month
  • 29. Tips, Tricks, and Lessons Learned
  • 30. Encoding: UTF8 vs Windows 1252 Our database uses Windows 1252 encoding. JavaScript uses UTF8. What to do? If only http://howfuckedismydatabase.com/ had a joke about this…
  • 31. Encoding: UTF8 vs cp1252 • Database • Characters with codes > 256 are HTML entity encoded, as are < and > (XSS prevention) • Classic ASP • Most pages set codepage to 1252, so ASP automatically does conversion/encoding for incoming values • All URLs on our desktop site are URL encoded using 1252 values • Node.js • Natively deal in UTF8, and convert when going to/from the DB • Edge.js/.NET handle much of it automatically, BUT we must do proper HTML entity encoding ourselves • Some manual character substitution is required (e.g. some chars have high codepoints in UTF8, but are below 256 in 1252) • Mobile URLs all use UTF8 encoding
  • 32. Log file management • IIS logs • All node traffic ends up in IIS logs, so you have unified log for the server • BUT, you can’t tell which traffic is actually handled by node (unless you use paths) • express/node logs • Handled automatically by iisnode: console and stderr • One per node process, with a handy index.html • Still trying to figure out best management strategy (tips welcome!)
  • 33. Git • Git and GitHub for Windows work great! • git-posh: PowerShell add-ins make life easier • Managing line-endings a small challenge • Most modules use unix endings; most of our code uses Windows • For now (but not ideal): set core.autocrlf to false • ‘git pull’ deploy • iisnode’s auto-refresh will automatically detect changes to JS and gracefully recycle processes while draining existing traffic
  • 34. Other libraries • Testing • mocha • should • supertest • Build/automation • grunt • Front-end • express • handlebars (hbs)
  • 35. Q + A
  • 36. Thanks! Questions? Curious to learn more? Brave enough to try this yourself? Email me! [email protected]