How to add AngularJS to your ASP.NET 5 applications

- select the contributor at the end of the page -

AngularJS can be a great addition to your ASP.NET applications, but getting started can be a bit daunting for the uninitiated. Thankfully, you don’t have to go it alone. Let's take a look at how you can add AngularJS to your ASP.NET applications with minimal stress.

The tools


Before we dig too deep here, let’s take a look at the tools we’ll be using. To get started we’ll use the brand new ASP.NET 5 Release Candidate. Please note that adding AngularJS to an earlier ASP.NET MVC 5 application is almost identical to the steps we’ll cover here, but some of the final steps will be a bit different.

Next, we’ll use AngularJS 1.4. If you’ve been paying attention to the hype, you’ve probably heard that AngularJS 2.0 is coming. While it is indeed in the works, it isn’t ready for prime-time yet, so I suggest sticking with 1.x for now. The Angular team does have a plan in place to help with the transition to 2.0 when the time comes, so your investment in the current version of Angular won’t be lost.

We’ll also use Visual Studio 2015. We could do all this from the command-line or with another editor, such as VS Code, but we’ll stick with the full-blown IDE. Finally, we’ll use Node Package Manager (NPM) to install client-side packages. Visual Studio 2015 ships with support for NPM, as well as Bower, for managing packages. You’ll notice that the default project template for ASP.NET 5 already has some Bower packages installed, but Bower has fallen out of favor with many Web developers. So, we’ll do the trendy thing and use NPM instead.

Creating a sample project


We’ll need an ASP.NET project (in order to Add Angular to it). You may already have an application to try this on, but for the purposes of ensuring we’re on the same page, let’s start with a brand new ASP.NET project. To do this, open Visual Studio 2015, and go to File -> New Project. Select “Web” in the tree view on the left, then choose “ASP.NET Web Application” on the right:

aspnet_01

Click OK. This will bring up the New ASP.NET Project dialog. Under ASP.NET 5 Templates, choose Web Application, then click OK.

aspnet_02

It may take a few minutes, but Visual Studio will initialize your new project for you. Once it’s finished, let’s go ahead and run our sample app, just to make sure it works. You should see the ASP.NET 5 sample homepage:

aspnet_03

Now we’re ready to add AngularJS to the mix.

Installing AngularJS


There are several ways to add AngularJS to our project. The easiest is to just reference Angular via the Google-hosted CDN. All we have to do is add a script tag pointing to the version of AngularJS we want to use, and we’re all set. Best-practices, however, dictate that we also provide a local fallback for Angular in case something goes wrong with the CDN. So, we’ll do both: We’ll add a reference to the CDN and we’ll use a package manager to pull down a local copy. But which package manager should we use?

AngularJS is available as a NuGet pakage. We could install that package, which would automatically add the AngularJS library to our application. But, going forward, the ASP.NET team wants us to leverage other package managers for client-side tools and frameworks, not NuGet. (Remember, Visual Studio ships with support for Bower and NPM. The community is moving away from Bower, and I personally prefer npm, so we’ll use this  instead of Bower).

Now, let’s use npm to install AngularJS. Expand the “Dependencies” node of your project in Solution Explorer, right-click on “npm,” and choose “Open package.json.”

aspnet_04

Your package.json file defines your application’s npm dependencies. It’s a fairly simple file that contains a JavaScript object literal. Let’s go ahead and add AngularJS as a dependency.

The file already has a section for development dependencies, which are those that are used to build your application. But AngularJS will be a runtime dependency. So, let’s add a new section for our runtime dependencies. You can do this by adding a new object property called “dependencies.”








{
"name": "ASP.NET",
"version": "0.0.0",
"devDependencies": {
"gulp": "3.8.11",
"gulp-concat": "2.5.2",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.2.0",
"rimraf": "2.2.8"
},         "dependencies": {
}}

Now let’s add AngularJS. Within the “dependencies” object, type in “angular” followed by a colon, and you’ll see Visual Studio’s IntelliSense kick in with a list of package versions. You should see something like this:

aspnet_05

NOTE: The exact version may change depending on the most-current version available.

The three options shown are slightly different:


  • 4.8 – Reference this exact version of AngularJS. If another developer executes an “npm install,” he or she will receive version 1.4.8, regardless of what other versions might be available.

  • ^1.4.8 – Reference the latest available version of 1.x.x. Today that may be 1.4.8, but if another developer executes “npm install” to restore packages next month, they might get 1.5.0 instead.

  • ~1.4.8 – Reference the latest version of 1.4.x. Today that may be 1.4.8, but next week it could be 1.4.9. However, if 1.5.0 were to come out next week, executing an “npm install” would still install the latest 1.4.x release, and not 1.5.0.


Let’s choose the first option, and have our app reference the latest version (at the time of this writing that would be “1.4.8”). Again, this will tell our app to use this specific version of AngularJS, and nothing newer. Angular does have an unfortunate habit of making breaking changes even between patch versions on occasion, so I like to opt-in to an upgrade, rather than letting npm automatically install the latest for me.

Once you’ve specified “angular” and version “1.4.8,” your complete package.json file should look like the following:








{
"name": "ASP.NET",
"version": "0.0.0",
"devDependencies": {
"gulp": "3.8.11",
"gulp-concat": "2.5.2",
"gulp-cssmin": "0.1.7",
"gulp-uglify": "1.2.0",
"rimraf": "2.2.8"
},
"dependencies": {
"angular": "1.4.8"
}
}

When you save the file, Visual Studio will automatically execute “npm install” for you, which will install AngularJS. However, our work isn’t quite finished yet—we still need to actually add AngularJS to our project.

Adding AngularJS to your project


You may be used to NuGet, in which installing a package will (typically) configure your project for you; npm doesn’t behave this way. When you install a package, it’s placed into the node_modules folder. This folder exists outside of the project’s wwwroot folder, so you can’t directly reference scripts that live within node_modules. We’ll have to do something else instead.

There are a few options for dealing with this. We could manually copy the necessary AngularJS scripts into our wwwroot folder, but this is tedious. We’d have to remember to copy new scripts each time we updated AngularJS, plus we’d need to do the same for any other libraries we decide to use (like those listed at the end of this article).

Instead, let’s use gulp to copy AngularJS into our wwwroot.

By default, a new ASP.NET 5 Web project includes a ‘lib’ folder where Bower packages are installed. We’ll create a gulp task to copy AngularJS there, too. Go ahead and open up the project’s gulp file (gulpfile.js), located in the root of the project. Let’s first add a new object near the top. This object will contain key/value pairs, where each key will be the original source of the item we want to copy, and the value will be where we want to copy it to.








var paths = {
webroot: "./wwwroot/"
};
var itemsToCopy = {
'./node_modules/angular/angular*.js' : paths.webroot + 'lib'
}paths.js = paths.webroot + "js/**/*.js";
paths.minJs = paths.webroot + "js/**/*.min.js";

Now let’s jump to the end of our gulp file, and drop in a new task to perform the copy:







gulp.task('copy', function () {
for (var src in itemsToCopy) {
if (!itemsToCopy.hasOwnProperty(src)) continue;
gulp.src(src)
.pipe(gulp.dest(itemsToCopy[src]));
}
});

We can now run this task using Visual Studio’s Task Runner Explorer. If you don’t already have this window open, go to Quick Launch in the top-right, and type “Task Runner Explorer.”

aspnet_06

Click on “Tools -> Task Runner Explorer” to open the window. Now you should see all the tasks that are defined in our gulp file.

aspnet_07

You can run any task by double-clicking it, so go ahead and double-click the “copy” task.  If everything goes according to plan, you should see an output window appear:

aspnet_08

And now we have angular.js and angular.min.js in our wwwroot, ready to ship with our application.

If this seems like a lot more work than just adding a NuGet package, you’re right. For simple cases like this, the new tooling in Visual Studio will feel like a step backward. But the new tooling actually opens the door for doing all sorts of cool things (like ES2015 to ES5 transpilation with Babel)—we’ll talk more about this later.

Referencing AngularJS


You’re probably tired of hearing this, but we’re not quite finished yet! We still need to reference AngularJS somewhere in our application’s markup, otherwise the library will never be loaded. Typically, the best place to do this is in your _Layout.cshtml, so let’s add it there.

The _Layout.cshtml file that Visual Studio created for us already has references to jQuery and Bootstrap. Not only are they referenced, but they’re referenced using best-practices: In non-development environments, they’ll attempt to use the libraries from a CDN before loading a local fallback. We’ll follow this same pattern for loading AngularJS.

First, find where your scripts are loaded—they’ll be just before the closing body tag in _Layout.cshtml.








<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment names="Staging,Production">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-
test
="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("scripts", required: false)
</body>

Let’s first add our local, non-minified version of AngularJS to the Development environment block.







<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/lib/angular.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>

That part was easy, now let’s do the same thing for loading AngularJS in Staging and Production:







<environment names="Staging,Production">      <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.5/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-
test
="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal">
</script>      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"
asp-fallback src="~/lib/angular.min.js"
asp-fallback-test="window.angular">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>

Notice that we’re using ASP.NET MVC tag helpers to attempt to load Angular from a CDN, then falling back and loading it from our lib folder if that fails.

We now have AngularJS added to our project, so what now?

Creating your AngularJS application module


AngularJS is not a simple beast and, sadly, I can’t teach you everything you need to know about it in this tutorial. BUT, I will show you a bit more before we wrap up! Let’s start by defining a module and bootstrapping AngularJS.

NOTE: If you want to learn more about AngularJS modules or application bootstrapping, check out the documentation for ngApp.

Let’s pretend we already have a module, and let’s go ahead and load it in our layout. Find the opening <body> element, and add an ng-app attribute to it with a value of “psBlogApp”, like this:








<body ng-app="psBlogApp">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">

Next we need to actually define this module. Let’s jump over to our site.js file, which the Visual Studio project template already created for us. You’ll find it in /wwwroot/js.

Now let’s drop in the following code:








angular.module('psBlogApp', [])
.run(function() {
console.log('Hello, world, from psBlogApp!');
});

When we build and run our app, we’ll see the following in the JavaScript console:

aspnet_09

That means AngularJS has bootstrapped successfully, and we can now start leveraging it in our application! Let’s go ahead and create a super-simple directive. Back over in our site.js, let’s drop in this directive declaration:








angular.module('psBlogApp', [])
.run(function () {
console.log('Hello, world, from psBlogApp!');
})
.directive('psCurrentTime', function () {
return {
template: '<h2 class="text-
center">{{vm.currentTime}}</div>',
controllerAs: 'vm',
controller: function () {
var vm = this;
vm.currentTime = new Date().toLocaleTimeString();
}
}
});

Now we’ll open up our Home controller’s Index view, and drop in a new instance of our directive:







<ps-current-time></ps-current-time>
<div class="row">
<div class="col-md-3">
<h2>Application uses</h2>
<ul>
<li>Sample pages using ASP.NET MVC 6</li>
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518007">Gulp</a> and <a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side libraries</li>
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li>
</ul>
</div>

When we run our application, we’ll see our directive displaying the current time:

aspnet_10

Next steps


Getting AngularJS added to your project is just the first step, and while it seems like quite a bit of work the first time you do it, the payoff is well worth it. You can now add rich, client-side behaviors to your existing code, build full single-page applications, or build “SPA-silos ” for portions of your application without rewriting the entire thing.

A few parting words of advice:


  • Try to use directives and services whenever possible. If you’re comfortable using beta-quality code, you could even go with AngualrJS 1.5 and use components. These will translate to AngularJS 2.0 more easily than code created with Angular controllers (in my experience, directives are more likely to lead to cleaner code as well).

  • If you’re using Bootstrap in your application, check out the UI Bootstrap It provides Angular versions of many of the Bootstrap components, as well as services you can use for triggering things like modals.

  • If you decide to build a single-page application, or even a SPA-silo, check out the UI Router. Its routing capabilities are far more robust than what you’ll find in the current versions of AngularJS.

  • If you’re going to use gulp (and for better or worse, this is the direction the ASP.NET team is pushing things), you should take full advantage of it. I highly recommend setting up your project to use the following plug-ins: ng-annotate, Babel, and angular-templatecache. Together, these tools more than offset the overhead of having to maintain your own build script.

  • As you start moving data back and forth between the client and the server, remember that the server is actually the source of truth for what that data looks like. Your client-side references will break easily if you change your server-side models, so be extra careful when refactoring.


If you want to check out the full source for this application, head on over to the GitHub repo.  And if you want to learn more about Angular (and why wouldn’t you?), be sure to check out the extensive Pluralsight library on AngularJS.

Get our content first. In your inbox.

Contributor

Matt Honeycutt

is a software architect specializing in ASP.NET web applications, particularly ASP.NET MVC. He has over a decade of experience in building (and testing!) web applications. He’s an avid practitioner of Test-Driven Development, creating both the SpecsFor and SpecsFor.Mvc frameworks. He has served as the lead developer on numerous multi-million dollar software projects and enjoys finding elegant solutions to difficult problems.