ProudMonkey

ASP.NET Core: Getting Started with AngularJS 2

Last year I wrote an article about “ASP.NET 5: Jump Start to AngularJS with MVC 6 Web API”. This article will walk you through on how to get started with AngularJS 2 in ASP.NET Core (a.k.a ASP.NET 5).

In this article you will basically learn how to set up the required tools needed for you to run a simple Angular 2 App within ASP.NET Core. By simple, I mean there’s no database or data model involved as I’m trying to keep this article as simple as possible so starters can easily follow. In my next article, I'll demonstrate how to build an app that uses ASP.NET Core Web API to work with data, but at this point we’ll just start with the basics first.

Before we dig further let’s get to know Angular 2 first.

Angular 2 has some essential changes compared to Angular 1 and it is entirely written in TypeScript. Angular 2 is the second major installment of AngularJS, a world-renowned development framework born with the idea of giving the coder the toolbox needed to build reactive, cross-platform web-based apps optimized for desktop and mobile: it features a structure-rich templating approach which is based upon a natural, easy-to-write and readable syntax.

To learn more or if you want to contribute, feel free to visit the official Github repository here.

Let’s Get Started!

Fire up Visual Studio 2015 and select File > New Project. In the dialog, under Templates > Visual C# > Web, select ASP.NET Web Application as shown in the figure below:

Figure 1: New Project Dialog

You can name your project to whatever you like but for this demo I simply named it as “AngularJS2Demo” for simplicity. Click OK to bring up the following dialog below:
Figure 2: New ASP.NET Project dialog

Select “Web API” under "ASP.NET 5 Preview Templates" and then click OK to let Visual Studio create the project for you.

You might be wondering why we didn’t choose one of the ASP.NET 4.5 Templates – especially the Single Page Application option, which sounds like it would be the perfect choice for what we’re up to – you should take a look to the brand-new features introduced with ASP.NET Core, most importantly the built-in support of modern client-side utilities such as, to name a couple, NPM and Bower. If you never heard of them do not worry, as we’ll get to them soon enough.

The figure below shows the newly created project.

Figure 3: New default ASP.NET Core Empty project structure

If you already know the core significant changes of ASP.NET Core then you may skip this part, but for those who are new to ASP.NET Core then I would like to highlight some of those changes. If you have worked with previous versions of ASP.NET before then you will notice that the new project structure is totally different. The project now includes these files:

  • src folder: contains all projects that contain source code that make up your application.
  • global.json: this is where you put solution-level settings and allows you to do project-to-project references.
  • wwwroot: is a folder in which all your static files will be placed. These are the assets that the web app will serve directly to the clients, including HTML, CSS, Image and JavaScript files.
  • project.json: contains project settings.
  • startup.cs: this is where you put your startup and configuration code.

For details about the new features in ASP.NET Core check out this article: Introducing ASP.NET 5: The New ASP.NET in Town!

Adding the Scripts folder

The next thing to do is to create a new folder called “Scripts”. To do this, just right click on the project and select Add > New Folder. This folder will contain all the JavaScript files needed in our application, then we’ll combine and minify these using a JavaScript Task Runner such as Grunt: this way we’ll make sure that the resulting file will be added to the wwwroot folder automatically after each build. The figure below shows the project structure with the newly added folder:

Figure 4: The Scripts folder

Getting the Required Packages

ASP.NET Core supports three (3) main package managers: NuGet, NPM and Bower.

Package Manager

A package manager enables you to easily gather all resources that you need for building an application. In other words, you can use the package manager to automatically download all the resources and their dependencies instead of manually downloading project dependencies such as jQuery, Bootstrap and AngularJS from the web/internet.

NuGet: NuGet manages .NET packages such as Entity Framework, ASP.NET MVC and so on. You typically specify the NuGet packages that your application requires within a "project.json" file.

NPM: NPM is one of the newly supported package managers in ASP.NET Core. This package manager was originally created for managing packages for the open-source NodeJS framework. The package.json is the file that manages your project's NPM packages.

Bower: Bower is another supported package manager in ASP.NET Core. It was created by Twitter that is designed to support front-end development. You can use Bower to manage client-side resources such as jQuery, Angular and Bootstrap.

Adding StaticFiles Dependency

We need to add reference to Microsoft.AspNetCore.StaticFiles so you won't end up getting 404 File Not Found error in the browser. If you arleady have this reference then you can ignore this step. Now open your project.json file and the following package:

"Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final"

Then in call the UseStaticFiles method in the Configure() function of the Startup.cs file:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){  
      app.UseStaticFiles();
}
Introducing TypeScript

Taken from the documentation- TypeScript is a free and open source programming language developed and maintained by Microsoft. It is a strict superset of JavaScript, and adds optional static typing and class-based object-oriented programming to the language. Check out the official site of TypeScript for more details.

In this particular demo we are going to use TypeScript for a number of good reasons, the most important of them are:

  • TypeScript has a number of features over JavaScript, such as: static typing, classes and interfaces. Using it in Visual Studio also enables a strong intelliSense which gives us the chance to benefit from the built-in IntelliSense, together with its distinctive features, will allow us to spot for most programming errors as we type the code, potentially saving a great amount of time.

  • For a large client-side project, TypeScript will allow us to produce a more robust code, which will be also fully deployable anywhere a plain JavaScript file would run. As a matter of fact, since TypeScript is a superset of JavaScript it can be used alongside any JavaScript code without problems.

Configuring TypeScript

Let’s add a new file called “tsconfig.json”. Right click on the project and then select Add > New Item; Switch to Client Side option from the left pane then select “TypeScript JSON Configuration File” as shown in the figure below:
Figure 5: Adding tsconfig.json file

Click Add to generate the default configuration for you. Now replace the default settings with the following:

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

These configuration settings will influence how the IntelliSense and our external TypeScript compiler will work, two things that will help us big time.

For this example we need to use NPM to install the resources we need in our application such as Grunt and the Grunt plugins. To do this just right-click in the Project and select Add > New Item. In the dialog select “NPM configuration file” as shown in the figure below:

Figure 6: Adding package.json file

Click Add to generate the file with the default settings for you. Modify the “package.json” file by adding the following dependencies:

{
  "version": "1.0.0",
  "name": "AngularJS2Demo",
  "private": true,
  "dependencies": {
  },

  "devDependencies": {
    "grunt": "1.0.1",
    "grunt-contrib-copy": "1.0.0",
    "grunt-contrib-uglify": "1.0.1",
    "grunt-contrib-watch": "1.0.0",
    "grunt-ts": "5.5.1"
  }
}

Keep in mind that, at the time of writing, Grunt 1.0.1 is the latest version. You can check the most recent build by checking the Visual Studio IntelliSense, which happens to work here and is even able to perform an impressive real-time update checks upon each package’s latest build.
Note that you aren’t forced to input precise build numbers, as you can also use the standard npmjs syntax to specify auto-update rules bound to custom version ranges using the supported prefixes, such as:

  • The Tilde (~). ~1.0.1 will match all 1.1.x versions, excluding 1.2.0, 1.0.x and so on.
  • The Caret (^). ^1.0.1 will match everything above 1.0.1, excluding 2.0.0 and above.

Now save the package.json file to fetch and install the needed packages. You should be able to see a new folder under Dependencies named NPM as shown in the following:

Figure 7: Installing Grunt dependencies

Configuring Grunt

Grunt is an open-source tool that enables you to build client-side resources for your project. For example, you can use Grunt to compile your LESS or Saas files into CSS. Adding to that, Grunt can also be used to minify CSS and JavaScript files.

In this example, we will use Grunt to combine and minify JavaScript files. We will configure Grunt so that it will take all the JavaScript files from the Scripts folder that we created earlier, combine and minify the files within the wwwroot folder.

Now right-click on your project and select Add > New Item. Select "Grunt Configuration file" from the dialog as shown in the figure below:

Figure 8: Adding Grunt Configuration file

Then click Add to generate the file and then modify the code within the gruntfile.js file so it will look like this:

module.exports = function (grunt) {  
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-ts');

    grunt.initConfig({
        ts: {
            base: {
                src: ['Scripts/app/boot.ts', 'Scripts/app/**/*.ts'],
                outDir: 'wwwroot/app',
                tsconfig: './tsconfig.json'
            }
        },

        uglify: {
            my_target: {
                files: [{
                    expand: true,
                    cwd: 'wwwroot/app',
                    src: ['**/*.js'],
                    dest: 'wwwroot/app'
                }]
            },
            options: {
                sourceMap: true
            }
        },

        // Copy all JS files from external libraries and required NPM packages to wwwroot/js
        copy: {
            main: {
                files: [{
                    expand: true,
                    flatten: true,
                    src: [
                        'Scripts/js/**/*.js'
                    ],
                    dest: 'wwwroot/js/',
                    filter: 'isFile'
                }]
            }
        },

        // Watch specified files and define what to do upon file changes
        watch: {
            scripts: {
                files: ['Scripts/**/*.js'],
                tasks: ['ts', 'uglify', 'copy']
            }
        }
    });

    // Define the default task so it will launch all other tasks
    grunt.registerTask('default', ['ts', 'uglify', 'copy', 'watch']);
};

The code above contains three (3) sections. The first one is responsible for loading each Grunt plugins that we have configured earlier. The initConfig() is responsible for configuring the tasks. The ts is responsible for compiling TypeScript files into JavaScript. The Uglify plugin is configured so that it combines and minifies all the files from the Scripts folder and generates the result within wwwroot folder. The copy basically moves all JS files from external libraries and required NPM packages to wwwroot/js. The last section contains the definitions for your tasks. In this case we define a single "default" task that runs "ts", "uglify", "copy" and then "watches" for changes in our JavaScript file.

To learn more about Grunt and its configuration file syntax you can visit the official website here.

Integrating AngularJS 2

There are basically two ways to get Angular 2, both with their pros and cons: using NPM, which implies fetching the AngularJS 2 latest build and host the code within our project, or by using a CDN to reference the required scripts.

In this example we are going to use NPM to install AngularJS 2 in our app. First open package.json file and add the following packages under “dependencies” section like this:

"dependencies": {
    "angular2": "^2.0.0-beta.8",
    "systemjs": "0.19.22",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "tsd": "^0.6.5",
    "zone.js": "0.5.15"
  },

Now save the file to fetch and install the required packages. After the installation you should be able to see something like this:
Figure 9: AngularJS 2 and other dependencies

All of those dependencies will be installed in the following location in your local drive:

AngilarJS2Demo/node_modules/angular2/

Now we need to move these files from the location mentioned above to the wwwroot folder. We can achieve that by adding a dedicated task to our Grunt configuration, specifically under the copy task as shown in the highlighted code below:

copy: {  
    main: {
        files: [{
            expand: true,
            flatten: true,
            src: [
                'Scripts/js/**/*.js',
                'node_modules/es6-shim/es6-shim.min.js',
                'node_modules/systemjs/dist/system-polyfills.js',
                'node_modules/angular2/bundles/angular2-polyfills.js',
                'node_modules/systemjs/dist/system.src.js',
                'node_modules/rxjs/bundles/Rx.js',
                'node_modules/angular2/bundles/angular2.dev.js'
            ],
            dest: 'wwwroot/js/',
            filter: 'isFile'
        }]
    }
},
Setting up the Client Code

The next thing that we are going to do is to create a folder called “app” under the “Scripts” folder. Your project structure should now look like this:

Figure 10: Adding the “app” folder

Now it’s time for us to lay down the client code of our app, a working skeleton to use as a starting point. It will consist of:

  • An Angular 2 component file
  • An Angular 2 bootstrap file
  • An HTML file to wrap things up
The Component File

Angular 2 is entirely component based. Controllers and $scope are no longer used. They have been replaced by components and directives. The Component is the most basic and fundamental concept in Angular 2. Think of it like a class that controls a specific piece of web page where we can either display some data to each user and/or respond to their feedback's. We can say that our Angular 2 App will be almost entirely built upon multiple Components serving specific purposes: most of them will be reusable; others will be only used once. They can also either be as small as few lines or they can result in a ridiculously long piece of code.

Now let’s add a new TypeScript file by right-clicking on the “app” folder and then selecting Add > New Item. Under Client-Side option from the left pane of the dialog, select “TypeScript File” as shown in the figure below:

Figure 11: Adding app.component.ts

Name the file as “app.component.ts” and then copy the following code below into that file:

import {Component} from 'angular2/core';

@Component({
    selector: 'angularjs2demo',
    template: '<h1>AngularJS 2 Demo</h1><div>Hello ASP.NET Core! Greetings from AngularJS 2.</div>'
})

export class AppComponent { }  

That's it. Let's see what the code is all about.

The first line of code basically imports the Component function from Angular 2 library, which is angular2/core. The Component function is what we need to define a Component’s metadata for a class. The code block under @Component is the creation of the component. The @Component denotes a TypeScript instruction that tells Angular that this class is an Angular component. Notice the selector and template fields passed as configuration object. The last line of code defines the AppComponent class: notice the export keyword, which will allow us to import it from other components. The act of exporting makes our app.components.js file a Module.

The Bootstrap File

Now that we have our main component, let's add another TypeScript file to create a bootstrap to run the app. Again right click on the "app" folder and then select Add > New Items> TypeScript File. Name the file as "boot.ts" and then copy the following code below:

///<reference path="../../node_modules/angular2/typings/browser.d.ts" />

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

bootstrap(AppComponent);  

Again, let’s take a look on what we just wrote:

The first line adds a reference to “browser.d.ts” to ensure that our task runner (Grunt) will compile and execute. The next line imports the bootstrap function from another angular core module: this is required to boot our App within a browser. The next line of code imports our application root component that we just wrote earlier. Finally, the last line calls the bootstrap function with a reference to the root component class, so our application will boot up.

Now we’re just missing an entry point to load with the browser: let’s add it right now.

The HTML File

Let's add a new HTML file by right-clicking on the "wwwroot" folder and then selecting Add > New Item > HTML Page. Name the file as "index.html" as shown in the figure below:

Figure 12: Adding Index.HTML

The HTML file serves two main purposes: being an entry point for the browser so it can load the client-script files and execute the application, and laying out the DOM structure used by Angular 2 to display it.
Now click Add to create the file and then replace the generated markup with the following markup below:

<html>  
<head>  
    <title>ASP.NET Core: AngularJS 2 Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- 1. Load libraries -->
    <!-- IE required polyfills -->
    <script src="/js/es6-shim.min.js"></script>
    <script src="/js/system-polyfills.js"></script>

    <!-- Angular2 libraries -->
    <script src="/js/angular2-polyfills.js"></script>
    <script src="/js/system.src.js"></script>
    <script src="/js/Rx.js"></script>
    <script src="/js/angular2.dev.js"></script>

    <!-- Bootstrap via SystemJS -->
    <script>
        System.config({
            packages: {
                "app": {
                    defaultExtension: 'js'
                }
            }
        });
        System.import('app/boot')
            .then(null, console.error.bind(console));
    </script>
</head>

<body>  
    <!-- Application PlaceHolder -->
    <angularjs2demo>Please wait...</angularjs2demo>
</body>  
</html>  

Finally, we need to set it as the main entry point when executing our App in debug mode. In Solution Explorer, right-click to the project node and select Properties, then switch to the Debug tab and change the Launch URL parameter to "index.html" as shown in the figure below:

Figure 13: Changing the default launch URL

Running the Application

Now that we’ve set everything up, it’s time to take a look at where we’re doing. The first thing we should do is to turn our Task Runner on:

  • Right click on "gruntfile.js" and then select "Task Runner Explorer"
  • Make sure to click the "Refresh" button to load the task as shown in the figure below: Figure 14: Refresh Task Runner

  • Expand the “Alias Tasks”, then right-click to the default task and hit Run. You should be able to see something like this when successful. Figure 15: Running the Task Runner

After successfully running the Task Runner you should also see that the app and js folders are generated within your wwwroot folder as shown in the figure below:
Figure 16: app and js folder being generated

Now hit F5 or simply click on the IIS Express button to run the app and you should be able to see the following output below in the browser.
Figure 17: Output

That’s it! I hope someone find this article useful. :)

Take a look at the next part of this article here: ASP.NET Core and Angular 2 Code Venture - Part 1