Setting Up VS 2015 for ASP.NET Core RTM 1.0 and Angular 2 RC 3

In this post I will explain how to setup Visual Studio 2015 in order to develop an Angular 2 RC3 application hosted inside ASP.NET Core project.  I of course read the quick start first.  You need to make sure to install VS 2015, you can use Community edition of you want.  You would also need to install ASP.NET Core.

Let’s get started.  Create new ASP.NET Core project.

SNAGHTML8ef77359_thumb1

Select empty template to keep everything simple for getting started demo.

SNAGHTML8ef841d5_thumb2

Let’s add static files support to serve a plain vanilla HTML page.  Open project.json file and add the static files line from below.

{ "dependencies": { "Microsoft.NETCore.App": { "version": "1.0.0", "type": "platform" }, "Microsoft.AspNetCore.Diagnostics": "1.0.0", "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", "Microsoft.AspNetCore.Server.Kestrel": "1.0.0", "Microsoft.Extensions.Logging.Console": "1.0.0", "Microsoft.AspNetCore.StaticFiles": "1.0.0" },

Now we can add a page which will host our Angular app.  Again, add just a plain HTML page under wwwroot folder, since that is the root of our deployable Core application.  You can just right click on that folder, add new item, then pick HTML page template.  I am calling mine index.html.  In order to see this page we need to turn off preloaded startup code and replace it with static files server.  Open up Startup.cs file and replace Configure method with the following.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseStaticFiles(); }

Now we can test the host page.  Open up VS command prompt and navigate to the project folder (NOT solution folder).  Type “dotnet run”.  Your app will compile and Kestrel web server with start.  Open browser and navigate to http://localhost:5000/index.html.  You will see the host page.  To make sure edit the index.html page and add some content to it.  It is time to start up Angular 2 portion.  I like adding NPM support to the project from command line.  From the same command prompt type “npm init” to initialize NPM file.  Follow the prompts, giving some meaningful answers.  Once this is done, switch to visual studio.  You will see that dependencies node in project explorer with have npm listed.  RIch click on that node and select open package.json. We need to add all Angular 2 scripts and dependencies by adding dependencies and devDependencies nodes as shown below.

{ "version": "1.0.0", "name": "angular-2-demo", "private": true, "devDependencies": { "typings": "^1.0.4" }, "dependencies": { "@angular/common": "^2.0.0-rc.3", "@angular/compiler": "^2.0.0-rc.3", "@angular/core": "^2.0.0-rc.3", "@angular/http": "^2.0.0-rc.3", "@angular/platform-browser": "^2.0.0-rc.3", "@angular/platform-browser-dynamic": "^2.0.0-rc.3", "@angular/router": "^3.0.0-alpha.8", "@angular/router-deprecated": "^2.0.0-rc.2", "@angular/upgrade": "^2.0.0-rc.3", "systemjs": "0.19.27", "core-js": "^2.4.0", "reflect-metadata": "^0.1.3", "rxjs": "5.0.0-beta.6", "zone.js": "^0.6.12" } }

All packages that start with @angular are angular core packages.  This is different from beta versions, which only had a single package.  Other packages are supporting packages for angular 2.  In order to proving TypeScript support, we will use typings NPM module, which is under devDependencies.  Give VS a minute to restore the packages after saving package.json file.

 

Now we need to install code JavaScript typings files for TypeScript.  At the same prompt type “typings install  dt~core-js –save –global”.  Once completed, you will see typings folder in project explorer, with core-js folder under it.

In the next step we will setup compilation options for TypeScript.  Add new item to the root of your project, selecting TypeScript Configuration File item template.  Change the content to look as follows.

{ "compileOnSave": true, "compilerOptions": { "noImplicitAny": false, "suppressImplicitAnyIndexErrors": true, "noEmitOnError": true, "removeComments": false, "sourceMap": true, "target": "es5", "emitDecoratorMetadata": true, "experimentalDecorators": true, "module": "system", "moduleResolution": "node" }, "exclude": [ "node_modules", "wwwroot" ] }

We are adding decorator options, which are required for Angular 2.  We are setting module to use systemjs, which is the default for all the demos I have seen.

Now I am going to setup gulp to make my development flow a bit smoother.  If you do not have gulp installed globally, type “npm install gulp”  at the command prompt.  After that you can add new item to the root of the project, selecting Gulp Configuration File item template.  Open gulpfile.js and replace the content with the following.

var gulp = require('gulp'); gulp.task('thirdparty', function () { gulp.src('./node_modules/core-js/**/*.js') .pipe(gulp.dest('./wwwroot/node_modules/core-js')); gulp.src('./node_modules/@angular/**/*.js') .pipe(gulp.dest('./wwwroot/node_modules/@angular')); gulp.src('./node_modules/zone.js/**/*.js') .pipe(gulp.dest('./wwwroot/node_modules/zone.js')); gulp.src('./node_modules/systemjs/**/*.js') .pipe(gulp.dest('./wwwroot/node_modules/systemjs')); gulp.src('./node_modules/reflect-metadata/**/*.js') .pipe(gulp.dest('./wwwroot/node_modules/reflect-metadata')); gulp.src('./node_modules/rxjs/**/*.js') .pipe(gulp.dest('./wwwroot/node_modules/rxjs')); }); gulp.task('copy', function () { gulp.src('./app/**/*.*') .pipe(gulp.dest('./wwwroot/app')); }); gulp.task('watch', function () { gulp.watch('./app/**/*.*', ['copy']); }); gulp.task('default', ['thirdparty', 'copy', 'watch']);

What is going on here?  Third party task copies necessary Angular 2 scripts from node_modules folder to the same folder under wwwroot.  Copy task copies our own application files, which will be placed under app folder under project root to wwwroot folder as well.  Finally, watch task will monitor the changes to app folder and re-copy the files wwwroot folder by firing copy task.  By default we will run all three tasks when we run gulp every time.

Time to write application code.  Create new folder called “app” under project root.  Create a subfolder called “shell”.  It will contain bootstrapping code.  Add new item to shell folder, picking TypeScript file template.  Change the name to main.  This will be our root component for Angular 2 application.  Here is the sample code you can add to it.

import { Component } from "@angular/core"; @Component({ selector: "app-shell", template: ` <div> Hello, {{title}} </div> ` }) export class Main { title: string; constructor() { this.title = "World!"; } }

If everything works OK, we will see a div with the words “Hello, World!” in it.  Now we need to bootstrap this main component.  Add new TypeScript file in the same folder, calling it bootstrapper.ts.  Here is its content.

import {Main} from "./main"; import { bootstrap } from "@angular/platform-browser-dynamic"; import {HTTP_PROVIDERS} from "@angular/http"; bootstrap(Main, [HTTP_PROVIDERS]);

All we are doing here is importing our own component.  Then we are importing Angular 2 bootstrapping in browser module as routing support.  Finally, we bootstrap the app, with our Main component as the root.  Ire commend that you build the app now to ensure there are no errors.

Now we need to configure systemjs module loader.  Create new JavaScript file called startup.js under wwwroot folder.  This is the only file we will add there.  We could also add it under app folder if we wanted to.  Here it its content.  This has changed slightly since RC 2.

(function (global) { // map tells the System loader where to look for things var map = { 'app': 'app', '@angular': 'node_modules/@angular', 'rxjs': 'node_modules/rxjs' }; // packages tells the System loader how to load when no filename and/or no extension var packages = { 'app': { main: 'shell/bootstrapper.js', defaultExtension: 'js' }, 'rxjs': { defaultExtension: 'js' } }; var ngPackageNames = [ 'common', 'compiler', 'core', 'http', 'platform-browser', 'platform-browser-dynamic', 'router', 'router-deprecated', 'upgrade', ]; // Add package entries for angular packages ngPackageNames.forEach(function (pkgName) { packages['@angular/' + pkgName] = { main: "bundles/" + pkgName + '.umd.js', defaultExtension: 'js' }; }); var config = { map: map, packages: packages } System.config(config); System.import('app').catch(function (err) { console.error(err); }); })(this);

We are specifying our app folder as a package for system js.  We are also adding core angular packages, including rxjs, reactive extensions.  We are configuring systemjs by calling config method and passing our packages map.  Finally we are starting app package.  Previously in the same file we specified that the entry point for it is bootstrapper.js.

It is time to edit our index.html page and add the necessary scripts.

<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Angular 2</title> </head> <body> <app-shell></app-shell> <script src="node_modules/zone.js/dist/zone.js"></script> <script src="node_modules/reflect-metadata/Reflect.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="startup.js"></script> </body> </html>

At the same time we added an element called <app-shell> which matches the selector we added onto the definition of our Main component.  Let’s build the app one more time.

Get back to the command line and type “gulp” to copy our files around.  Open up second VS command prompt, navigate to the same project folder and type “dotnet run” to start the server.  Now navigate to http://localhost:5000/index.html to see the results of your hard work.  You should see “hello, world’’.  Go ahead and edit main.ts and change the title.  Refresh the page again.  You should see new title.  Our environment and our first app are DONE!!!

You can download the sample project here.  You will need to restore all packages, npm and .NET Core to run it.

Enjoy.