CLI运行ASP.NET Core项目报错,Visual Studio运行正常求原因
问题:ASP.NET Core项目在CLI与Visual Studio运行时的异常差异分析
项目代码
Program.cs
using Platform; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Use(async (context, next) => { try { await next(); } catch (Exception e) { await context.Response.WriteAsync(e.ToString()); await context.Response.WriteAsync($"\n{e.TargetSite}"); } }); app.Map("/branch", branchBuilder => { branchBuilder.UseMiddleware<QueryStringMiddleware>(); branchBuilder.Use(async (context, next) => { await context.Response.WriteAsync("branch"); await next(context); }); }); app.MapGet("/", () => "Hello World!"); app.Run();
QueryStringMiddleware.cs
namespace Platform { public class QueryStringMiddleware { private RequestDelegate next; public QueryStringMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { if (context.Request.Method == HttpMethods.Get && context.Request.Query["custom"] == "true") { if (!context.Response.HasStarted) { context.Response.ContentType= "text/plain"; } await context.Response.WriteAsync("class middleware\n"); } await next(context); } public static async Task Jip(HttpContext context) { await context.Response.WriteAsync("jipjip\n"); } } }
问题现象
- 通过CLI运行项目,发起
/branch?custom=true请求时抛出异常,异常信息如下:
class middleware branchSystem.InvalidOperationException: StatusCode cannot be set because the response has already started. at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value) at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value) at Microsoft.AspNetCore.Builder.ApplicationBuilder.<>c.b__18_0(HttpContext context) at Program.<>c.<<$>b__0_3>d.MoveNext() in D:\develop\Platform\Program.cs:line 28 --- End of stack trace from previous location --- at Platform.QueryStringMiddleware.Invoke(HttpContext context) in D:\develop\Platform\Middleware.cs:line 23 at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.InvokeCore(HttpContext context, PathString matchedPath, PathString remainingPath) at Program.<>c.<<$>b__0_0>d.MoveNext() in D:\develop\Platform\Program.cs:line 13 Void ThrowResponseAlreadyStartedException(System.String)
- 在Visual Studio中运行相同项目并发起该请求,无异常,响应正常。
差异原因分析
核心差异源于两种运行环境的响应状态码处理逻辑不同:
- 请求进入
/branch分支的中间件链后,QueryStringMiddleware和后续的匿名中间件已经向响应流写入了内容,此时Response.HasStarted标记为true。 - 分支内未配置任何终结点(如
MapGet),ASP.NET Core框架会尝试返回404状态码以表示请求路径未匹配到处理逻辑。 - CLI启动时默认使用Kestrel服务器,Kestrel遵循严格的HTTP规范:当响应流已启动(即已向客户端发送数据),不允许再修改状态码,因此直接抛出
StatusCode cannot be set because the response has already started异常。 - Visual Studio默认使用IIS Express运行,IIS Express的响应处理逻辑为了开发便利放宽了限制,允许在响应已启动的情况下设置状态码(或忽略该错误继续完成响应),因此不会触发异常。
内容的提问来源于stack exchange,提问作者Daniil Lozhkin
相关产品推荐
相关产品推荐

