Aurelia Hello World with ASP.NET 5

Tuesday, April 7, 2015

The purpose of this post isn’t to give an exhaustive tour of Aurelia features, but to show a simple Aurelia application running in ASP.NET 5 and demystify some of the tools you’ll commonly see used with Aurelia. This post makes use of jspm and the SystemJS module loader. These tools and libraries aren’t required to use Aurelia, but they sure can make life easier.

1. Create a new, empty ASP.NET 5 web application with Visual Studio 2015.

2. Install and initialize jspm. In a previous post we looked at using jspm with the latest pre-release of ASP.NET. You’ll want to follow all those same steps, particularly the initialize step telling jspm to use ./wwwroot as the public folder path. We want Aurelia installed and served from a jspm_packages folder inside this wwwroot folder, since ASP.NET 5 serves static assets from wwwroot by default.

3. Use jspm to install some of the core Aurelia pieces. From the command line:

jspm install aurelia-framework
jspm install aurelia-bootstrapper

jspm will download all the required files and place them in the jspm_packages folder of wwwroot.

4. We are now ready to create an index.html file in wwwroot. There are 4 significant instructions in the following markup.

<html>
<head>
    <title>Hello from Aurelia</title>
</head>
<body aurelia-app>
    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
    <script>
        System.import("aurelia-bootstrapper");        
    </script>
</body>
</html>

The aurelia-app attribute tells Aurelia where it will take control of the DOM and inject our applications’ first view and viewmodel.

The script tag to load system.js brings glorious magic to the page. SystemJS is a module loader, much like  Require JS, but SystemJS knows how to load different types of modules – AMD, CommonJS, and ES6 modules. SystemJS also contains the ability to dynamically compile ES6 code into ES5 code on the fly. We’ll take advantage of the dynamic compilation features to use Aurelia without setting up any build task for our script code. jspm installs SystemJS by default.

The script tag to load config.js brings in configuration data to tell the module loader where to find script files, like scripts for Aurelia as well as our own application. The configuration also tells the loader how to behave. Fortunately for us, jspm creates and maintains the config.js file, so the only work we have to do is include the file on the page. 

Finally, we will use the module loader’s API to import the aurelia-bootstrapper. The module loader will find and load the bootstrapper and the bootstrapper’s dependencies into the browser.  Once the bootstrapper has control, it will begin to spin up Aurelia using some default configuration options, and go looking for our application, which we will build in the next two steps.

5. By default, Aurelia will go looking for an app.js script in the same folder as our index.html file. Let’s fill app.js with the following code:

export class App {
    
    constructor() {
        this.message = "";
    }

    activate() {
        this.message = "Hello, World!";
    }

    changeMessage() {
        this.message = "Goodbye!";
    }

}

View models in Aurelia are plain, vanilla JavaScript.  There is no magic or registration code required. The framework will automatically invoke the activate method, which can return a promise if long running work needs done.

6. Once Aurelia finds and activates app.js, the framework will try to load an app.html file to function as the view for the model. We’ll create app.html in the wwwroot folder, too.

<template>
    <div>
        <div>${message}</div>
        <button click.trigger="changeMessage()">Say Goodbye</button>
    </div>
</template>

Binding model content into the DOM is as easy as using the string interpolation ${ } syntax, while events are directed to model methods using trigger, delegate, and call expressions.  

image

And that’s it! Once you learn just a few simple conventions, Aurelia makes applications easy. We haven’t touched on routing, dependency injection, custom elements, or any of the other features that make Aurelia great. Those are all topics for the future… 


Comments
gravatar Carlos Tuesday, April 7, 2015
Thank you K. Scott Allen! This was a great getting started post that made the setup clear and simple. I prefer it over the Aurelia skeleton project, which while well done, is bloated with things that obfuscate the basics of a hello world project with a complex build etc. that are better covered later on. Thanks again!
gravatar mg1075 Tuesday, April 7, 2015
Would it be possible to have a similar Aurelia "hello world" write-up for VS 2013 or WebStorm?
gravatar Carlos Tuesday, April 7, 2015
@mg1075 VS 2013 and WebStorm would be the same process (probably slightly easier). The only real difference being that you don't have to place all the files you'd be serving in the wwwroot folder. Otherwise its the same thing.
gravatar Costr Tuesday, April 7, 2015
How I felt when I first read this article: http://cdn.meme.am/instances/500x/61044825.jpg I must admit...I needed a refresher.
gravatar Radenko Wednesday, April 8, 2015
Hi Scott. Nice example of how to work with Aurelia with ASP.NET 5. Can you please extend this example to show how to mix ASP.NET MVC 6 with Aurelia. I want to have some views standard MVC and some SPA - Aurelia based in same app. Thanks
gravatar Radenko Wednesday, April 8, 2015
Managed to mix ASP.NET MVC 6 with Aurelia with simple link from MVC 6 View to Index.html Aurelia view. I hope only that Session will be passed from Aurelia request to my API controller as well...
gravatar Vitali Wednesday, April 8, 2015
Thank you K. Scott Allen! Would you show how to use aurelia with ASP.NET 5, Typescript and bower instead of jspm, please?
gravatar Mark Rowe Wednesday, April 8, 2015
Thanks again Scott, how do you think this compares to KO and other binding languages.
gravatar Scott Wednesday, April 8, 2015
@Mark - Aurelia provides more features than just binding, there is also routing and eventing and custom elements, to name a few, so I'd look at Aurelia as more of a complete framework for building client side apps.
gravatar Scott Wednesday, April 8, 2015
@ Vitali - sure - just need more time :)
gravatar Carlos Wednesday, April 8, 2015
@Vitali I can see using typescript perhaps but why would you want to use bower over jspm?
gravatar Vitali Wednesday, April 8, 2015
@Carlos I've tried to use jspm but I had some problems with Bootstrap like this: https://github.com/jspm/jspm-cli/issues/393 After that I prefered using stack like above. At the moment I don't understand the advantages of jspm over bower in this use case.
gravatar Vitali Wednesday, April 8, 2015
@Carlos I've tried to use jspm but I had some problems with Bootstrap like this: https://github.com/jspm/jspm-cli/issues/393 After that I prefered using stack like above. At the moment I don't understand the advantages of jspm over bower in this use case.
gravatar Pharaoh Wednesday, April 8, 2015
@Scott - I'm also interested in your opinion how Aurelia is used together with Typescript. I'm quite fond of using strongly typed languages. Is there any situations where use of Typescript isn't good choice for building Aurelia apps.
gravatar Scott Wednesday, April 8, 2015
@Pharaoh: Lot's of TS definitions and examples here: https://github.com/cmichaelgraham/aurelia-typescript. I think TypeScript is a good choice.
gravatar John R Wednesday, April 8, 2015
Thank you for this! I hadn't heard about Aurelia before this and it looks great. It takes the best things about Angular and fixes the bad parts. I'd love to see a post about how to do bundling with Aurelia, TypeScript and VS2015. This simple example results in 130+ requests, so obviously bundling will be important. I'm just not sure how to make that work with the dynamic module loading.
gravatar Malisa Ncube Wednesday, April 8, 2015
Thank you Scott. Simple and clear. I think I will be more inclined to use Aurelia than Angular 2.0 in my next projects.
gravatar Guy Wednesday, April 8, 2015
Now can you show how to make jspm work inside vs2015, like npm or bower. without having to use command line.
gravatar Wes Wednesday, April 8, 2015
Thanks for the post! With Aurelia producing a static website (html, js, css), would it be possible to host the site on something like azure blob storage and avoid the iis pipeline altogether? I think I remember reading somewhere that the outbound bandwidth is much higher on the blob storage than a small azure website and can also be fronted by a CDN. Any thoughts on this?
gravatar Rob Wednesday, April 8, 2015
@wes I've got at least one client who is hosting their entire Aurelia app in Azure Blob Storage, fronted by CDN :) Their services are written with vNext .NET MVC and hosted separately.
gravatar bastienJS Saturday, April 11, 2015
Thank you for the sample and that you will also take time for the TypeScript addition :-)
gravatar Travis Tuesday, April 14, 2015
@Scott Thank you for your example. I am curious, have you done anything yet with wrapping any .Net code around an Aurelia app? For example using integrated authentication and then passing user information or permissions down into Aurelia.
gravatar Wes Tuesday, April 14, 2015
@Rob, how are they getting around the issue of Azure blob storage not supporting a default document? So if I navigate to http://yourdomain.com how do they have it automatically serve http://yourdomain.com/index.html?
gravatar OhPlease Wednesday, April 15, 2015
This is such a rip off of Node.js. Give me a break. This is just sad. Microsoft had years and years to fix IIS. It just kept making things worse with ASP.Net MVC. Razor was just terrible. Rather than coming up with ideas on how to improve web app development Microsoft can't. It doesn't have any ideas. So it took Google to fix things. Google released the V8 engine and Node was built on that. Then everyone in the real world of development started using Node. And then Microsoft found a way to improve their dev stack: copy Node.
gravatar Scott Wednesday, April 15, 2015
@Travis: not yet. @OhPlease: jspm is a node program, not a copy. Other than that, everything here was focused on the client not the server.
gravatar Carlos Wednesday, April 15, 2015
@OhPlease. You "sound" really emotional and "read" as nonsensical.
Monday, April 20, 2015
export class MyApp{ constructor(){ this.firstName = 'John'; this.lastName = 'Doe'; } get fullName(){ return `${this.firstName} ${this.lastName}`; } } I copied it from Rob's blog. can you explain me why the access to the object properties requires the syntax : `${this.firstName} ${this.lastName}` ??
gravatar Bernhard Monday, April 20, 2015
Thanks for the intro Scott. I'd like to see how one would build debug versus release script, or does it always build combined minified with sourcemap support?
gravatar Scott Monday, April 20, 2015
@Bernhard: Personally I've been using node tools like gulp and gulp plugins to build, lint, minify, etc, then yes, I'll send down minified code and use sourcemaps.
gravatar Scott Monday, April 20, 2015
Re: the `${this.firstName} ${this.lastName}` syntax. This is JS2015 template literal syntax: http://odetocode.com/blogs/scott/archive/2014/09/18/features-of-es6-part-7-template-literals.aspx
gravatar Kelly Ethridge Monday, April 27, 2015
Thank you for this intro and your Pluralsight videos. This intro works for Chrome and Firefox, but IE11 has an error. I'm presuming it has something to do with converting the code to ES5 incorrectly. Have you experienced this?
gravatar Scott Wednesday, April 29, 2015
@Kelly - It works on my machine! What is the error?
gravatar Mark S Wednesday, April 29, 2015
There is a nice set of TypeScript / Aurelia samples found in this github repository: https://github.com/cmichaelgraham/aurelia-typescript
gravatar Kelly Ethridge Thursday, April 30, 2015
@Scott - Sorry, I'm a complete newbie with javascript so my debugging skills are non-existent. Anyways, the error I get in IE is "JavaScript runtime error: Cannot define property 'Symbol(id)_h.2bkfu5gitgx': object is not extensible". I'm using IE11 on Win7-64bit. I did write your example in VS2013, though.
gravatar Phil Stricker Saturday, May 2, 2015
@Scott Thanks for the writeup! I have used Eisenberg's last SPA project Durandal with quite a bit of success but am finding the reliance on knockout to be a bit heavy. Excited to see what Aurelia looks like.
Simon Sunday, May 3, 2015
Hi Scott, do you have any plan to release an Aurelia course on Pluralsight ?
gravatar Scott Monday, May 4, 2015
@Simon: yes!
gravatar Mauna B Tuesday, May 5, 2015
I have tried to complete the sample as well, and have run into the same issue as Kelly. I loaded github, github for windows, nodejs, gulp, jspm, and the Aurelia packages. According to the stack trace in IE (Developer Tools/Console and Debugger Tab): Script5077: Cannot define property 'Symbol(id_i.ee8k5norqt0: object is not extensible; File: index.js, Line: 204, Column 11; "at defineProperty (Unknown script code:48:3)\n at Anonymous function (Unknown script code:36:5)\n at fastKey (Unknown script code:29:5)\n at module.exports.def (Unknown script code:114:7)\n at set (Unknown script code:10:5)\n at set (Unknown script code:51:13)\n at ensureOriginOnExports (Unknown script code:14:5)\n at Anonymous function (Unknown script code:131:15)\n at O (http://localhost:4767/jspm_packages/es6-module-loader.js:7:7426)\n at K (http://localhost:4767/jspm_packages/es6-module-loader.js:7:7013)"
gravatar Scott Tuesday, May 5, 2015
@Kelly, @Mauna: I haven't been able to reproduce this bug myself. I will make an issue of it and post back when I find out more.
gravatar Ward Bell Thursday, May 7, 2015
Hi Scott - Working just fine in VS2015 RC :-) One twist ... the only version of 'Microsoft.AspNet.StaticFiles' I could find from within VS Nuget Package Manager was beta-5. That doesn't work with beta-4 bits and trying to figure out what had changed (hint: plenty) was a bridge too far. Fortunately, one can get working nuget packages by modifying the *project.json* like so: "dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta4-*", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta4-*", "Microsoft.AspNet.StaticFiles": "1.0.0-beta4-*" } Hope that helps someone besides me. Keep up the great work!
Steve Sunday, May 17, 2015
I had the same issue as Mauna & Kelly. Was using es7 and to resolve I converted to typescript. Seems to be an issue with es7/babel/IE. Still using systemjs, working gr8 now. Really like the framework.
gravatar David Developer Monday, May 18, 2015
@Steve Having the same issue you had (that Mauna & Kelly had). How to I convert to typescript? Thanks.
Comments are closed.

My Pluralsight Courses

K.Scott Allen OdeToCode by K. Scott Allen
What JavaScript Developers Should Know About ECMAScript 2015
The Podcast!