Angular + . net Core -当从浏览器调用API时,仅生产环境中的路由问题



我有这个奇怪的问题,当我等待30+秒之前,我做一个浏览器API调用它说以下消息:

Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'api/tcform/GetCurrentDate' Error: Cannot match any routes. URL Segment: 'api/tcform/GetCurrentDate'     at Jt.noMatchError (https://mysite/main.3a68a3e49f0763cc89ec.js:1:265122)     at o.selector (https://mysite/main.3a68a3e49f0763cc89ec.js:1:264852)     at o.error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:894743)     at o._error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884678)     at o.error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884475)     at o._error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884678)     at o.error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884475)     at F._error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884678)     at F.error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884475)     at I._error (https://mysite/main.3a68a3e49f0763cc89ec.js:1:884678)

的例子

工作示例不工作,给我上面的错误信息

如果我在这30秒内进入周期,它就会一直工作。这件事已经困扰我一个月了。有谁知道这种行为的问题是什么,我该如何解决?

详情如下。

  • 只发生在生产版本
  • 托管在IIS上
  • 我使用"npm run build -- --configuration production"然后我复制目录上的dist文件夹的内容。然后我从VS2019发布并将发布的内容复制到我的服务器IIS。
  • 我没有使用哈希策略,我不打算,但我试过了,我仍然有同样的问题。

我会张贴我的Startup.cs…如果您需要任何其他文件来确定,我会尝试提供它们

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MotoYdrogiosVS.Repository;
using MotoYdrogiosVS.Middleware;
using MotoYdrogiosVS.Services.DataProtector;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Net.Http.Headers;
namespace MyNamespace
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddSingleton<IGlobalVariablesRepository, GlobalVariablesRepository>();
services.AddSingleton<IProtectorService, ProtectorService>();
//var provider = services.BuildServiceProvider();
//var cipher = provider.GetService<IProtectorService>();
services.AddScoped<IAuthenticationRepository, AuthenticationRepository>();
services.AddScoped<ITcAccountsRepository, TcAccountsRepository>();
services.AddScoped<IErrorRepository, ErrorRepository>();
services.AddScoped<IPriceTableRepository, PriceTableRepository>();
services.AddScoped<IReportsRepository, ReportsRepository>();
services.AddScoped<ITcDriverFormRepository, TcDriverFormRepository>();
services.AddScoped<ITcFormRepository, TcFormRepository>();
services.AddScoped<IVehiclesMakeRepository, VehiclesMakeRepository>();
services.AddScoped<IJCCRepository, JCCRepository>();
services.AddScoped<ISystemRepository, SystemRepository>();
//services.AddEntityFrameworkSqlServer();

//commented out by charis at 27/6/2022
services.AddMvc().AddNewtonsoftJson();
services.AddMvcCore();
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
//configuration.RootPath = "ClientApp/dist";
});
services.AddSession();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
//app.Use(async (context, next) =>
//{

//    await next();
//    if (context.Request.Path.Value.Contains("api"))
//    {
//        await next();
//    }
//    if (context.Response.StatusCode == 404 && !System.IO.Path.HasExtension(context.Request.Path.Value))
//    {
//        context.Request.Path = "/index.html";
//        await next();
//    }
//});
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
//app.UseDeveloperExceptionPage();
}
else
{
//app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.Use(async (context, next) =>
{
//var url = context.Request.Path.Value;
//if (url.Contains("/api/tcform/GetCurrentDate"))
//{
//    // ...do your things
//    context.Response.Redirect(url, permanent: false);
//    return;   // short circuit
//}

await next();
if (context.Response.StatusCode == 404 && !System.IO.Path.HasExtension(context.Request.Path.Value) &&
!context.Request.Path.Value.Contains("api"))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseHsts();
}
//app.UseStaticFiles();
//app.UseDefaultFiles();
app.UseStaticFiles();
//app.UseDefaultFiles();
//app.UseStaticFiles(new StaticFileOptions
//{
//    OnPrepareResponse = context =>
//    {
//        if (context.File.Name == "index.html")
//        {
//            context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store");
//            context.Context.Response.Headers.Add("Expires", "-1");
//        }
//    }
//});
if (!env.IsDevelopment())
{
//app.UseMvc();
//app.UseStatusCodePagesWithReExecute("/"); // <-- added to redirect to angular
app.UseSpaStaticFiles(new StaticFileOptions()
{
OnPrepareResponse = ctx =>
{
var headers = ctx.Context.Response.GetTypedHeaders();
headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromDays(0)
};
}
});
}
app.UseRouting();
app.UseSession();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
// To learn more about options for serving an Angular SPA from ASP.NET Core,
// see https://go.microsoft.com/fwlink/?linkid=864501
spa.Options.SourcePath = "ClientApp";
spa.Options.DefaultPageStaticFileOptions = new StaticFileOptions()
{
OnPrepareResponse = ctx => {
var headers = ctx.Context.Response.GetTypedHeaders();
headers.CacheControl = new CacheControlHeaderValue
{
Public = true,
MaxAge = TimeSpan.FromDays(0)
};
}
};
//spa.Options.StartupTimeout = new TimeSpan(0, 10, 0);
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
}
}
}

经过一个月的研究,我终于找到了我的问题。

在我的app.module.ts

中有这段代码
ServiceWorkerModule.register('ngsw-worker.js', {
enabled: environment.production,
// Register the ServiceWorker as soon as the application is stable
// or after 30 seconds (whichever comes first).
registrationStrategy: 'registerWhenStable:30000'
})

我不知道它是什么,它来自我最可能使用的模板,但它是我所有问题的问题。我现在把它注释掉了,但似乎我的web应用程序没有它也能正常工作。