【问题标题】:ASP.NET Core WEB API Problem with GET parameters in API methodASP.NET Core WEB API API 方法中的 GET 参数问题
【发布时间】:2020-02-08 06:59:02
【问题描述】:

我有这个控制器

[ApiController]
    [Route("api/[controller]")]
    public class FamiliesController : ControllerBase
    {
        readonly FamilyFinanceContext db;
        public FamiliesController(FamilyFinanceContext context)
        {
            db = context;
        }


        [HttpDelete("deletefamily")]
        public async Task<ActionResult<Family>> DeleteFamilly(int id)
        {
            Family user = db.Families.FirstOrDefault(x => x.Id == id);
            if (user == null)
            {
                return NotFound();
            }
            db.Families.Remove(user);
            await db.SaveChangesAsync();
            return Ok(user);
        }
    }

在调用https://localhost:44373/api/families/deletefamily?id=2 之后我有这个错误 - HTTP ERROR 405 理论上,这个 GET 参数必须有效。我做错了什么?

【问题讨论】:

  • 您要求的是 DELETE ([HttpDelete("deletefamily")]) 而不是 GET。两者都需要支持吗?
  • 你如何调用这个API?我认为问题出在您的客户端
  • 如果您使用诸如 Chrome 之类的 Web 浏览器进行调用,那将执行 GET 并且您的控制器期待 DELETE

标签: asp.net-core asp.net-core-webapi


【解决方案1】:

正如 ESG 所述,您尝试执行 DELETE,因此您需要使用 DELETE 动词,而不是 GET 动词。由于这个原因,您会收到 405 Method Not Allowed(您不能在 DELETE 操作上使用 GET)。您应该使用 PostMan (https://www.postman.com/) 之类的工具来创建您的 DELETE 请求,因为您不能仅仅在浏览器中轻松地做到这一点。

为了更符合 REST 约定,您应该考虑稍微更改您的 DELETE 方法:

    [HttpDelete("{id}")]
    public async Task<ActionResult> DeleteFamily([FromRoute] int id)
    {
        Family user = db.Families.FirstOrDefault(x => x.Id == id);
        if (user == null)
        {
            return NotFound();
        }
        db.Families.Remove(user);
        await db.SaveChangesAsync();
        return NoContent();
    }

然后您将其称为 DELETE https://localhost:44373/api/families/2

通过使用 [HttpDelete("{id}"] 属性,您将 id 从查询字符串移动到 URI,这更符合 REST 约定(URI 代表一个对象)。查询字符串参数更多通常用于可选功能,例如过滤、排序等,而不是表示对象本身的端点。

通常 DELETE 操作不会返回内容,但这取决于您。如果你真的想返回用户对象,那么坚持使用 Ok(user),但 NoContent 更典型的 DELETE 动词。

【讨论】:

  • 您还应该对参数使用装饰器,在您的情况下为[FromRoute] int id,或者如果他将其保留为查询参数[FromQuery] int id。此外,仅当您的路线除了类型之外都相同时,才需要在 {id:long} 中指定参数的类型,IMO 无论如何都不应该这样做。
  • @Bodacious,这些都是好点。我从来没有真正打算在其中输入类型(“long”),但我从其他一些代码中剪切和粘贴。我已经更新了代码。
猜你喜欢
  • 2021-08-11
  • 2018-01-27
  • 2021-07-26
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
  • 2020-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多