ASP.NET Core and Angular 2

ASP.NET Core and Angular 2 with TypeScript Writing web applications nowadays is becoming a bit more complex as the frameworks evolve taking advantage of other frameworks/tools. That’s the case of Angular 2 (which was developed using TypeScript) and ASP.NET Core with take advantage of npm and bower for the dependencies as well as gulp for performing some tasks. In this article, I will show you how to configure ASP.NET Core and Angular 2 using TypeScript to create your rich client-side apps.

ASP.NET Core is a new open-source and cross-platform framework for building modern cloud-based Web applications using .NET. It was built from the ground up to provide an optimized development framework for apps that are either deployed to the cloud or run on-premises. It consists of modular components with minimal overhead, so you retain flexibility while constructing your solutions. It has evolve taking concepts from node.js and other platforms.

Angular is a development platform for building mobile and desktop web applications using modern web standards. Is an open-source JavaScript framework that augments browser-based applications with Model-View-Controller (MVC) capability, facilitating both development and testing. If you know the previous version, Angular 2 might seems to be a completely different framework, but the main concepts are there. One of the main differentiators is that Angular 2 is written in TypeScript, a superset of JavaScript that compiles to clean JavaScript output. Because its transcompiled to JavaScript, you can use the framework from JavaScript as well as from TypeScript itself.

Now, let’s start configuring a project with both technologies, ASP.NET Core and Angular 2. I’ll assume that you have an ASP.NET Core project created, with MVC configured, although this is not a requirement for using both technologies together. If you need to create a new project, just use the Web Application template in Visual Studio or using the aspnet’s Yeoman generator.

In order to have ASP.NET Core and Angular 2 running together, you’ll need to have the Angular 2 dependencies in place. Angular 2 is distributed using the npm package manager. Open the npm’s package.json file located at the root of your project and add the following dependencies to it.

  "dependencies": {
    "angular2": "2.0.0-beta.9",
    "systemjs": "0.19.24",
    "es6-shim": "^0.33.3",
    "rxjs": "5.0.0-beta.2"
  },

If you are using Visual Studio, after saving the file, it will download the new dependencies (else, just run npm install in the same folder). The files will be downloaded in the node_modules folder, which is not served as default by ASP.NET. You could configure ASP.NET to serve this folder, but it’s better to just copy the files to the wwwroot folder using a gulp tasks. Add the following code in the gulpfile.js. This will add a few tasks to copy each of the dependencies to the wwwroot/lib/npmlibs folder, as well as a task named copy-deps that will run all the others.

paths.npmSrc = "./node_modules/";
paths.npmLibs = paths.webroot + "lib/npmlibs/";

gulp.task("copy-deps:systemjs", function () {
    return gulp.src(paths.npmSrc + '/systemjs/dist/**/*.*', { base: paths.npmSrc + '/systemjs/dist/' })
         .pipe(gulp.dest(paths.npmLibs + '/systemjs/'));
});

gulp.task("copy-deps:angular2", function () {
    return gulp.src(paths.npmSrc + '/angular2/bundles/**/*.js', { base: paths.npmSrc + '/angular2/bundles/' })
         .pipe(gulp.dest(paths.npmLibs + '/angular2/'));
});

gulp.task("copy-deps:es6-shim", function () {
    return gulp.src(paths.npmSrc + '/es6-shim/es6-sh*', { base: paths.npmSrc + '/es6-shim/' })
         .pipe(gulp.dest(paths.npmLibs + '/es6-shim/'));
});

gulp.task("copy-deps:rxjs", function () {
    return gulp.src(paths.npmSrc + '/rxjs/bundles/*.*', { base: paths.npmSrc + '/rxjs/bundles/' })
         .pipe(gulp.dest(paths.npmLibs + '/rxjs/'));
});

gulp.task("copy-deps", ["copy-deps:rxjs", 'copy-deps:angular2', 'copy-deps:systemjs', 'copy-deps:es6-shim']);

Now that you have the Angular 2 dependencies ready to be served in your project, you need to add them to your site so you can start using it. Open the _Layout.cshtml file located at Views/Shared/ and add the following code at the end of your head tag. Note that the polyfills and shims are declared before system.js and angular2. Additionally, in this case I added the router bundle to show you that you need to add additional bundles like Http and router (if you don’t need it, you can remove it).

<environment names="Development">
  <script src="~/lib/npmlibs/es6-shim/es6-shim.js"></script>
  <script src="~/lib/npmlibs/systemjs/system-polyfills.src.js"></script>
  <script src="~/lib/npmlibs/angular2/angular2-polyfills.js"></script>

  <script src="~/lib/npmlibs/systemjs/system.src.js"></script>
  <script src="~/lib/npmlibs/rxjs/Rx.js"></script>
  <script src="~/lib/npmlibs/angular2/angular2.js"></script>
  <script src="~/lib/npmlibs/angular2/router.js"></script>
</environment>

<environment names="Staging,Production">
  <script src="~/lib/npmlibs/es6-shim/es6-shim.min.js"></script>
  <script src="~/lib/npmlibs/systemjs/system-polyfills.js"></script>
  <script src="~/lib/npmlibs/angular2/angular2-polyfills.min.js"></script>

  <script src="~/lib/npmlibs/systemjs/system.src.js"></script>
  <script src="~/lib/npmlibs/rxjs/Rx.min.js"></script>
  <script src="~/lib/npmlibs/angular2/angular2.min.js"></script>
  <script src="~/lib/npmlibs/angular2/router.min.js"></script>
</environment>

Now, you have the dependencies in place for your ASP.NET Core and Angular 2 application, but if you plan to use TypeScript in your project you need to perform a few steps more. Create a tsconfig.json file in the root of your project to configure the compiler to include decorators and specify the use of system.js for module resolution.

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

If you try to compile the project now, you might find some TypeScript issues because Promise and other types are not defined. Add the es6-shim’s TypeScript definitions to your project. To do this, download the one from the DefinitelyTyped repository and add it to your project (you don’t need to serve this file, so you can have a ts folder with it in the root of the project).

Finally, let’s create the base structure for an Angular 2 application. We’ll create two TypeScript files inside a new folder named app under wwwroot. The first file will be the component, which will be a basic Hello World component. Create a file named app.component.ts inside the wwwroot/app folder and add the following code.

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }

Now, create a file named boot.ts also inside the wwwroot/app folder and add the following code. This file is the one that you will load as start point of your app.

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);

Open the view where you plan to add your Angular app, I will choose the Views/Home/Index.cshtml view. Add the angular component tag (e.g. <my-app></my-app>) to the html and add the following script section to the end of the file. This script will configure System.js (specifying to use js files whenever the extension it’s not defined) as well as initialize the Angular 2 app by importing the boot.js file located at the app folder.

@section Scripts {
    <script>
        System.config({
            packages: {
                'app': { defaultExtension: 'js' },
                'lib': { defaultExtension: 'js' },
            },
        });

        System.import('app/boot')
            .then(null, console.error.bind(console));
    </script>
}

You have the base structure for an ASP.NET Core and Angular 2 application. You can find the full code in my Angular2ASPNETCoreBaseApp repository. Now, you just need to start developing your awesome ideas.

Updated: I created a new post explaining how to configure routing to use Angular 2 Routing component.

Updated 2: I created a new post explaining how to configure Angular2’s Http service and ASP.NET to consume the MVC APIs.