Getting Started with ASP NET Core 1 and Angular 2 in Visual Studio 2015

The goal of this post is to set up a Visual Studio 2015 project with ASP NET Core 1 and Angular 2 Typescript that can be used as a template for all my projects.

ASP NET Core1 Logo         angular2Logo

The whole code is available on GitHub: https://github.com/softwarejc/angular2-aspmvc-core1-getting-started

We will use npm (Node Package Manager) to add our dependencies and we will configure the typescript transpiler integrated in Visual Studio. We will also configure a gulp task to bundle our javascript an css dependencies.

Content

  • Introduction
  • Install Pre-requisites
  • Create an empty ASP Core 1 project
  • Auto transpile Typescript after save
  • Add Angular 2 with npm
  • Set up gulp task to bundle dependencies

Introduction

The former ASP.NET 5 was renamed to .NET Core 1. It is a modular Microsoft runtime library implementation that includes a subset of the .NET Framework.

.NET Core 1 was written from scratch. It has a lot of advantages, for example it is lighter, open-source and multi-platform: Mac, Linux and Windows.

Although the version 1 is in Release Candidate there are some ASP.NET 4.6 features missing, like SignalR.

It is up to you to choose a mature Framework like ASP.NET 4.6 or a modern one like ASP.NET Core 1… you can read more about it in this post by Scott Hanselman. I copied the following diagram from that post :-).

ASPNET Core 1

Install Pre-requisites

There are some problems in Windows using npm version 2. It nest dependencies and ends up having too long paths for Windows. Let’s start updating npm to version 3 and configuring Visual Studio to use it.

The first thing that we should do is to install Python version 2.7.X and NodeJS version 4.2.X. Remember the path where you install NodeJS, we will need it later.

Now open a command line and update npm:

npm install npm -g

Check your npm version:

npm -v

The version should be higher than 3.X.X.

Open visual studio and add the path where NodeJS is installed as the first path to look for external tools (at the top). The next time that Visual Studio has to restore a node package it will start looking for nodejs.exe in that path. The version we just installed will be found and used.

Configure VS to use npm 3

Create an empty ASP NET Core 1 project

Let’s create our project and configure a very simple server-side code.

In Visual Studio 2015 Update 1 ASP NET Core 1 is still called ASP NET 5. Create a new project and select the WebAPI template. Our project will have a SPA that will call a WebAPI controller to get a message.

Create ASPNET 5 Project

 

Delete the Project_Readme.html and update the values controller with this simple WebAPI controller that returns a hello message and the server UTC Time:

We will call this method later from angular to check that the communication between our SPA and the server works. For now we can call it from the browser to check it. Run the application and write something like this in your browser using your configured port:

http://localhost:10137/api/hello

You should see something like:

apiTest

You can also pass your name to check that the server receive your parameters:

http://localhost:10137/api/hello?name=JuanCarlos

The file Startup.cs contains the configuration of the middleware. We will see in a future post how it works and how to configure it to use features like authentication. The default configuration when you select a WebAPI project template is ok for us.

Auto transpile Typescript after save

We can tell Visual Studio to auto transpile always that we edit and save a typescript file enabling:

“Automatically compile TypeScript files which are not part of a project”
ts Compile on Save

Our files will be part of the project… but this is an easy way to make Visual Studio auto transpile. Running typescript compiler in watch mode is an alternative… but I like this solution because I have everything integrated in Visual Studio.

If you know a better way please leave me a comment. 🙂

We will have a tsconfig.json file on the project root of our project to configure typescript, Visual Studio will use that file and not the settings that we configure in Options:

Add Angular 2 with npm

The application that we will use as an example will be a simple application that call the server to get a message and will display using Angular 2.

Let’s add Angular 2 and other dependencies to npm, we need a file called “package.json” on the root of our project:

Save the file and Visual Studio will create node_modules folder and download all dependencies for you.

It is out of the scope of this post to explain how Angular 2 works you can read more about it here. But basically we define a component that we can use in our index.

<hello></hello>

This component is a html view that has bindings to its code behind or “view-model”.

hello.view.html

hello.component.ts

The hello.component uses the service hello.service that makes REST calls to the server and returns Observable<T>.

hello.service.ts

We need to “start” / “bootstrap” our application. We will use System.JS to do that. This is this index.html where we “start” our Angular 2 app:

index.html

This is the piece of code of index.html that bootstrap our application:

System.import(‘./app/bootstrap’).then(null, console.error.bind(console));

And this is our bootstrap.ts:

Set up gulp task to bundle dependencies

Our index.html only references a style.css and a deps.js file. Those files are a bundle with all our dependencies. To create that bundle we will use gulp. We need this gulpfile.js on the root of our project:

We want to create our bundles automatically when we rebuild or clean the project (not in every build).

Open Task Runner Explorer and bind the clean and bundle tasks to the “Clean” Visual Studio event:

GulpBinding

This will trigger our tasks always that we clean or rebuild our solution. You can also add the bundle task to the “Before Build” event… but it can takes 8-10 seconds and normally the dependencies are not changing in every build.

We have a pre-configured project that hopefully will save us some time in the future!

If you know how to make it better please leave me a comment!

Have fun with ASP.NET Core and Angular 2!

TypeScript – Introduction

It is time to start learning the language of the future: TypeScript

There are a lot of online resources to learn the language, here I just share a small piece of code with the basics of the language:

//---------------
// 1 Basic types
//---------------
var myBooleanVar: boolean = false;
var myNumberVar: number = 29;
var myStringVar: string = "Juan Carlos";

// 1.1 Arrays
var myArrayVar: number[] = [1, 2, 3];
var myArrayVar: Array<number> = [1, 2, 3];

// 1.2 Enumerations
enum Direction { Up, Down, Left, Right };
var myDirectionVar: Direction = Direction.Up;

// 1.3 Any
var myAnyTypeVar: any = "I am a text";
myAnyTypeVar = false; // before it was string, now a boolean

// 1.4 Void
function log(msg: string): void {
	console.log(msg);
	// this functions returns nothing
}

//---------------
// 2 Interfaces
//---------------
interface IPerson {
	name: string;
	age?: number; // optional parameter
}

function sayHello(person: IPerson) {
	console.log(person.name);
	if (person.age) {
		console.log("Your age is " + person.age)
	}
}

// myVar has no type but has all the fields that a 
// Person should have. Therefore is a Person (duck typing)
var myVar = { name: "Juan Carlos" };
sayHello(myVar);

// 2.1 Interfaces extends
interface IStudent extends IPerson {
	studentId: number;
}

// 2.2 Interfaces indexes
interface Friends {
	[index: number]: IPerson;
	length: number;
}

// 2.3 Interfaces with functions/methods
interface PeopleService {
	getPersonId(person: IPerson): number;
	// a function that has a Person has parameter and return a boolean
	(newFriend: IPerson): boolean;
}

//---------------
// 3 Classes
//---------------

// 3.1 Interfaces implementation
interface IVehicle {
	move(direction: Direction);
	registrationNumber: number;
}

class Vehicle implements IVehicle {
	registrationNumber: number;

    constructor(id: number) {
		this.registrationNumber = id;
	}

	move(direction: Direction) {
		console.log("Moving" + direction);
	}
}

// 3.2 Classes Extends
class Car extends Vehicle {
	// by default all public
	private numberOfWheels: number = 4;
	speed: number = 120;
	
	// method override
	move(direction: Direction) {
		console.log("Speed = " + this.speed);
		// call base
		super.move(direction);
	}
}

var myCar: IVehicle = new Car(1234);
myCar.move(Direction.Up);

// 3.3 Classes, define class fields in constructor 
// add public or private to the parameter
class Motorbike implements IVehicle {
	private numberOfWheels: number = 2;
	
	// the constructor defines a public field 'registrationNumber'
    constructor(
		public registrationNumber: number,
		// define a private field with the value passed as parameter
		// if no value specified, the field as the value 90
		private speed: number = 90) {
	}

	move(direction: Direction) {
		console.log("Moving the motorbike" + direction);
	}
}

// 3.4 Accesors and static fields
class Plane implements IVehicle {
	// Static field
	static minSpeed: number = 100;
	static speedCorrectionFactor: number = 0.8;
	
	constructor(
		public registrationNumber: number,
		private _speed: number = 300) {
	}

	// speed getter
	get getSpeed(): number {
		// for some reason the public speed is 80%
		// of the realone
        return this._speed * Plane.speedCorrectionFactor;
    }

	// speed setter
    set setSpeed(newSpeed: number) {
		if (newSpeed > Plane.minSpeed) {
			this._speed = newSpeed;
		}
	}

	move(direction: Direction) {
		console.log("Flying! " + direction);
	}
}

Resources:
http://www.typescriptlang.org/Handbook