I have a new ASP.NET Core Web API (.NET 8.0) and planned to host my Angular (^18.0.0) single page application (SPA) in the wwwroot folder. At development time, I want to run/debug the SPA locally in Node.js using ng serve and at production time, I want to serve up index.html and the uniquely named main.js, polyfills.js and styles.css files from wwwroot, which I created by running ng build --configuration production. It works fine in the production scenario, but in development, it's as if ASP.NET is swallowing or blocking requests to the API routes. Here's the basic project structure with the WeatherForecastController: /ProjectName │ ├── /Controllers │ ├── WeatherForecastController.cs │ ├── /wwwroot │ ├── /webclient │ │ ├── /src │ │ └── ... │ ├── index.html │ └── ... (other .js & .css for Angular) │ ├── appsettings.json ├── Program.cs └── ... Here's the contents of Program.cs: namespace IntegratedSpaWebApi; 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.UseAuthorization(); app.MapControllers(); app.UseSpa(config => { config.Options.SourcePath = "webclient"; if (app.Environment.IsDevelopment()) { // This next line is the feature that causes the problem for me... config.UseProxyToSpaDevelopmentServer("http://localhost:4200/"); } }); app.Run(); } } I did a couple of other relevant things while creating the project: Checked "Enable OpenAPI support" before creating it in Microsoft Visual Studio 2022 Enterprise. Added the NuGet package Microsoft.AspNetCore.SpaServices.Extensions (Version="8.0.1") The NuGet package is what enables the app.UseSpa(...) extension method to be called, and SwaggerGen is helpful in demonstrating that something's gone wrong. To reproduce the issue, I can start the .NET project and navigate to https://localhost:7087/swagger/index.html where I have the option to "Try Out" the GET /WeatherForecast method (with no parameters). What happens next depends on the environment: Production 200 JSON response comes back as expected Development (assuming ng serve has also been started) 404 HTML response comes back (shown below outside the markdown list) <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot GET /WeatherForecast</pre> </body> </html> It's probably worth noting that the integrated Angular single page application runs correctly in both Production and Development cases if I request index.html. It's also worth noting that I when I can't access the Web API from SwaggerGen (development) then a simple GET for https://localhost:7087/WeatherForecast in the browser also returns the same 404 HTML. But when I can access the Web API from SwaggerGen (production) then the same URL also returns 200 JSON. Very consistent. It feels like the call to UseProxyToSpaDevelopmentServer is what's tripping me up. I have tried it both above and below the call to MapControllers with no change in behaviour, but I wonder if the timing of the UseSpa configuration callback has something to do with it. It seems strange that SwaggerGen correctly routes swagger/index.html but the call to the WeatherForecastController (whose route I've tried specifying as both [Route("[controller]")] and [Route("api/weather")] (but not concurrently, of course)) does not correctly route the request. Any idea what I'm doing wrong? The convenience of being able to debug Angular at the same time as debugging ASP.NET and doing that without any CORS issues seems immense to me, and I can't believe that this doesn't work, just that I'm doing it wrong. Continue reading...