Содержание
Одним из способов передачи данных в контроллер, помимо параметров маршрута, является также использование параметров запроса в URL. Параметры запроса могут активно использоваться в проекте Web API, например, для определения пользователем фильтров данных, направления сортировки, постраничного вывода результатов и т.д. ASP.NET Core позволяет передавать с помощью параметров запроса как простые типы данных, так и сложные. Этот способ передачи данных в контроллер является одним из способов, используемых системой привязки модели в ASP.NET Core.
Параметры запроса в URL указываются после символа ?
и представляют собой пары «имя-значение», которые отделяются друг от друга символом &
. Например, в URL
http://localhost?id=3&name=Bob
определено два параметра:
id
со значением3
name
со значениемBob
Передача простых типов данных (строк, чисел и т.д.)
Создадим новое приложение ASP.NET Core Web API с использованием контроллеров и добавим в него новы контроллер:
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { [HttpGet] public int Get(int number) { return ++number; } }
действие Get()
контроллера возвращает число на 1 больше, чем переданное в параметре number
. При этом, number
является параметром запроса в URL и должен передаваться так:
https://localhost:7098/api/Values?number=1
то есть имя параметра в URL должно полностью совпадать с именем параметра в методе. Аналогичным образом можно передавать несколько параметров, представляющих собой простые значения, например, добавим новое действие в контроллер:
[HttpGet("person")] public string Get(int id, string name) { return $"Id = {id} Name = {name}"; }
выполнив запрос вида https://localhost:7098/api/Values/person?id=1&name=Bob
на выходе получим строку
Id = 1 Name = Bob
Передача объектов
Чтобы передать в параметрах запроса целый объект достаточно определить каждое свойство объекта как отдельный параметр. Например, добавим в наше приложение следующий класс:
public class User { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public string Password { get; set; } }
Теперь добавим в контроллер новое действие:
[HttpGet("class")] public string Get([FromQuery] User user) { return $"Id = {user.Id} Name = {user.Name} Email = {user.Email} Password = {user.Password}"; }
В этом действии мы указываем для параметра user атрибут [FromQuery]
, который указывает, что параметр должен быть привязан с помощью строки запроса. Теперь запустим приложение и, выполнив запрос вида: https://localhost:7098/api/Values/class?Id=1&Name=Bob&Email=bob%40mail.com&Password=1234567
, получим следующую строку
Id = 1 Name = Bob Email = bob@mail.com Password = 1234567
Также, мы можем получить JSON-объект, если изменим действие следующим образом:
[HttpGet("class")] public User Get([FromQuery] User user) { return user; }
в этом случае, объект типа User
будет по умолчанию сериализован в JSON и в Swagger мы увидим следующий результат:
{ "id": 1, "name": "Bob", "email": "bob@mail.ru", "password": "1234567" }
Передача массивов
Чтобы передать в действие контроллера массив мы можем поступить двумя способами:
- в качестве имен параметров использовать индексы элементов массива, например, [0], [1], [2] и т.д.
- использовать одно и то же имя параметров, соответствующее имени параметра-массива в действии контроллера
Добавим в контроллер новое действие:
[HttpGet("array")] public int Get([FromQuery] int[] ints) { return ints.Max(); }
Теперь можно запустить приложение и выполнить либо такой запрос:
https://localhost:7098/api/Values/array?[0]=1&[1]=2&[2]=3&[3]=4
, либо такой https://localhost:7098/api/Values/array?ints=1&ints=2&ints=3&ints=4
в итоге, в действие контроллера будет передан массив целых чисел, состоящий из четырех элементов. В результате выполнения действия мы получим результат 4 (максимальное значение в массиве)
Передача массива объектов
Для передачи массива объектов необходимо совместить всё вышесказанное. То есть имя параметра должно содержать как индекс объекта в массиве, так и свойство объекта. Например, добавим в контроллер следующее действие:
public User[] Get([FromQuery] User[] users) { return users; }
Теперь, чтобы передать в действие контроллера массив из двух объектов User
мы должны выполнить следующий запрос (для удобства чтения каждый объект User
в запросе начинается с новой строки):
https://localhost:7098/api/Values/class-array? users[0].Id=1&users[0].Name=Bob&users[0].Email=bob@mail.com&users[0].Password=1234567& users[1].Id=2&users[1].Name=Sam&users[1].Email=sam@mail.com&users[1].Password=1234567
в результате, в качестве параметра действие контроллера получит массив состоящий из двух объектов и в браузере мы увидим следующий результат:
[ { "id": 1, "name": "Bob", "email": "bob@mail.com", "password": "1234567" }, { "id": 2, "name": "Sam", "email": "sam@mail.com", "password": "1234567" } ]
Передача словарей
Передача словаря в контроллер немногим сложнее передачи обычного массива — достаточно в параметре запроса использовать не индекс элемента, а значение ключа в словаре. Добавим в контроллер новое действие:
[HttpGet("dictionary")] public Dictionary<string, string> Get([FromQuery] Dictionary<string, string> dict) { return dict; }
Чтобы передать в действие контроллера словарь, выполним следующий запрос: localhost:7098/api/Values/dictionary?dict[fruit]=apple&dict[number]=one
В результате, в браузере увидим:
{ "fruit": "apple", "number": "one" }
Передача перечислений
Перечисление (enum
) — это пользовательский тип данных, представляющий собой набор именованных целочисленных констант. В ASP.NET Core мы можем передавать значение перечисления в контроллер двумя способами — используя имя константы в перечислении или её значение. Добавим в наше приложение следующее перечисление:
public enum PaymentType { CreditCard = 1, DebitCard = 2 }
теперь определим в контроллере следующее действие:
[HttpGet("enum")] public PaymentType Get(PaymentType type) { return type; }
Запустим приложение и выполним запрос вида localhost:7098/api/Values/enum?type=1
или localhost:7098/api/Values/enum?type=creditcard
. В обоих случаях ответ сервера будет содержать значение константы, т.е. 1
. При этом, если мы зададим в параметре запроса несуществующее значение константы, например, localhost:7098/api/Values/enum?type=10
, то сервер вернет ошибку:
{ "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", "title": "One or more validation errors occurred.", "status": 400, "errors": { "type": [ "The value '10' is invalid." ] }, "traceId": "00-7501933ea4b0a0fab1830f816453cfab-3940a90e248941e1-00" }
При работе с перечислениями в API не всегда удобно, чтобы сервер возвращал нам значение константы. Более удобным для чтения, случае работы с перечислениями, является использование имен констант. Например, в нашем случае, было бы удобно, если бы сервер вместо значение 1
вернул имя — CreditCard
. Чтобы использовать имена констант, нам необходимо настроить параметры сериализации в JSON, используемые контроллерами. Для этого необходимо открыть файл Program.cs и добавить следующую строку:
builder.Services.AddControllers() //эта строка уже есть в проекте .AddJsonOptions(opt => //настраиваем параметры сериализации в JSON { opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); });
Итого
Используя параметры запроса, мы можем передавать в контроллеры Web API как простые типы, так и сложные — такие как объекты, словари, массивы и т.д. Параметры запроса можно использовать в приложениях Web API, например, для указания серверу параметров фильтрации и сортировки данных.