Контроллеры Web API. Передача данных в контроллер через параметры запроса

Одним из способов передачи данных в контроллер, помимо параметров маршрута, является также использование параметров запроса в URL. Параметры запроса могут активно использоваться в проекте Web API, например, для определения пользователем фильтров данных, направления сортировки, постраничного вывода результатов и т.д. ASP.NET Core позволяет передавать с помощью параметров запроса как простые типы данных, так и сложные. Этот способ передачи данных в контроллер является одним из способов, используемых системой привязки модели в ASP.NET Core.

Параметры запроса в URL указываются после символа ? и представляют собой пары «имя-значение», которые отделяются друг от друга символом &. Например, в URL

http://localhost?id=3&name=Bob

определено два параметра:

  1. id со значением 3
  2. 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"
}

Передача массивов

Чтобы передать в действие контроллера массив мы можем поступить двумя способами:

  1. в качестве имен параметров использовать индексы элементов массива, например, [0], [1], [2] и т.д.
  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, например, для указания серверу параметров фильтрации и сортировки данных.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии