Hosting Angular in IIS under an existing website

I recently had cause to put an Angular application a IIS sub application under an existing .Net website so effectively they share the same host url. It took me longer than it should have done – I made heavy weather of it. Some issues were just fiddly and took some working out. Some issues I had were the result of my own sub-optimal performance in this technical area (stupidity). It was Saturday afternoon so I’m allowed sub -optimal performance in my own time.

Tutorial

There is already a good tutorial here. So I’m not proposing to go through it step by step, Instead I’ll quickly outline the basic steps then point out where I went wrong. I suffer so you don’t have to.

Motivation

Just briefly – my motivation for doing this was to have Angular running under the same address as the API it was calling.

So

Is called by an angular app under a virtual directory at

This is to avoid Cross Origin Scripting Issues in my own environment. I know there are other ways to do this – but they either

  1. Never worked
  2. Were too invasive to implement on the API side (for a spare time demo project)
  3. Did work then frustrating stopped working

So I bit the bullet and moved Angular under the API project where it is always going to work for me i.e. they use the same host url so are no longer cross origin.

Create the Sub Application

So very briefly – ceate a sub application under main application to get this configuration

Point virtual directory to Angular app and browse. Boom – It doesn’t work!

Error 1: Using a .Net App pool

First issue is this yellow screen of death

The exact error will vary but essentially the angular application complains that it is missing assemblies, handlers, modules etc… It wants to be a .Net application. It doesn’t need to be.

When setting up the new application the default will be a .Net integrated application pool

To stop it behaving like a .Net app – create a new app pool with .Net CLR version of ‘No Managed Code’

Assign this to the new angular application in IIS and the site is no longer a .Net wannbe. The YSOD is gone.

Error 2: Pointing to the wrong folder

No yellow screen of death, instead the application is entirely blank. This is where I was being particularly sub-optimal. So I pointed it to my angular application at

This is never going to work. Angular builds into this directory by default

Point the sub application here. Why I thought this would magically work I’ve no idea. Although IIS had stopped behaving like a .Net site, I clearly carried on thinking it was one and pointed to the root folder as I would a .Net site. 15 minutes of my life working this out that I am never going to get back. Oh well.

Error 3: Correcting Angular script references

So run the app again and sadly it is still blank. This time if you look at chrome developer toolbar or similar you will see a lot of 404 errors

What’s going on here is that Angular is still behaving as if it is loading all scripts from the root website. To correct this

  1. Use base href element in the root index page i.e.

1. Change the ng build command from

to

This will point Angular to the right direction i.e. looking at the dist folder the script references have changed from

to

Which is correct for our sub application.

As a side note – I always forget these kind of command lines. To avoid the need for additional brain friction use the npm start command to run the ng build command with the extra parameters. So go to packages.json in the root directory of your angular app and change the npm start node under scripts to the build command i.e.

Now to build the app use

And the build command runs with the correct params.

Error 4: Refreshing page causes 404

If you are using routing you will find that refreshing a page when on a route (i.e. demo-app/Angular/page1) will give a 404 error, To resolve this one

1. Install Url rewrite

2. Include a web.config page into your src folder with these url rewrite rules

3. Include the web.config file in project assets. Go to .angular-cli.json and add web.config to the asset node like so

If you omit this step then the web.config won’t be copied over to the dist folder on build. If you add it to the dist folder manually then it will be deleted on build so you won’t be any further forward.

Once all these steps are done, refreshing on a route this will reissue the request up to the base url which will resolve correctly.

Finishing up

Now the angular app runs nicely under a sub application in IIS and my Cors problem is no longer an issue. There are a couple of disadvantages to running it this way

  1. Hot reloading of the application on rebuild doesn’t work
  2. Related to this – the application sometimes caches and a hard refresh of the browser (ctrl, F5) is sometimes needed to kick it back to life.
  3. When refreshing a page it will redirect back to the root so you lose whatever route you are on so

Refreshed becomes

Which may or may not be what you want

These are probably resolvable but when I got my development environment to this point, I declared loudly to all with ears to hear – Job done!

Useful Links

https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module
Url Rewriting module in IIS – official microsoft page

https://blogs.msdn.microsoft.com/webdev/2006/06/30/part-1-of-3-creating-sub-projects-in-iis-with-web-application-projects/
Setting in sub applications in IIS – detailed tutorial

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Wiki page about CORS which was causing me all the problem in the first place