31

I have simple app with one component that expects certain parameters from url. there is only one route in the application:

const appRoutes: Routes = 
                       path: 'hero/:userId/:languageId',component: HeroWidgetComponent }];

In the Index.html, I have this in the header <base href="/">

I am using webpack and the application runs fine on development environment, when browsing the url: http://localhost:4000/hero/1/1.

However, when building the app for production and getting the distribution files, then hosting that on IIS. I get the following Error when trying to browse the same url:

HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

The application works fine if I remove all the routing and just browse: http:localhost:4200 on the IIS.

Hussein Salman
  • 7,806
  • 15
  • 60
  • 98
  • 1
    Your `IIS` server needs to be configured properly so that all angular routes are redirected to `index.html` (or the html file where the angular app is triggered from). Unfortunately I'm no `IIS` server expert, so I can't give you a real answer how to do that exactly. – tftd May 04 '17 at 14:43

6 Answers6

75

We have to make IIS fall back to index.html by adding a rewrite rule.

Step 1: Install IIS URL Rewrite Module

Step 2: Add a rewrite rule to web.config

   <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <system.webServer>
        <rewrite>
          <rules>
            <rule name="AngularJS Routes" stopProcessing="true">
              <match url=".*" />
              <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />   
              </conditions>
              <action type="Rewrite" url="/" />
            </rule>
          </rules>
        </rewrite>
      </system.webServer>
    </configuration>
Hussein Salman
  • 7,806
  • 15
  • 60
  • 98
  • I am hosting on Godaddy. I followed this, but didn't have to install IIS URL Rewrite, and it just works. – mapussah Aug 02 '17 at 22:15
  • 2
    @mapussah, probably because this module is already installed. – Hussein Salman Aug 03 '17 at 14:23
  • 1
    Hi, I follow the same step, but it still goes to 404 error in my local IiS. I downloaded the URL rewrite from the given link in answer, After executing it says already installed. Can you please share what I am missing? I have develop application using Angular 4, @angular/cli, C# Web API, VS 2015. – Prashant Kankhara Sep 20 '17 at 18:59
  • @mapussah may be because you created Visual Studio angular template which comes with web.config file – Nour Lababidi Oct 06 '18 at 17:29
  • 2
    how to make this change under IIS website configuration instead of having to have web.config file – RollRoll Dec 27 '18 at 21:38
  • i am hosting REST Api on the same place... but different folder (e.g. rest) after that i am getting error: Failed to load resource: the server responded with a status of 405 (Method Not Allowed) – Ivan Salo Feb 22 '19 at 22:29
  • Also this linked helped me: http://sundeepkamath.in/posts/hosting-angular-application-in-iis-server/ – ConductedClever Sep 09 '19 at 11:20
  • If your site is hosted on a shared server, and you do not have the option to install "Rewrite", there is no choice but to use with the outdated solution as described here: https://stackoverflow.com/a/63024083/3374391 – Haim Tabak Dec 20 '20 at 20:42
  • Good job amazing – HOÀNG LONG Mar 22 '21 at 08:08
6

STEP 3: add web.config link to angular.json: (because after ng build it will skipped)

"architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser",
                    "options": {
                         ..........
                        "assets": [
                            "src/favicon.ico",
                            "src/assets",
                            **"src/web.config"**
                        ]
ogaltsev
  • 121
  • 2
  • 3
4

If you are using an IIS application like myApp below your default web site (then the URL to your application should have the syntax http://localhost/myApp/my-angular-route), then you should try to modify the action to

<action type="Rewrite" url="/myApp/"/>;

Then it works for my environment without any problems.

Step by step instructions can be found here: https://blogs.msdn.microsoft.com/premier_developer/2017/06/14/tips-for-running-an-angular-app-in-iis/

Community
  • 1
  • 1
Robert
  • 51
  • 1
3

Modify angular routing by adding # after baseurl:

http://localhost:4200/yourApp#/subPageRoute

In app-routing.module.ts on line with RouterModule.forRoot add ", { useHash: true }"

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

This way IIS thinks everything after # is some id on page and ignores it.

Aurel Havetta
  • 455
  • 4
  • 9
  • Although this solution is outdated, it can in any case be integrated into a project that is on a shared server that you will not be able to install "Rewrite" – Haim Tabak Dec 20 '20 at 20:34
3

Without installing IIS URL Rewrite

As @tftd explained in the comment to the question, IIS needs to know how to handle the request when it cannot find a matching file or folder.

You can configure IIS to return index.html whenever a route with path and/or parameters (also known as a deep link) is requested.

Manually in IIS

  1. Select your site In IIS Manager
  2. Open Error Pages icon in IIS section
  3. Open Status Code 404 list item
  4. Select Execute URL on this site radio button
  5. Enter your SPA root path, ex: '/index.html'
  6. Click OK Edit Custom Error

There is no need to restart the application pool, just browse to your deep link. The server will respond with status code 200. (tested on Windows Server 2016 with IIS 10 in 2021).

If your SPA is not rooted at /index.html, enter the folder or file where your app is rooted in step 5.

The manual process described above adds or changes httpErrors section of the web.config:

<configuration>
    <system.webServer>
        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" prefixLanguageFilePath="" path="/index.html" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
</configuration>

To avoid losing this change after the next deployment, make sure your release pipeline keeps the httpErrors section like above in the web.config.

This works for both Angular and React apps.

regmagik
  • 574
  • 3
  • 14
  • worked for me with a simple addition I am having web-dev application under default website and just replaced /index.html with /web-dev/ and worked now when refresh browser it keeps me on same route/page – sudurrani Aug 25 '22 at 08:02
0

Copy and paste this web.config to your root folder

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
 
  <rewrite>
    <rules>
      <rule name="Angular Routes" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="./index.html" />
      </rule>
    </rules>
  </rewrite>
 
</system.webServer>
</configuration>
Vinod John
  • 17
  • 6
  • This answer could be improved. Can you provide why OP should paste this config? Why should this work and solve the problem? – Malcor Jun 22 '21 at 11:37