【问题标题】:.NET Core 3.1/5 Api Querystring parameters do not work.NET Core 3.1/5 Api Querystring 参数不起作用
【发布时间】:2021-04-24 09:12:36
【问题描述】:

我注意到我的 .Net Core 3.1 和 .Net Core 5 API 有一些奇怪的地方。当有 2 种不同的 GET 方法来检索所有记录和通过 id 检索单个记录时,基于路由的参数有效,但查询字符串参数无效。

这里是一些示例代码

using Core5TestApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Core5TestApi.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class DataController : ControllerBase
    {
        private readonly ILogger<DataController> _logger;
        List<Data> allData = new List<Data>{
                new Data { Id = 1, Name = "Name 1" },
                new Data { Id = 2, Name = "Name 2" }
            };

        public DataController(ILogger<DataController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<Data> GetAll ()
        {
            return allData;
        }

        [HttpGet("{id}")]
        [Route("{id}")]
        public Data Get(int id)
        {
            return allData.First(i => i.Id == id);
        }
    }
}

以下是网址和结果

调用:http://localhost:51672/api/data 结果:[{"id":1,"name":"Name 1"},{"id":2,"name":"Name 2"}]

调用:http://localhost:51672/api/data/1 结果:{"id":1,"name":"Name 1"}

调用:http://localhost:51672/api/data?id=1 结果:[{"id":1,"name":"Name 1"},{"id":2,"name":"Name 2"}]

最后一个结果忽略querystring参数,执行GetAll。

我觉得我错过了一些非常基本的东西,尽管我相信我以前看过这项工作

我还尝试在 Get 方法中的参数之前使用 [FromQuery] 属性。这实际上打破了基于路由的参数路径

【问题讨论】:

    标签: c# asp.net-core .net-core asp.net-web-api-routing asp.net-core-5.0


    【解决方案1】:

    当您调用 http://localhost:51672/api/data?id=1 时,路由会忽略 ?id=1,因为没有任何路由。

    如果你想要 id=1 的记录,你必须使用 http://localhost:51672/api/data/1。

    并从最后一个动作中移除[Route("{id}")],应该是:

              [HttpGet("{id}")]
                public Data Get(int id)
            {
                return allData.First(i => i.Id == id);
            }
    

    但如果你仍然想使用 http://localhost:51672/api/data?id=1 你的行动应该是:

                 [HttpGet]
                public Data Get([FromQuery] int id)
            {
                return allData.First(i => i.Id == id);
            }
    

    或者您可以对两者都使用一个操作:

           //http://localhost:51672/api/data/getAll
            [HttpGet("GetAll")]
            public IEnumerable<Data> GetAll()
            {
                  return allData.ToArray();
            }
    
            [HttpGet("{id0?}")]
            [HttpGet]
            public Data Get(int id0, [FromQuery] int id)
            {
                var itemId =  id0 == 0 ? id : id0;
                if(itemId==0) ...return error
                return allData.FirstOrDefault(i => i.Id == itemId);
            }
    

    【讨论】:

    • 感谢您的回答谢尔盖。请确认我对您的回答的总结是否正确:使用基于路由的属性时,如果需要查询字符串和基于路由的参数,则它们不能使用相同的变量。另一个问题是为什么您没有简单的 [HttpGet] 属性并使用 [Route] 来指定它。 [HttpGet] 和 [Route] 在指定路径方面有什么区别(找不到任何解释)。似乎它们可以互换
    • 我从不在我的 API 中使用任何 [HttpGet] 或 [HttpPost]。你不需要它们。它们对代码没有任何影响。一些浏览器或 httpclients 可以使用 Post 而不是 Get。在这种情况下,如果您使用属性,您的 API 将无法工作。我更喜欢 [Route] 和明确的动作名称。在一个真正的应用程序中,您可以在一个控制器中执行一百个操作,而仅使用 get 或 post 属性是不可能的。古典休止符只在教科书中才有用。
    猜你喜欢
    • 2020-07-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    • 2020-07-25
    • 1970-01-01
    相关资源
    最近更新 更多