How to set up an Angular 2 and TypeScript project with Visual Studio 2017

You can see the source code of this tutorial on my GitHub repository, here: Angular2 web app source code on GitHub.

Versions:

Create a new ASP.NET Core web application

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

How to setup an Angular 2 and TypeScript project with Visual Studio 2017
How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Create the MVC folder structure

What is MVC?

MVC, for Model-View-Controller, is an architectural pattern that separates an application into three main components:

The purpose of this architectural pattern is to build applications that are easily maintainable and testable, by separating the different components. A best practice is to pair this architectural pattern with an N-Tier layered architecture.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Create a folder to put the TypeScript files in

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Set TypeScript configuration

Although TypeScript is the primary language for Angular application development, it can't be executed by browsers directly; TypeScript must be "transpiled" into JavaScript using the tsc compiler, which requires some configuration.

To configure the TypeScript compiler and set up your environment, you have two files to add:

tsconfig.json

The TypeScript configuration file is required to guide the TypeScript compiler as it generates JavaScript files which are used by the browser.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

This is the default content when you add the tsconfig.json file to your project:


{
  "compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ]
}

So, what do we have in this file?

The compilerOptions section is optional; if it is null, the default values will be used. You can find the details of this section here: http://www.typescriptlang.org/docs/handbook/compiler-options.html

If you want more information about this file, you can read the documentation: http://www.typescriptlang.org/docs/handbook/tsconfig-json.html

For our project, we have to specify where tsc can find our TypeScript files, where we want it to generate the JavaScript files, and some other settings. This is the content we need:


{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": true,
    "suppressImplicitAnyIndexErrors": true,
    "rootDir": "App",
    "outDir": "wwwroot/app"
  },
  "compileOnSave": true,
  "angularCompilerOptions": {
    "genDir": ".",
    "debug": true
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ]
}

TypeScript type definition files

Many JavaScript libraries, such as jQuery, extend the JavaScript environment with syntax and features that the TypeScript compiler doesn't recognize natively. This file tells the compiler about the libraries you load.


{
  "globalDependencies": {
    "jquery": "registry:dt/jquery",
    "jasmine": "registry:dt/jasmine"
  }
}

Add a NPM configuration file

What is NPM?

NPM, for Node Package Manager, is a utility that helps with JavaScript open source package installation, versioning and dependency management. NPM is distributed with Node.js, which is an asynchronous event-driven JavaScript runtime designed to build scalable network applications.

Angular 2 and its dependencies are delivered through NPM, so you need to add the NPM configuration file, package.json, to your project.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

You will have an empty NPM configuration file:


{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
  }
}

To add Angular 2 and its dependencies to your project, you have to add some dependencies to your NPM configuration file:


{
  "version": "1.0.0",
  "description": "NO404 administration panel",
  "name": "no404 backoffice",
  "readme": "no404 backoffice",
  "license": "MIT",
  "dependencies": {
    "@angular/common": "~2.2.0",
    "@angular/compiler": "~2.2.0",
    "@angular/core": "~2.2.0",
    "@angular/forms": "~2.2.0",
    "@angular/http": "~2.2.0",
    "@angular/platform-browser": "~2.2.0",
    "@angular/platform-browser-dynamic": "~2.2.0",
    "@angular/router": "~3.2.0",
    "@angular/upgrade": "~2.2.0",

    "angular-in-memory-web-api": "~0.1.15",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.39",
    "zone.js": "^0.6.25",

    "bower": "1.7.9",
    "jquery": "^3.1.0"
  },
  "devDependencies": {
    "@types/core-js": "^0.9.34",
    "@types/node": "^6.0.45",
    "concurrently": "^2.2.0",
    "gulp": ">=3.9.1",
    "gulp-concat": ">=2.5.2",
    "gulp-copy": ">=0.0.2",
    "gulp-cssmin": ">=0.1.7",
    "gulp-load-plugins": "^1.3.0",
    "gulp-rename": ">=1.2.2",
    "gulp-rimraf": ">=0.2.0",
    "gulp-tsc": ">=1.2.0",
    "gulp-uglify": ">=1.2.0",
    "gulp-watch": ">=4.3.9",
    "gulp-clean-css": "^3.0.4",
    "gulp-clean": "^0.3.2",
    "jasmine-core": "2.4.1",
    "tslint": "^3.15.1",
    "typescript": "^2.0.0",
    "typings": "^1.3.2"
  },
  "scripts": {
    "start": "concurrently \"npm run gulp\" \"npm run watch\" \"npm run tsc:w\"",
    "postinstall": "typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "typings": "typings",
    "gulp": "gulp",
    "watch": "gulp watch",
    "ngc": "ngc"
  }
}

If you open your web application in the file explorer, you can now see a node_modules folder with some external dependencies in it:

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Add Gulp

Add gulp.config.js


module.exports = function () {

    var base = {
        webroot: "./wwwroot/",
        node_modules: "./node_modules/"
    };

    var config = {
        /**
         * Files paths
         */
        angular: base.node_modules + "@angular/**/*.js",
        app: "App/**/*.*",
        appDest: base.webroot + "app",
        js: base.webroot + "js/*.js",
        jsDest: base.webroot + 'js',
        css: base.webroot + "css/*.css",
        cssDest: base.webroot + 'css',
        lib: base.webroot + "lib/",
        node_modules: base.node_modules,
        angularWebApi: base.node_modules + "angular2-in-memory-web-api/*.js",
        corejs: base.node_modules + "core-js/client/shim*.js",
        zonejs: base.node_modules + "zone.js/dist/zone*.js",
        reflectjs: base.node_modules + "reflect-metadata/Reflect*.js",
        systemjs: base.node_modules + "systemjs/dist/*.js",
        rxjs: base.node_modules + "rxjs/**/*.js",
        jasminejs: base.node_modules + "jasmine-core/lib/jasmine-core/*.*"
    };

    return config;
};

Add the gulp configuration file

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

/*
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. https://go.microsoft.com/fwlink/?LinkId=518007
*/

var gulp = require('gulp');

gulp.task('default', function () {
    // place code for your default task here
});

/// 
"use strict";

var gulp = require('gulp');
var config = require('./gulp.config')();
var cleanCSS = require('gulp-clean-css');
var clean = require('gulp-clean');
var rename = require('gulp-rename');
var $ = require('gulp-load-plugins')({ lazy: true });

gulp.task("clean:js", function (cb) {
    //return $.rimraf('wwwroot/js/*.min.js', cb);
    return gulp.src('wwwroot/js/*.min.js', { read: false }).pipe(clean());
});

gulp.task("clean:css", function (cb) {
    //return $.rimraf('wwwroot/css/*.min.css', cb);
    return gulp.src('wwwroot/css/*.min.css', { read: false }).pipe(clean());
});

gulp.task('minify:css', function () {
    return gulp.src(config.css)
        .pipe(cleanCSS())
        .pipe(rename({
            suffix: '.min'
        }))
        .pipe(gulp.dest(config.cssDest));
});

gulp.task("clean", ["clean:js", "clean:css"]);
gulp.task('minify', ['minify:css']);

gulp.task("copy:angular", function () {

    return gulp.src(config.angular,
        { base: config.node_modules + "@angular/" })
        .pipe(gulp.dest(config.lib + "@angular/"));
});

gulp.task("copy:angularWebApi", function () {
    return gulp.src(config.angularWebApi,
        { base: config.node_modules })
        .pipe(gulp.dest(config.lib));
});

gulp.task("copy:corejs", function () {
    return gulp.src(config.corejs,
        { base: config.node_modules })
        .pipe(gulp.dest(config.lib));
});

gulp.task("copy:zonejs", function () {
    return gulp.src(config.zonejs,
        { base: config.node_modules })
        .pipe(gulp.dest(config.lib));
});

gulp.task("copy:reflectjs", function () {
    return gulp.src(config.reflectjs,
        { base: config.node_modules })
        .pipe(gulp.dest(config.lib));
});

gulp.task("copy:systemjs", function () {
    return gulp.src(config.systemjs,
        { base: config.node_modules })
        .pipe(gulp.dest(config.lib));
});

gulp.task("copy:rxjs", function () {
    return gulp.src(config.rxjs,
        { base: config.node_modules })
        .pipe(gulp.dest(config.lib));
});

gulp.task("copy:app", function () {
    return gulp.src(config.app)
        .pipe(gulp.dest(config.appDest));
});

gulp.task("copy:jasmine", function () {
    return gulp.src(config.jasminejs,
        { base: config.node_modules + "jasmine-core/lib" })
        .pipe(gulp.dest(config.lib));
});

gulp.task("dependencies", [
    "copy:angular",
    "copy:angularWebApi",
    "copy:corejs",
    "copy:zonejs",
    "copy:reflectjs",
    "copy:systemjs",
    "copy:rxjs",
    "copy:jasmine",
    "copy:app"
]);

gulp.task("watch", function () {
    return $.watch(config.app)
        .pipe(gulp.dest(config.appDest));
});

gulp.task("default", ["clean", 'minify', "dependencies"]);

You can now see a "default" task in the task explorer

How to setup an Angular 2 and TypeScript project with Visual Studio 2017
How to setup an Angular 2 and TypeScript project with Visual Studio 2017

You can see that the dependencies have been added to the lib folder.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Add Bower

Add Bower to add the jQuery and Bootstrap dependencies

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Create TypeScript app files

Create the main file to bootstrap your application


import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

const platform = platformBrowserDynamic();

platform.bootstrapModule(AppModule);

Add app.module.ts


import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
    imports: [
        BrowserModule,
        HttpModule,
        AppRoutingModule
    ],
    declarations: [
        AppComponent,
        HomeComponent
    ],
    bootstrap: [AppComponent],
    providers: [
    ]
})
export class AppModule { }

Add app.component.ts


import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'no404-bo-app',
    template: `
        <div class="container">
            <nav>
                <a routerLink="home" routerLinkActive="active">Home</a>
            </nav>
            <router-outlet></router-outlet>
        </div>
    `,
    providers: []
})
export class AppComponent implements OnInit {

    constructor() {
        console.log('AppComponent -> constructor');
    }

    ngOnInit() {
        console.log('AppComponent -> ngOnInit');
    }
}

Create the routing module (app-routing.module.ts)


import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';

export const routes: Routes = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: HomeComponent }
];

@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule { }

And add the home component


import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'home',
    template: `
        <h1>Home</h1>
        <p>Hello you !</p>
    `
})
export class HomeComponent implements OnInit {
    
    constructor() {
        console.log('HomeComponent -> constructor');

    }

    ngOnInit() {
        console.log('HomeComponent -> ngOnInit');
        
    }
}
How to setup an Angular 2 and TypeScript project with Visual Studio 2017

If you build your solution, you can see that your output app folder has been populated with some JavaScript files generated from your TypeScript files.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

If you launch your website, you will have something like this:

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

No trace in the console, and not the content of our TypeScript templates either. Why? Because we have to tell our website startup that we want to load our TypeScript application.

Configure your web app to display your Angular application

Check if your application is targeting the .NETCoreApp framework, version 1.1; if not, update it.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Check if the NuGet dependencies are targeting the latest version; if not, update them all.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Add the NuGet dependencies you need:

Microsoft.AspNetCore.StaticFiles is a middleware for handling requests for file system resources, including files and directories, that enables your application to serve HTML and JavaScript files, indispensable elements of an Angular application.

For more information about Microsoft.AspNetCore.StaticFiles, you can see:

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

Once you have added the Microsoft.AspNetCore.StaticFiles package, you have to enable your app to serve static files. This happens in the Configure method of the startup class, using app.UseStaticFiles().


public void ConfigureServices(IServiceCollection services)
{
    services
               .AddMvc()
               .AddJsonOptions(options => options.SerializerSettings.ContractResolver =
                   new DefaultContractResolver());
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseCors(
        builder => builder.AllowAnyOrigin()
            .AllowAnyHeader()
            .AllowAnyMethod()
            .AllowCredentials())
        .UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Add the Home controller with the view

Add HomeController and Index.cshtml in the home folder of the Views.

Add systemjs.config.js javascript file in your js folder of the wwwroot folder.


(function (global) {
    System.config({
        paths: {
            'npm:': 'lib/'
        },
        map: {
            app: 'app',
            '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
            '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
            '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
            '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
            '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
            '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
            '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
            '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
            'rxjs': 'npm:rxjs',
            'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
        },
        packages: {
            app: {
                main: './main.js',
                defaultExtension: 'js'
            },
            rxjs: {
                defaultExtension: 'js'
            },
            'angular2-in-memory-web-api': {
                main: './index.js',
                defaultExtension: 'js'
            }
        }
    });
})(this);

Set up the content of your Index.cshtml view to load the UI dependencies you need, and load your Angular application.


<!DOCTYPE html>
<html>
<head>
    <base href="/">
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>

    <script src="~/lib/core-js/client/shim.js"></script>
    <script src="~/lib/zone.js/dist/zone.js"></script>
    <script src="~/lib/reflect-metadata/Reflect.js"></script>
    <script src="~/lib/systemjs/dist/system.src.js"></script>

    <script src="~/js/systemjs.config.js"></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
</head>
<body>
    <div class="container">
        <no404-bo-app>Loading...</no404-bo-app>
    </div>
</body>
</html>

And it works!

If you launch your application now, you can see that everything is working and your Angular 2 application is correctly loaded.

How to setup an Angular 2 and TypeScript project with Visual Studio 2017

You can now implement your Angular 2 application to do what you have to do. Enjoy :)




PS: If you see a strange C folder appearing in your solution, follow this tutorial: Update ASP.NET Core web application to .NETCoreApp1.1 causes a project loading failure

How to setup an Angular 2 and TypeScript project with Visual Studio 2017
February 11, 2017
  • ASP.NET Core
  • Angular
  • Angular2
  • TypeScript
  • NPM
  • Node.js
  • MVC