Параметры .NET Core 3.1 / 5 Api Querystring не работают

Я заметил кое-что странное с моими .Net Core 3.1 и .Net Core 5 Apis. Когда существует 2 разных метода GET для получения всех записей и одна запись по идентификатору, параметры на основе маршрута работают, а параметры строки запроса - нет.

Вот пример кода

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);
        }
    }
}

Ниже приведены URL-адреса и результаты.

Вызов: 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.

Мне кажется, что мне не хватает чего-то очень простого, хотя я считаю, что видел эту работу раньше

Я также попытался установить атрибут [FromQuery] перед параметром в методе Get. Это фактически нарушает путь параметра на основе маршрута


person Lee Z    schedule 20.01.2021    source источник


Ответы (1)


Когда вы вызываете http: // localhost: 51672 / api / data? Id = 1, маршрутизация игнорирует? Id = 1, поскольку для этого нет никакого маршрута.

Вы должны использовать http: // localhost: 51672 / api / data / 1, если вам нужна запись с id = 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);
        }
person Serge    schedule 20.01.2021
comment
Спасибо за ответ Сергей. Пожалуйста, подтвердите, правильно ли я изложил ваш ответ: при использовании атрибутов на основе маршрута, если требуются параметры на основе строки запроса и маршрута, они не могут использовать одну и ту же переменную. Другой вопрос, почему у вас нет простого атрибута [HttpGet], и вы используете [Route], чтобы указать это. В чем разница между [HttpGet] и [Route] с точки зрения указания пути (не могу найти ничего, что объясняет это). Вроде они взаимозаменяемые - person Lee Z; 22.01.2021
comment
Я никогда не использую [HttpGet] или [HttpPost] в своих API. Они тебе не нужны. Они не имеют никакого значения в коде. Некоторые браузеры или http-клиенты могут использовать Post вместо Get. В этом случае ваш Apis не будет работать, если вы используете атрибуты. Я предпочитаю [Маршрут] и явные имена действий. В реальном приложении у вас может быть сотня действий в одном контроллере, и невозможно использовать только атрибуты get или post. Классический отдых хорош только в тексбуке. - person Serge; 22.01.2021