You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET 9中调用ASP.NET Core异步控制器方法返回HTTP 405错误

ASP.NET Core 异步API返回HTTP 405错误的排查与解决

问题描述

使用Razor页面的HttpClient调用ASP.NET Core(.NET 9)的异步API接口时返回HTTP 405 Method Not Allowed错误,但同控制器内的同步API可以正常响应。

调用代码:

var response = await Http.PostAsJsonAsync(nvgm.BaseUri + "api/User/check", user);

异步控制器方法:

[ApiController]
[Route("api/[Controller]")]
public class UserController : ControllerBase
{
    private readonly IUserRepo _repo;
        
    public UserController(IUserRepo repo)
    {
        _repo = repo;
    }

    [HttpPost]
    [Route("check")]
    public async Task<String> checkUser([FromBody] User givenUser)
    {
        User? user = await _repo.GetByEmailAsync(givenUser.Email);
        
        if (user != null)
        {
            return user.Name;
        }
        else
        {
            return "no work";
        }
    }
}

仓储层异步方法:

public async Task<User?> GetByEmailAsync(string email)
{
    return await _context.Users.FirstOrDefaultAsync(u => u.Email == email);
}

临时 workaround:通过同步API间接调用异步方法(但失去异步优势):

[HttpPost]
[Route("test")]
public String checkCheck([FromBody] User user)
{ 
    var asyncTest = checkUser(user);
    return "valid";
}

排查与解决步骤

1. 检查路由冲突

  • 确认是否存在其他控制器或路由模板与api/User/check匹配的非POST端点,导致路由匹配错误。
  • 验证方式:
    • 启动项目后访问Swagger页面(若已配置),查看User控制器下的check端点是否标记为POST方法。
    • 使用Postman直接发送POST请求到该接口,排除Razor页面HttpClient的调用问题。

2. 调整异步方法返回类型

ASP.NET Core的ApiController对返回类型有默认约定,直接返回Task<string>可能触发内容协商问题,建议改为ActionResult<string>

[HttpPost("check")] // 简化路由写法,合并HttpPost与Route特性
public async Task<ActionResult<string>> checkUser([FromBody] User givenUser)
{
    User? user = await _repo.GetByEmailAsync(givenUser.Email);
    
    return user != null ? user.Name : "no work";
}

3. 验证请求内容类型与参数绑定

  • 确保HttpClient发送的请求Content-Typeapplication/json,可显式指定以排除默认配置问题:
    var content = new StringContent(JsonSerializer.Serialize(user), Encoding.UTF8, "application/json");
    var response = await Http.PostAsync(nvgm.BaseUri + "api/User/check", content);
    
  • 检查User类的序列化兼容性:确保有无参构造函数,属性无[JsonIgnore]等影响绑定的特性。

4. 检查跨域配置(跨域场景下)

若Razor页面与API域名不同,需确认跨域策略允许POST方法:

// Program.cs中配置CORS
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll", policy =>
    {
        policy.AllowAnyOrigin()
              .AllowAnyMethod() // 确保包含POST方法
              .AllowAnyHeader();
    });
});

app.UseCors("AllowAll");

5. 确认中间件顺序

确保中间件加载顺序正确,UseCors()需放在UseRouting()之后、UseAuthorization()之前:

app.UseRouting();
app.UseCors("AllowAll");
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

6. 启用详细日志排查

appsettings.json中开启路由相关的Debug日志,查看请求匹配过程:

{
  "Logging": {
    "LogLevel": {
      "Microsoft.AspNetCore.Routing": "Debug",
      "Microsoft.AspNetCore.Mvc": "Debug"
    }
  }
}

启动项目后查看日志,确认请求是否被正确路由到目标异步方法。

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

火山引擎 最新活动