Search code examples
angulariisasp.net-coreurl-rewritingkestrel

Why is index.html returned by Asp net Core for requests of my Angular Spa dist files?


After deploying my Asp Net Core Angular Spa to a shared web server, requests for the angular runtime components return my index.html file.

EDIT (rephrasing question to clarity):

I have an angular spa that is served by the asp net core angular template. When I navigate to the url for the application, the index page is returned and then subsequent calls to return the script files for the client app all return index.html as well... even though the url is requesting runtime.js, main.js, etc

What additional configuration is required in addition to my code excerpts below?

public void ConfigureServices(IServiceCollection services)
{
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/dist";
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseStaticFiles();
    app.UseSpaStaticFiles();
    app.UseMvc();

    app.UseSpa(spa =>
    {
        spa.Options.SourcePath = "ClientApp";
    }); 
}

In my angular.json, I specify the following URL prefixes:

"baseHref": "/APPNAME/",
"deployUrl": "/APPNAME/ClientApp/dist/"

The source tree appears to be correct.

The requests for each of the runtime components are successful but they all return my index.html rather than what was requested.

Request URL: https://example.com/MYAPP/ClientApp/dist/main.17cf96a7a0252eeecd9e.js

Response from Chrome network debugger:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>APP NAME</title>

  <base href="/APPNAME/">

  <meta content="width=device-width, initial-scale=1"
        name="viewport">
  <link href="HRDRicon.png"
        rel="icon"
        type="image/x-icon">
<link rel="stylesheet" href="/APPNAME/ClientApp/dist/styles.d9e374eff45177231bee.css"></head>
<body class="fixed-sn white-skin">

<app-root></app-root>

<noscript>
  <p>
    Sorry, JavaScript must be enabled to use this app
  </p>
</noscript>

<script type="text/javascript" src="/APPNAME/ClientApp/dist/runtime.e460f84ccfdac0ca4695.js">
</script><script type="text/javascript" src="/APPNAME/ClientApp/dist/polyfills.d0cb8e9b276e2da96ffb.js"></script>
<script type="text/javascript" src="/APPNAME/ClientApp/dist/scripts.a54ea6f0498a1f421af9.js"></script>
<script type="text/javascript" src="/APPNAME/ClientApp/dist/main.17cf96a7a0252eeecd9e.js"></script>
</body>
</html>

I will add a link to the images in a comment since that is restricted in the original post.


Solution

  • I struggled with the spa-extensions, too. It seems that UseSpa sets up a catch-all rule to index.html that also intercepts the requests to all static files like .js and .css. To get my spa working in a subdirectory, all that was required were the modifications 1. and 2. in the startup.cs. No spa-extensions required.

    public static void Configure( IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...
        app.UseHttpsRedirection();
        app.UseStaticFiles();
    
        // 1. Configure request path for app static files
        var fileExtensionProvider = new FileExtensionContentTypeProvider();
        fileExtensionProvider.Mappings[".webmanifest"] = "application/manifest+json";
        app.UseStaticFiles(new StaticFileOptions()
        {
            ContentTypeProvider = fileExtensionProvider,
            RequestPath = "/myapp",
            FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), @"MyApp/dist"))
        });
    
        app.UseRouting();
    
        app.UseAuthentication();
        app.UseAuthorization(); 
    
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapDefaultControllerRoute();
            endpoints.MapRazorPages();
            // 2. Setup fallback to index.html for all app-routes
            endpoints.MapFallbackToFile( @"/myapp/{*path:nonfile}", @"MyApp/dist/index.html");
        });
    }