V13.4 Angular & ASPNET CORE I followed this instrucktion: https://docs.aspnetzero.com/aspnet-core-angular/latest/Deployment-Angular
Hi ASP.NET Zero Support Team,
we are migrating an existing ASP.NET Zero application (ASP.NET Core + Angular, merged solution / “all-in-one”) from Azure Windows App Service to Azure Linux App Service (Code) using .NET 8 runtime.
The application starts successfully and the backend is reachable, but the Angular SPA behaves incorrectly:
Navigating to https://01.pliwfm.one shows the backend (not the Angular UI).
We must explicitly open https://01.pliwfm.one/login to reach the Angular UI.
On the Angular login page, clicking the login button does nothing (no redirect / no API call).
In the UI we also see a “Continue with Google” button even though Google auth is disabled in our config.
This setup works on Windows App Service.
What we did (based on ASP.NET Zero docs)
We followed the merged Angular deployment instructions:
dotnet publish -c Release on the *.Web.Host project
After publish, moved all files from: wwwroot/dist → wwwroot (so Angular index.html is directly in /wwwroot)
We also update both:
Angular settings: assets/appconfig.production.json
Backend settings: appsettings.Production.json
Environment
Hosting: Azure App Service (Linux, Code)
Runtime: .NET 8 (Oryx startup)
Startup command: dotnet WFMOne.Web.Host.dll
Angular is served from: /home/site/wwwroot (merged deployment)
Current behavior / suspected issue
It looks like the SPA fallback/routing is not working as expected on Linux, so:
/ does not resolve to index.html
some auth/login related requests might be returning index.html or being swallowed
possibly reCAPTCHA v3 token generation/validation fails silently
In our Startup.cs we currently have a SPA fallback middleware like:
app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) { context.Request.Path = "/index.html"; await next(); } }); app.UseStaticFiles();
(We can provide full Startup.cs if needed.)
Questions
In merged mode, should / always resolve to Angular index.html out of the box, even on Linux App Service?
Are there known differences on Linux regarding:
static file hosting order (UseStaticFiles, fallback middleware order)
default documents (index.html)
routing that could cause / to go to backend controllers instead of SPA?
Is there an ASP.NET Zero recommended configuration for hosting merged Angular + API on Linux App Service (Code), especially to ensure SPA fallback works and auth flows are not intercepted?
The “login button does nothing”: are there known cases where reCAPTCHA or dynamic JS bundle loading fails because of wrong paths (e.g. bundling step npm run create-bundles, missing assets, wrong base href)?
What is the exact recommended folder structure after publish on Linux (should Angular end up in /wwwroot root, or /wwwroot/dist, or /wwwroot/wwwroot depending on template)?
Logs / evidence
App starts successfully; container logs show startup command executed and runtime is running. We can provide:
Browser DevTools network log (requests around login click)
screenshot / HAR file
current published folder tree
Thanks in advance — we want to keep both deployment options (merged and separated), but first we need the merged Linux setup to behave exactly like Windows.
1 Answer(s)
-
0
Hi @pliaspzero
This issue is not specific to ASP.NET Zero itself, but to differences between Windows App Service (IIS) and Linux App Service (Kestrel/Oryx) when hosting a merged Angular + ASP.NET Core application.
On Windows, IIS automatically serves index.html as a default document. On Linux App Service, there is no default document behavior, so / is handled by ASP.NET Core routing unless a proper SPA fallback is configured.
In our case, the root cause was:
SPA fallback middleware order
- UseStaticFiles() must run before the SPA fallback
- SPA fallback must be the last middleware
Angular files must be published directly under /wwwroot
- index.html must be located at /wwwroot/index.html
- Not under /wwwroot/dist or nested folders
Correct fallback implementation
app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.StartsWithSegments("/api")) { context.Response.StatusCode = 200; context.Request.Path = "/index.html"; await next(); } });After correcting the middleware order and ensuring Angular is deployed to the /wwwroot root directory, the following issues are resolved:
- / correctly loads Angular UI
- Login button works again
- OAuth / reCAPTCHA behaves correctly
- UI configuration matches backend config
This setup now behaves exactly the same way as the Windows Application Service.
Related Document
If this solution does not fully resolve the issue, we would be happy to assist further.
Markdown is supportedCopy & paste or drag & drop images (max 30 MB per image)