Search code examples
c#angulariisangular-ui-routerasp.net-core-webapi

How to prevent a 404 error when refreshing an angular application that has already been published to IIS 10


I have deployed my .NET API to IIS10 and inside the directory where the .NET files are I have a wwwroot folder where I have placed my published angular files. Within the same wwwroot folder ,amongst these files, there is also a web config that specifies the rewrite URL as shown below.

The apps seems to login and display fine until I refresh then I get a 404.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <handlers>
            <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
            <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG, DELETE, PUT" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
        </handlers>
    <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" />-->
          <action type="Rewrite" url="wwwroot/index.html" />
        </rule>
      </rules>
    </rewrite>
</system.webServer>
</configuration>

In app.modules.ts

providers: [
    {provide : LocationStrategy , useClass: HashLocationStrategy}
  ]

RouterModule.forRoot

import { NgModule } from '@angular/core';
...
const routes: Routes = [//routes in here];
@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes, { useHash: true })
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

snippet of index.html

<html class="loading" lang="en" data-textdirection="ltr" data-critters-container>

<head><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <base href="/">

  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
  <meta name="description" content="Modern admin is super flexible, powerful, clean &amp; modern responsive Angular 15+ Bootstrap 5 Template with unlimited possibilities with bitcoin dashboard.">
  <meta name="keywords" content="admin template, modern admin template, dashboard template, flat admin template, responsive admin template, web app, crypto dashboard, bitcoin dashboard">
  <meta name="author" content="EvolVision &amp; CleVision

Solution

  • According to your description, you have a asp.net core API project, and there is also an Angular frond-end project, and you currently want to compile Angular project and put it in the wwwroot folder under the .net core project.

    So we can refer to the structure of the SPA for processing.

    namespace NETAPI
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var builder = WebApplication.CreateBuilder(args);
    
                // Add services to the container.
    
                builder.Services.AddControllers();
                // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                builder.Services.AddEndpointsApiExplorer();
                builder.Services.AddSwaggerGen();
    
                var app = builder.Build();
    
                // Configure the HTTP request pipeline.
                //if (app.Environment.IsDevelopment())
                //{
                //    app.UseSwagger();
                //    app.UseSwaggerUI();
                //}
    
                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseAuthorization();
    
    
                app.MapControllers();
                app.MapFallbackToFile("index.html");
    
                app.Run();
            }
        }
    }
    

    Then you can build/publish your angualr project, and we can get below files then paste then into wwwroot folder(if not this folder,we need to create it manually).

    enter image description here

    enter image description here

    Tips

    If you find the startup url is swagger/index.html, we can change it in launchSettings.json.

    enter image description here