Quantcast

comments edit

Building your first Angular2 app using Visual Studio 2015 is quite simple. Let’s have a look at what’s inside a simple hello world app. Full code for this part is available on Github, just clone, let npm download packages, and run the sample !

This sample is based on angular.io quickstart, by adapting it to run on Visual Studio 2015. Following are some key points.

package.json

As explained in angular.io quickstart, dependencies are required to run the angular application. Differences between dependencies and devDependencies are explained in depth here.

The main dependencies are Angular2 (sure…) and systemjs. The latter is a dynamic module loader, removing all the hassle of referencing all your application js files in the index.html.

Other dependencies are polyfills, providing functionnality that will be offered later by browsers (hopefully). Internet Explorer has it’s own set of required shims, which have to be included in a specific order in index.html.

gruntfile

Like in previous samples, I’m using a gruntfile for managing the development and build process :

  • copy files into wwwroot
  • copy dependencies into wwwroot/vendor
  • compile typescript sources into wwwroot/app
  • watch for changes in typescript or html files, and copy them to wwwroot

The dependencies to copy are specified manually in the gruntfile. This may seem complicated to injector/wiredep fans, but at the moment I did not find an easier way to do it. Proposals will be appreciated !

application sources

The html and other static files are located in a src/html folder, and get copied to wwwroot folder. The application code is located in src/ts folder and get compiled into wwwroot folder using grunt-ts task.

It may seem easier to put everything in wwwroot directly, but separating the sources will enable for later testing of release building of application, including sources in unit test runner, and so on.

what are the main differences with AngularJS 1.5, from this hello world point of view ?

  • Angular2 is now based on typescript
  • There is no attribute based bootstrapping of your application, a root component is now used.
  • Systemjs is used for managing modules (webpack can be used as well).

Next part in this series will convert the Tour of heroes sample application from angular.io.

comments edit

In this part I’ll continue automating testing, with protractor integration. This is straightforward but requires a little plumbing configuration!

NPM packages used

Add the following packages to the package.json file :

  • grunt-protractor-runner
  • grunt-contrib-connect

The key packages here are grunt-contrib-connect, and grunt-protractor-runner. The grunt-protractor-runner package version 3.0.0 relies on nodejs version 4.0 at least.

Hopefully the update is easy : go to the node website, download the latest version, and make Visual Studio use it, in Tools > Options > Projects and Solutions > External Web Tools, and add the path to nodejs on top.

Visual studio config

Connect grunt task

Create a new task in gruntfile.js for starting the connect web server, which will serve your application to protractor runner.

connect: {
	server: {
		options: {
			port: 9001,
			base: 'wwwroot'
		}
	}
},

Protractor grunt task

The protractor task needs to update the webdrivers and start them in standalone mode (this is easier to setup)

protractor: {
	run: {
		options: {
			configFile: "test/protractor.conf.js",
			webdriverManagerUpdate: true
		}
	}
}

The e2e task, which will start the connect web server, and run protractor tests.

grunt.registerTask('test:e2e', [
	'connect:server',
	'protractor:run'
]);

And finally the protractor configuration file, with 2 important points :

exports.config = {
	// not required in standalone mode
	// seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['e2e/scenarios.js'],
    baseUrl: 'http://localhost:9001',
    rootElement: '[ng-app]'
}

Running this task will produce the following in task runner explorer console :

Protractor runner

Full code for this part is available on Github

comments edit

In this part I’ll dive into unit testing your AngularJS code. Not so much on the test specs details, as there are enough documentation on those. I’ll show how to set up a nice workflow which will set up tests as they’re added, and run them automatically when you edit you javascript code, and create code coverage reports.

NPM packages used

Add the following packages to the package.json file :

  • grunt-contrib-watch
  • grunt-karma
  • karma
  • karma-chrome-launcher
  • karma-coverage
  • karma-ie-launcher
  • karma-jasmine
  • karma-phantomjs-launcher
  • phantomjs

The key packages here are grunt-contrib-watch, grunt-karma and karma-coverage.

Watch task

Create a new task in gruntfile.js for reacting on file change events. This will trigger injection of JS files, or test running.

watch: {
	// adding or removing a js file trigger injections
	injections: {
		files: ['<%= paths.app %>/app/**/*.js'],
		tasks: ['wiredep', 'injector'],
		options: {
			event: ['added', 'deleted'],
		},
	},
	
	// changing an application file triggers automated tests
	tests: {
		files: ['<%= paths.app %>/app/**/*.js'],
		tasks: ['karma:unit']
	}
},

Karma grunt task

The karma task is quite simple as well, this one has two sub-tasks, to run unit tests into phantomjs, reporting results in a console; or runs tests directly into IE and Chrome browsers.

karma: {
    allBrowsers: {
        configFile: 'test/karma.conf.js',
        browsers: ['Chrome', 'IE']
    },
    unit: {
        configFile: 'test/karma.conf.js',
        browsers: ['PhantomJS']
    },
}

Will produce the following in task runner explorer console :

Karma runner

Code coverage

Producing code coverage reports is also simple, just add the relevant reporters, preprocessors and plugins to the karma.conf.js file.

reporters: ['progress', 'coverage'],

// process application files (not test !) for coverage
preprocessors: { '../wwwroot/app/**/!(*.spec).js': ['coverage'] },

plugins: [
	'karma-jasmine',
	'karma-chrome-launcher',
	'karma-ie-launcher',
	'karma-phantomjs-launcher',
	'karma-coverage'
],

And see output in test/artifacts/coverage-html folder :

Code coverage

HTML test runner

Finally, should you want to debug your tests, you can add the Jasmine html runner to the project, and inject JS files into it.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Jasmine Spec Runner v2.3.4</title>
    <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.3.4/jasmine_favicon.png">
    <link rel="stylesheet" href="lib/jasmine-2.3.4/jasmine.css">
    <script src="lib/jasmine-2.3.4/jasmine.js"></script>
    <script src="lib/jasmine-2.3.4/jasmine-html.js"></script>
    <script src="lib/jasmine-2.3.4/boot.js"></script>
    <!-- bower:js -->
    <!-- endbower -->
    <!-- injector:js -->
    <!-- endinjector -->
</head>
<body>
</body>
</html>

Then you can just run it from the file system :

Html runner

Full code for this part is available on Github

comments edit

Front end development capabilities saw a huge boost with the release of Visual Studio 2015 and the seamless integration of Npm, Grunt and Bower. In the first part of this series I’ll summarize quickly how to get started creating an AngularJS and ASP.NET 5 WebApi application. First of all, you’ll need the following tools:

Then, create a new web application project using the ASP.NET 5 Templates :

Creating an ASP.NET 5 project

Add an index.html file inside the wwwroot folder.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <p>Hello</p>
</body>
</html>

This folder will be the root of your application, from the web server point of view. Press F5 and, behold :

Creating an ASP.NET 5 project

project.json

This file is used for defining your ASP.NET 5 application dependencies and other properties. Here a dependency on Microsoft.AspNet.IISPlatformHandler and Microsoft.AspNet.StaticFiles is sufficient.

Then you can add three main files:

  • The package.json manages development dependencies: the various tools to process source files during the build process.
  • The bower.json manages application dependencies: all libraries and frameworks that your application depends on.
  • The gruntfile.js file is handling frontend application development build process. For example, watching for scss file changes to generate css, and minify javascript files for production deployment.

package.json

Add a dependency to grunt, injector, and wiredep. Injector and wiredep are used to modify your html files to include bower dependencies and your application source code.

bower.json

Add a dependency to angular, ui-router, and jquery. After saving, Visual Studio should start downloading those. Semantic versioning is used, and nicely explained here on StackOverflow

gruntfile.js

Here is a bit more work, add a wiredep and injector tasks. Wiredep is used for bower dependencies, and injector is used for application files.

injector: {
    options: {
        lineEnding: "\r\n", // this is a Windows centric sample ;)
        relative: true, // relative to injection target file
        addRootSlash: false
    },

    // application scripts injection sub-task
    appScripts: {
        files: {
            '<%= paths.app %>/index.html': [
                '<%= paths.app %>/app/**/*.module.js',
                '<%= paths.app %>/app/**/*.js',
                '!<%= paths.app %>/app/**/*.spec.js'
            ]
        }
    },

    // application css injection sub-task
    appCss: {
        files: {
            '<%= paths.app %>/index.html': [
                '<%= paths.app %>/styles/**/*.css'
            ]
        }
    }
},

wiredep: {
    app: {
        src: [
            '<%= paths.app %>/index.html'
        ]
    }
}

Both tasks will inject file references into your index.html, which will need adaptation :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>

    <!-- bower:css -->
    <!-- endbower -->
    <!-- injector:css -->
    <!-- endinjector -->
</head>
<body>

    <!-- bower:js -->
    <!-- endbower -->
    <!-- injector:js -->
    <!-- endinjector -->

    <p>Hello</p>
    <div ng-app="app">
        <ui-view />
    </div>
</body>
</html>

Finally, add an angularjs controller inside an app folder :

(function () {
    'use strict';

    angular.module('app', [
        // Angular modules 

        // Custom modules 
        'app.home',

        // 3rd Party Modules
        'ui.router'
    ])
    .config(function ($urlRouterProvider, $stateProvider) {
        // For any unmatched url, redirect to /home
        $urlRouterProvider.otherwise("/home");
        // Now set up the states
        $stateProvider
            .state('home', {
                url: "/home",
                templateUrl: "app/app.template.html",
                controller: "HomeController",
                controllerAs: "home"
            });
    })
    .controller('HomeController', HomeController);

    function HomeController() {
        var vm = this;
        vm.title = 'Hello world';
    };
})();

And run both wiredep and injector tasks from task runner :

Task runner

Full code for this part is available on Github

comments edit

Le routing

Une nouveauté dans Web API 2.0 est le routing par attribut. Auparavant il était nécessaire de déclarer les routes selon des conventions :

routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Voici le même exemple en utilisant les attributs :

[RoutePrefix("api/names")]
public class NamesController : ApiController
{
	[HttpGet]
	[Route("{prefix}")]
	public IHttpActionResult GetNames(string prefix)
	{
		var names = this.dataProvider.GetFirstNames().Where(x => x.StartsWith(prefix));

		return this.Ok(names);
	}
}

Il n’est plus nécessaire de conformer toutes les routes à des conventions qui pouvaient devenir fastidieuses à maintenir, comme par exemple les routes que l’on peut rencontrer dans une API de type REST :

  • /clients
  • /clients/123
  • /clients/123/orders
  • /clients/123/orders/456

La serialisation

La sérialisation se fait de manière transparente : en fonction du content-type de la requête HTTP, la réponse sera sérialisée en JSON ou en XML par défaut. Des points d’entrée sont présents dans Web API pour personnaliser ce comportement : http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

Les filtres

Tout comme ASP.NET MVC, les filtres permettent l’interception des actions des controlleurs, avant ou après l’exécution de celles ci.

Les usages courants sont :

  • la sécurisation des actions
  • la journalisation
  • la modification des en-têtes http avant envoi de la réponse
public class CustomHeaderAttribute : ActionFilterAttribute
{
	public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
	{
		actionExecutedContext.Response.Headers.Add("Hello-Header", "Hello world !");
	}
}

Les tests unitaires

La séparation des rôles apportée par Web API permet de facilement mettre en place des tests unitaires, avec ou sans mocking.

Il est également possible de faire des tests de bout en bout : Tests unitaires avec WebApi, Castle Windsor et OWIN

Le code source est disponible sur github