10

I am going through the tutorials for Angular 2 and have been able to get a simple application up and running. Now, I am moving on to the routing and navigation part found here https://angular.io/docs/ts/latest/guide/router.html, but something isn't working for me.

I went to the live example in Plunker and downloaded the code from there. I then setup a solution in Visual Studio 2015 and plugged in all of the code from the Plunker download. The application works perfectly except for one thing, the navigation doesn't seem to work as the documentation would seem to indicate.

I start debugging the application in Visual Studio using IIS Express and Chrome browser. The main page loads correctly and I can click on the links for Crisis Center and Heroes. When I click the links, the component views correctly load and everything looks perfect.

Now, if I try to navigate by simply typing in the URL, the component views don't load and all I have is a blank page.

For example, I start debugging the application in Visual Studio and the Chrome Browser opens with the URL http://localhost:56074/. The main page is loaded correctly with the "Component Router" header and the two links for "Crisis Center" and "Heroes". Now, if I simply go to the address bar and add "/crisis-center" to the end of the URL so it looks like http://localhost:56074/crisis-center, I get a blank page. The Chrome console shows the following error:

GET http://localhost:56074/crisis-center 404 (Not Found) Navigated to http://localhost:56074/crisis-center

and the Network trace clearly shows a 404 for crisis-center. In fact, if I use the navigation link on the main page for Crisis Center and click on it to show the crisis center component view, and then simply hit the refresh button to refresh the page while at the crisis center view, the same result happens.

Is this a Visual Studio issue? IIS Express? Other ideas?

We are a .Net development shop and our primary development environment is Visual Studio. If this is an issue with developing an Angular 2 application in Visual Studio using IIS Express, this may be a show stopper.

If anyone wants to try the same thing I can zip up my VS solution and share.

Anyone tried an Angular 2 application in Visual Studio using IIS Express that can maybe tell me what I am doing wrong?

meyousikmann
  • 821
  • 1
  • 9
  • 30
  • You need to setup your server to return default page (usually index.html) when it can't a resource. I didn't work with IIS for a long time, so can't tell you exactly what to do... – Sasxa Jan 28 '16 at 04:10
  • See: http://stackoverflow.com/questions/34541532/is-angular-2s-router-broken-when-using-html5-routes – Langley Jan 28 '16 at 04:12
  • Possible duplicate of [Angular 2.0 router not working on reloading the browser](http://stackoverflow.com/questions/31415052/angular-2-0-router-not-working-on-reloading-the-browser) – Günter Zöchbauer Jan 29 '16 at 07:40

6 Answers6

21

Angular 2 by default uses HTML5 routing, you either have to map all server requests to index.html by adding the following to web.config

<rewrite>
    <rules>
        <rule name="redirect all" stopProcessing="true">
            <match url="^(.*)$" ignoreCase="false" />
            <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
            </conditions>
            <action type="Rewrite" url="PATH TO INDEX.HTML" appendQueryString="true" />
        </rule>
    </rules>
</rewrite>

or implement the HashLocationStrategy, as described in angular docs here

provide(LocationStrategy, {useClass: HashLocationStrategy})
Jerry
  • 563
  • 4
  • 13
tergd1
  • 557
  • 6
  • 19
  • I don't know how I missed the Angular docs on this. I also feel pretty lame in that I asked this question when there appear to be others that are quite similar. Clearly I am not the first person that has run into this. Sorry for the duplicate question. Your answer is exactly correct, but I actually utilized Bharathi answer because of the AppCmp code. – meyousikmann Jan 30 '16 at 03:11
  • this is great - especially for a line of business type app where # URLs don't look out of place – Simon_Weaver Apr 05 '16 at 06:30
  • Thanks for sharing the ` `. I was using ` ...` and it didn't redirect to the requested page. Instead all paths were redirecting to index.html. This solved my issue. – Adrian Moisa Jul 30 '16 at 10:15
  • There is one issue with this code: all my JSON get requests give errors because of global url redirect. I tried using a regex, but it doesn't work ``. Any ideas? – Adrian Moisa Jul 30 '16 at 12:06
  • This worked for me, but I had to install the URL rewrite module first (of course!) https://www.iis.net/downloads/microsoft/url-rewrite – Bulan Jan 17 '17 at 09:06
3

In addition to @stasivash answer: If you have trouble making ajax requests to a certain path in your project, such as YOUR-DOMAIN/api/..., I suggest adding the following condition:

<add input="{REQUEST_URI}" negate="true" pattern="^\/api\/.*$" ignoreCase="true" />

resulting in:

<rewrite>
  <rules>
      <rule name="redirect all" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false" />
          <conditions logicalGrouping="MatchAll">
              <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
              <add input="{REQUEST_URI}" negate="true" pattern="^\/api\/.*$" ignoreCase="true" />
          </conditions>
          <action type="Rewrite" url="/index.html" appendQueryString="true" />
      </rule>
  </rules>
</rewrite>
Community
  • 1
  • 1
Adrian Moisa
  • 3,923
  • 7
  • 41
  • 66
2

For this issue, you need to use PathLocationStrategy or HashLocationStrategy for your application. It's available in the 'angular2/router'.

Example for using HashLocationStrategy:

boot.ts

bootstrap(AppCmp, [
       ROUTER_PROVIDERS,
       provide(LocationStrategy, {useClass: HashLocationStrategy})
   ]);

and in your main component,

class AppCmp {
          constructor(location: Location) {
          location.go(location.path());
       }

The location.path() dynamically gives the path for the page to be loaded.

1

Old question, but I wanted to provide this suggestion as an alternative for future readers as I preferred the Rewrite method:

Building upon the answers from stas.ivash and Adrian Moisa: I used their URL Rewrite suggestions, but instead of listing out routes, I modified the regex to route everything excluding the files that our Angular 2 CLI generated app needs, with the given extensions (.bundle.js, .bundle.map, etc...):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="AngularJS" stopProcessing="true">
          <match url="^(?!.*(.bundle.js|.bundle.map|.bundle.js.gz|.bundle.css|.bundle.css.gz|.png|.jpg|.ico)).*$" />
          <conditions logicalGrouping="MatchAll">
          </conditions>
          <action type="Rewrite" url="/"  appendQueryString="true" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

I can't really speak to the performance implications of using this RegEx solution in a Production environment, but it works well for us on our Dev and Stage environments.

Community
  • 1
  • 1
Steve
  • 11,596
  • 7
  • 39
  • 53
1

You can fix the error by implementing hash location strategy:

To enable HashLocationStrategy it's like this:

RouterModule.forRoot(routes, {useHash: true})

URL can contain some data prepended with a # character.

The # part of the URL is called the hash fragment. It’s never sent to the server,

example: http://example.com/#/clients

Thomas Fritsch
  • 9,639
  • 33
  • 37
  • 49
ferralucho
  • 637
  • 7
  • 24
0

This is my solution: https://csjdpw.atlassian.net/wiki/display/~Genhan.Chen/404+issue+for+Angular+2+routing

Refers to another posting: AngularJS 2 routing

Community
  • 1
  • 1
G Chen
  • 199
  • 3
  • 12