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

使用GetEndPoint方法无响应,不使用则报405错误的原因咨询

ASP.NET Core中自定义中间件导致405错误未正常返回的问题分析

我遇到一个ASP.NET Core的问题,两段代码仅差一个自定义中间件,请求结果却完全不同:

Code 1(带自定义中间件)

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseRouting();

app.Use(async (context, next) =>
{
    var endPoint = context.GetEndpoint();

    if (endPoint != null)
    {
        await context.Response.WriteAsync($"EndPoint: {endPoint}\n");
        await context.Response.WriteAsync($"Display Name: {endPoint.DisplayName}\n");
        await context.Response.WriteAsync($"Request Delegate: {endPoint.RequestDelegate}\n");
        await context.Response.WriteAsync($"Meta Data: {endPoint.Metadata}\n");
    }
    await next(context);
});

app.UseEndpoints(endpoint => {
endpoint.MapGet("map1", async (context) => {
    await context.Response.WriteAsync("In Map 1");
});

endpoint.MapPost("map2", async (context) => {
    await context.Response.WriteAsync("In Map 2");
});
});

app.Run(async (context) => {
await context.Response.WriteAsync("Neither in Map 1 nor in Map 2");
});

app.Run();

现象:用GET方法请求/map2时,浏览器卡住,Postman报错(无响应或超时)。

Code 2(注释自定义中间件)

using System.ComponentModel.Design.Serialization;
using Microsoft.AspNetCore.Authentication;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseRouting();

//app.Use(async (context, next) =>
//{
//    var endPoint = context.GetEndpoint();
//    if (endPoint != null)
//    {
//        await context.Response.WriteAsync($"EndPoint: {endPoint}\n");
//        await context.Response.WriteAsync($"Display Name: {endPoint.DisplayName}\n");
//        await context.Response.WriteAsync($"Request Delegate: {endPoint.RequestDelegate}\n");
//        await context.Response.WriteAsync($"Meta Data: {endPoint.Metadata}\n");
//    }
//    await next(context);
//});

app.UseEndpoints(endpoint => {
endpoint.MapGet("map1", async (context) => {
    await context.Response.WriteAsync("In Map 1");
});

endpoint.MapPost("map2", async (context) => {
    await context.Response.WriteAsync("In Map 2");
});
});

app.Run(async (context) => {
await context.Response.WriteAsync("Neither in Map 1 nor in Map 2");
});

app.Run();

现象:用GET方法请求/map2时,浏览器和Postman均返回405 Method Not Allowed错误,这个结果我能理解,但不知道为什么Code 1不会返回同样的错误,反而出现无响应的情况。


问题原因分析

这是因为自定义中间件提前向响应流写入了内容,打断了ASP.NET Core内置的405错误处理逻辑:

  1. 请求进入管道后,UseRouting会完成端点匹配,用GET请求/map2时,路由系统会找到对应的MapPost("map2")端点(虽然该端点只接受POST方法)。
  2. 在Code 2中,没有自定义中间件,UseEndpoints会检查请求方法与端点允许的方法是否匹配,发现不匹配后,直接返回405错误,同时自动处理响应状态码、Allow头等头部信息。
  3. 在Code 1中,自定义中间件在UseEndpoints之前执行,此时context.GetEndpoint()已经能拿到匹配到的map2端点,中间件直接调用Response.WriteAsync向响应流写入了内容。一旦响应流开始写入,ASP.NET Core就会判定响应已启动,后续UseEndpoints中的405错误处理逻辑会被跳过——因为响应状态和内容已经无法修改。
  4. 但匹配到的map2端点的请求委托只处理POST请求,GET请求进入后不会执行任何写入操作,同时后续的app.Run委托也不会触发(因为端点已经匹配成功),导致响应流只写入了中间件的内容,但没有完成响应的收尾,客户端会一直等待直到超时,表现为浏览器卡住、Postman报错。

简单总结:中间件提前启动了响应,让405错误逻辑无法触发,而匹配到的端点又不处理当前请求方法,最终导致响应未完成,客户端超时。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:46:11