Search code examples
.netangularsingle-page-application

.NET UseSpa() for two Angular applications


From my .NET 7 Application, I need to server two distinct Angular applications.

Desired URLs

| URL          | Expected Result            |
| -------------| -------------------------- |
| host/api/xyz | API Calls for .NET Backend |
| host/        | Frontend A                 |
| host/appB    | Frontend B                 |

Folder Structure

| Folder          | Content    |
| ----------------| ---------- |
| WebApi          | .NET DLLs  |
| WebApi/dist/ngA | Frontend A |
| WebApi/dist/ngB | Frontend B |

Startup.cs

//Frontend A
app.MapWhen(
    c => /* not api and not /appB -> equals host with no path */,
    staticApp =>
    {
        var pathA = Path.Combine(env.ContentRootPath, "dist/ngA");

        var staticFileOptions = new StaticFileOptions { FileProvider = new PhysicalFileProvider(pathA) };

        staticApp.UseSpaStaticFiles(staticFileOptions);

        staticApp.UseSpa(spa =>
        {
            spa.Options.DefaultPage = new PathString("/index.html");
            spa.Options.SourcePath = pathA;
            spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions { FileProvider = new PhysicalFileProvider(pathA)  };
        });
    });

//Frontend B
app.MapWhen(
    c => /* matches /appB */,
    staticApp =>
    {
        var pathB = Path.Combine(env.ContentRootPath, "dist/ngB");

        staticApp.UseSpaStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(pathB) });

        staticApp.UseSpa(spa =>
        {
            spa.Options.DefaultPage = new PathString("/index.html");
            spa.Options.SourcePath = pathB;
            spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions { FileProvider = new PhysicalFileProvider(pathB)  };
        });
    });

What is working

  • Api calls are properly routed
  • Frontend A under host with no path is properly routed

What does not work

  • Frontend B
    • index.html is properly loaded
    • But insted of the related .js and .css files, the index.html of Frontend B is returned

I do not quite understand how the logic behind the UseSpa() methods work and thus cant really tell, why it does not find the javascript and css files of the Angular application B.

Edit 1

  • Frontend B's index.html has a <base> tag, it looks like this: <base href="/appB"/>
  • The requests by the browser look fine by me. e.g. this one: localhost:56741/appB/runtime-es2015.49ae479b67d8b8914bd9.js However, here AppB's index.html is returned instead of the javascript content.
  • In the index.html of AppB, i have added /appB to the script tag. <script src="appB/runtime-es2015.49ae479b67d8b8914bd9.js" .../> Otherwise the request for the .js file would be sent on the base path (without appB/).

Solution

  • What I endet up doing, was:

    • use wwwroot
    • use UseStaticFiles() instead of UseSpaStaticFiles()

    Then it became pretty straight forward.

    var pathA = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "wwwroot/appA"));
    var staticFileOptionsA = new StaticFileOptions { RequestPath = "", FileProvider = pathA };
    app.UseStaticFiles(staticFileOptionsA);
    
    var pathB = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "wwwroot/appB"));
    var staticFileOptionsB = new StaticFileOptions { RequestPath = "/appB", FileProvider = pathB };
    app.UseStaticFiles(staticFileOptionsB);