【问题标题】:HTTP 405 upon GET request when retrieving data检索数据时 GET 请求时的 HTTP 405
【发布时间】:2020-02-27 20:47:31
【问题描述】:

我一直在尝试为一个项目制作一个 REST API。从技术上讲,以前从未这样做过,但有一件事让我有点困惑。我有一个对服务器的 GET 请求,该请求从我的 DbContext 正确返回了一个客户端列表,但是我现在的第二个 get 操作请求似乎只返回一个 HTTP 405 错误,我似乎无法找出原因.有什么想法吗?

我已尝试将其设为 actionResult,但可能不正确?我知道当操作只是一个返回“值”或另一个字符串的字符串时它起作用,但似乎无法像第一个 GET 方法那样返回一个对象

获取存储库中所有客户端的有效 get 方法

        // GET: api/Client
        [HttpGet]
        public IEnumerable<Logic.Objects.Client> Get()
        {
            return _repository.GetClients();
        }

返回 405 的第二种方法


        //GET: api/Client/5
        [HttpGet("{id}", Name = "Get")]
        public Task<Client> Get(Guid id)
        {
            return _repository.GetClientByIDAsync(id);
        }

如果我向 api/Client/{id} 添加了一个客户端 ID,那么预期的结果将是返回该特定客户端的信息,而不是所有信息,因为这是一个唯一标识符,并且不会与任何标识符相同其他客户端,保持 RESTful 思维方式。

405 是它抛出的唯一错误,除非它的 ID 不正确,不是 Guid,在这种情况下,它会在方法中抛出异常,这也让我知道它正在到达那里,只是它应该如何处理有问题要返回它的值吗?

编辑:对于那些感兴趣的人来说,这是整个控制器类。有些方法还没有实现,所以它们与问题并不相关。至少我不会这么想。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dbnd.Logic.Interfaces;
using Dbnd.Logic.Objects;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Dbnd.Logic.Objects;

namespace Dbnd.Api.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ClientController : ControllerBase
    {
        private IRepository _repository;

        public ClientController(IRepository repository)
        {
            _repository = repository;
        }
        // GET: api/Client
        [HttpGet]
        public IEnumerable<Logic.Objects.Client> Get()
        {
            return _repository.GetClients();
        }

        //GET: api/Client/5
        [HttpGet("{id}", Name = "Get")]
        public Task<Client> Get(Guid id)
        {
            return _repository.GetClientByIDAsync(id);
        }

        // POST: api/Client
        [HttpPost]
        public ActionResult Post([FromBody, Bind("UserName, Email, PasswordHash")] Client client)
        {
            _repository.CreateClientAsync(client.UserName, client.Email, client.PasswordHash);

            return CreatedAtRoute("Get", client);
        }

        // PUT: api/Client/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] string value)
        {
        }

        // DELETE: api/ApiWithActions/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
}

【问题讨论】:

  • 那你怎么调用这个方法呢?另外,为什么要将 int 转换为 Guid,为什么不首先传入正确的 Guid?
  • 试试这个return Ok(client);
  • 如何将 int 解析为 Guid?
  • 返回Ok(client);,结果相同。此外,首先将其设为 Guid 而不是 int 而不对其进行解析。两种结果仍然有 405。理论上,该方法应该在用户时调用,例如在 url 栏中键入 api/Client/(无论他们的 ID 是什么)
  • 尝试在第二次调用中更改属性:[HttpGet("{id}")]

标签: c# asp.net api


【解决方案1】:

我有另一个 api,它的工作方式与您第一次发布的方式完全相同(使用 actionResults)。我在您的代码中找不到问题。它可能是您所说的设置,但也可能是您组合 URL 的方式。

我最好的选择是你的存储库没有返回元素,但同样,它不应该给你一个 405,而是一个 404 未找到。我猜你的 _repository 的响应给出了一个错误。

也许一个故障排除的想法是尝试一个Postman 请求来获取并在你的控制器中设置一个断点,看看你是否能看到问题出在哪里。

我刚刚创建了一个测试项目来尝试重现您的问题,但它工作正常。我遵循了微软的这个教程:https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-3.0&tabs=visual-studio

这是我生成的控制器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ClientsController : ControllerBase
    {
        private readonly ClientContext _context;

        public ClientsController(ClientContext context)
        {
            _context = context;
        }

        // GET: api/Clients
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Client>>> GetClients()
        {
            return await _context.Clients.ToListAsync();
        }

        // GET: api/Clients/5
        [HttpGet("{id}")]
        public async Task<ActionResult<Client>> GetClient(long id)
        {
            var client = await _context.Clients.FindAsync(id);

            if (client == null)
            {
                return NotFound();
            }

            return client;
        }

        // PUT: api/Clients/5
        [HttpPut("{id}")]
        public async Task<IActionResult> PutClient(long id, Client client)
        {
            if (id != client.Id)
            {
                return BadRequest();
            }

            _context.Entry(client).State = EntityState.Modified;

            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ClientExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        // POST: api/Clients
        [HttpPost]
        public async Task<ActionResult<Client>> PostClient(Client client)
        {
            _context.Clients.Add(client);
            await _context.SaveChangesAsync();

            return CreatedAtAction("GetClient", new { id = client.Id }, client);
        }

        // DELETE: api/Clients/5
        [HttpDelete("{id}")]
        public async Task<ActionResult<Client>> DeleteClient(long id)
        {
            var client = await _context.Clients.FindAsync(id);
            if (client == null)
            {
                return NotFound();
            }

            _context.Clients.Remove(client);
            await _context.SaveChangesAsync();

            return client;
        }

        private bool ClientExists(long id)
        {
            return _context.Clients.Any(e => e.Id == id);
        }
    }
}

我知道它不能直接回答您的问题,但我希望它能给您带来思考并帮助您解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-24
    • 1970-01-01
    • 2015-04-23
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    相关资源
    最近更新 更多