You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure App Service上ASP.NET Core Web API的POST/PUT请求间歇性500错误排查

问题描述

我们的Web应用采用REST API+SPA架构,基于.NET 6.0稳定运行多年,CORS配置无误。自2024年5月起,每日多次出现POST/PUT请求快速返回500错误的情况,持续5-15分钟后自动恢复,期间GET请求完全正常。

排查情况

  • 异常请求未被IIS及ASP.NET Core应用日志记录,且响应缺少正常500错误应有的X-Powered-By: ASP.NET头,说明请求可能未到达服务器。
  • 当前Azure App Service Plan资源使用率仅30%,排除资源耗尽问题。
  • 问题在Chrome、Edge、Safari中均有出现,但同一设备上可能Chrome出问题而Edge正常,重启浏览器即可解决。
  • 已确认移除Azure Traffic Manager后问题仍存在,部署至全新App Service、升级至.NET 8.0也无法解决。
  • 导出HAR文件对比正常与异常请求,未发现差异。

相关代码

Startup.cs配置

public class Startup
{
    readonly string _corsPolicyName = "corsOrigins";
    public IConfiguration Configuration { get; }
    public IWebHostEnvironment Environment { get; }

    private static IConfiguration config;
    public static IConfiguration GetConfiguration()
    {
        return config;
    }

    public Startup(IConfiguration configuration, IWebHostEnvironment environment)
    {
        Configuration = configuration;
        config = configuration;
        Environment = environment;
    }

    public void ConfigureServices(IServiceCollection services)
    {
        if (Environment.IsDevelopment())
            IdentityModelEventSource.ShowPII = true;

        // logging
        services.AddApplicationInsightsTelemetry();
        services.AddLogging(logging => 
        {
            logging.AddSimpleConsole();
            logging.AddAzureWebAppDiagnostics();
        });
        services.Configure<AzureFileLoggerOptions>(options =>
        {
            options.FileName = "filelog-";
            options.FileSizeLimit = 50 * 1024;
            options.RetainedFileCountLimit = 5;
        });
        services.Configure<AzureBlobLoggerOptions>(options =>
        {
            options.BlobName = "Backend.txt";
        });

        // so our claims will not be translated
        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

        // configure languages
        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en"),
                new CultureInfo("no")
            };
            options.DefaultRequestCulture = new RequestCulture("en");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });

        // add Identity
        services.AddIdentity<ApplicationUser, ApplicationRole>()
            .AddEntityFrameworkStores<AuthContext>()
            .AddRoleManager<RoleManager<ApplicationRole>>()
            .AddDefaultTokenProviders();
        services.AddUserAndPasswordPolicies();

        services.AddCors(options =>
        {
            {
                options.AddPolicy(_corsPolicyName, builder =>
                builder.SetIsOriginAllowedToAllowWildcardSubdomains()
                .WithOrigins("https://*.our.domain")
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials());
            }
        });

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(o =>
        {
            o.MapInboundClaims = false;
            o.Authority = Configuration.GetValue<string>("authServerUrl");
            o.Audience = "backend";
            o.RequireHttpsMetadata = true;
            o.SaveToken = true;
            o.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name",
                RoleClaimType = "role",
                ValidateIssuer = true,
                ValidateAudience = true
            };
        });

        services.AddControllersWithViews(options =>
        {
            options.Filters.Add<WebCustomExceptionFilter>();
        })
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
            });

        services.AddSignalRManager();

        services.AddRazorPages()
            .AddRazorRuntimeCompilation();

        services.AddSwaggerGenNewtonsoftSupport();
        services.AddSwaggerGen(options =>
        {
            options.SwaggerDoc("v1", new OpenApiInfo { Title = "server debug api spec", Version = "v1" });
            options.SchemaFilter<EnumSchemaFilter>();
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        StaticEnvironment.IsDebug = env.IsDevelopment();
        StaticEnvironment.ContentRootPath = env.ContentRootPath;

        app.UseCors(_corsPolicyName);

        if (env.IsDevelopment())
        {
            app.UseStaticFiles();
            app.UseDeveloperExceptionPage();
            app.UseSwagger();
            app.UseSwaggerUI(c => {
                c.DocumentTitle = "Backend Swagger docs";
                var sidebar = Path.Combine(env.ContentRootPath, "wwwroot/sidebar.html");
                c.HeadContent = File.ReadAllText(sidebar);
                c.InjectStylesheet("/colors.css");
                c.InjectStylesheet("/style.css");
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "server");
            });
        }
        else
        {
            app.UseHttpsRedirection();
            app.UseHsts();
        }

        // Localization
        app.UseRequestLocalization();
        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
     

        // Enable static files for use in MVC views. 
        app.UseStaticFiles();
        app.UseStaticFiles(new StaticFileOptions()
        {
            FileProvider = new PhysicalFileProvider(
                        Path.Combine(Directory.GetCurrentDirectory(), @"Style")),
            RequestPath = new PathString("/Style")
        });
    }
}

典型控制器签名

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class ImprovementController : ControllerBase

前端fetch代码

const fullUrl = `${baseUrl}/${url}`
const bearer = getBearer()
const connectionId = getConnectionId()
    
const req = {
    method: "POST",
    headers: {
        "Authorization": bearer,
        "Content-Type": "application/json"
    },
    body: JSON.stringify(data)
}
    
const res = await fetch(fullUrl, req)

内容的提问来源于stack exchange,提问作者atlmag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:12:05