Содержание
Одним из способов передачи данных в контроллер, помимо параметров маршрута, является также использование параметров запроса в URL. Параметры запроса могут активно использоваться в проекте Web API, например, для определения пользователем фильтров данных, направления сортировки, постраничного вывода результатов и т.д. ASP.NET Core позволяет передавать с помощью параметров запроса как простые типы данных, так и сложные. Этот способ передачи данных в контроллер является одним из способов, используемых системой привязки модели в ASP.NET Core.
Параметры запроса в URL указываются после символа ? и представляют собой пары «имя-значение», которые отделяются друг от друга символом &. Например, в URL
http://localhost?id=3&name=Bob
определено два параметра:
idсо значением3nameсо значением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, например, для указания серверу параметров фильтрации и сортировки данных.