【问题标题】:Why is my server responding Method Not Allowed on GET preflight request and saying Allow Delete?为什么我的服务器在 GET 预检请求上响应不允许的方法并说允许删除?
【发布时间】:2021-07-29 23:04:41
【问题描述】:

我有一个 .Net Core 3.1 Web API,它设置为允许所有方法用于我的测试目的。 当我在特定端点上运行 HTTP GET 请求时,我得到 405 Method Not Allowed 并且响应标头说 Allow: DELETE.

此控制器和我的其他控制器中的所有其他端点都按预期工作。

这是我的控制器代码:

[Authorize]
[Produces("application/json")]
[Route("api/User")]
public class UserAccountController : ControllerBase
{
    [HttpGet]
    [AllowAnonymous]
    [Route("ConfirmAccountEmail")]
    protected override async Task<IActionResult> ConfirmAccountEmail(string token, string email)
    {
        // confirm email code here...
    }

    [HttpDelete("{id}")]
    [Route("DeleteUserAccount")]
    [Authorize(Roles = AdminToken)]
    public override async Task<IActionResult> DeleteUserAccount([FromRoute] int id)
    {
        // user delete code here...
    }
}

在我的 Startup.cs 中

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime)
{
    app.UseRouting();
    app.UseCors(builder =>
    {
        builder.AllowAnyHeader().AllowAnyOrigin().AllowAnyMethod(); // just for testing
    });
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoint(e => 
    {
        e.MapControllers();
    ));
}

这是我的请求(来自 Postman)的样子

这是我从服务器返回的响应标头

我尝试将 Route 和 HTTP 类型更改为 POST(并将参数作为表单数据传递)。

我尝试删除那个 Delete 端点,在这种情况下我得到 404 Not Found。所以这让我相信,出于某种原因,控制器映射正在将一个路由绑定到我的另一个路由的删除方法,但我不明白为什么。

我觉得我错过了一些明显的东西,但我不知道现在是什么。

感谢您的帮助!

【问题讨论】:

  • 需要检查的一点:对 UseCors 的调用必须放在 UseRouting 之后,但在 UseAuthorization 之前。
  • 谢谢,但这就是我在上面的代码中已经有了它。
  • protected override 你没有收到编译器警告吗?
  • @nvoigt 我不这样做,因为我的真实代码正在实现一个抽象类。但是,事实证明,这是一个问题,因为受保护的方法不能用作 API 端点。

标签: c# asp.net-core-webapi asp.net-core-3.1


【解决方案1】:

当我在特定端点上运行 HTTP GET 请求时,我得到 405 Method Not Allowed 并且响应标头显示 Allow: DELETE。

对于这个关于“动作定义”的文档,你可以找到:

控制器上的公共方法(具有NonAction 属性的方法除外)都是操作。

请尝试在您的ConfirmAccountEmail 方法中将protected 修改为public,如下所示。

public async Task<IActionResult> ConfirmAccountEmail(string token, string email)
{
    // confirm email code here...

【讨论】:

  • 就是这样!我正在为其他目的实现一个抽象类,但没有意识到受保护的修饰符不适用于 API 端点。谢谢!
【解决方案2】:

通常您可以收到 CORS,但根本问题与 CORS 规则无关。我建议试试这个

[Authorize]
[Produces("application/json")]
[Route("api/User")]
public class UserAccountController : ControllerBase
{
    [HttpGet]
    [AllowAnonymous]
    protected override async Task<IActionResult> ConfirmAccountEmail(string token, string email)
    {
    // confirm email code here...
    }

    [HttpDelete("{id}")]
    [Authorize(Roles = AdminToken)]
    public override async Task<IActionResult> DeleteUserAccount([FromRoute] int id)
    {
    // user delete code here...
    }

}

即从操作方法中删除 Route 属性,然后像这样测试端点 GET https://localhost:4000/api/UserDELETE https://localhost:4000/api/User/1234

另一种选择是删除 HTTP 动词属性

[Authorize]
[Produces("application/json")]
[Route("api/User")]
public class UserAccountController : ControllerBase
{

   [AllowAnonymous]
   [Route("ConfirmAccountEmail")]
   protected override async Task<IActionResult> ConfirmAccountEmail(string token, string email)
{
    // confirm email code here...
}


   [Route("DeleteUserAccount/{id}")]
   [Authorize(Roles = AdminToken)]
   public override async Task<IActionResult> DeleteUserAccount([FromRoute] int id)
{
    // user delete code here...
}

}

然后像GET https://localhost:4000/api/UserConfirmAccountEmailDELETE https://localhost:4000/api/DeleteUserAccount/123这样调用端点

【讨论】:

    猜你喜欢
    • 2021-03-21
    • 1970-01-01
    • 2016-12-12
    • 2020-07-30
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2020-03-30
    相关资源
    最近更新 更多