Как получить несколько параметров объекта в GET Action в ASP.NET Core 2.2 REST API? - PullRequest
0 голосов
/ 14 января 2019

У меня есть общий сценарий, когда я хочу перечислить некоторые элементы в приложении веб-клиента (я использую vue.js и axios), которые выбираются из серверной части (приложение REST asp.net core 2.2). Клиент должен передать некоторые параметры фильтрации и нумерации страниц бэкэнду, чтобы получить элементы, которые он должен отобразить на текущей странице.

Однако у меня проблема в том, что действие GET, определенное на контроллере сервера, не может десериализовать параметры, переданные ему из HTTP-запроса.

Вот код бэкэнда:

// these are classes that represent parameters sent in HTTP Get request
public class Filter
{
    public bool IsActive { get; set; }
    public string Name { get; set; }
}

public class Pagination
{
    public string Page { get; set; }
    public string ItemsPerPage { get; set; }
}

Это действие в контроллере:

[HttpGet]
public IActionResult GetItems([FromQuery]Filter filter, [FromQuery]Pagination pagination)
{
    // ... get items from db with specified filter and pagination
    return Ok();
}

Вот аксиос запроса на получение от клиента:

axios.get('https://localhost:44336/api/items', {
  params: {
    filter: {
      isLive: true,
      name: 'test123'
    },
    pagination: {
      page: 5,
      itemsPerPage: 10
    }
  }
})

Обратите внимание, что я использую параметры axios, чтобы указать два вложенных объекта, один фильтр и другую нумерацию страниц. Это не работает, и параметры, переданные в действие GetItems (), являются объектами со значениями по умолчанию (например, isLive = false, name = null, page = 0, itemsPerPage = 0 ...)

Есть ли способ заставить эту работу работать и иметь два отдельных объекта, переданных и должным образом десериализованных действием GetItems ()?

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Для вашего текущего запроса от axios запрос будет https://localhost:44320/api/SampleData/GetItems?filter={"isActive":true,"name":"test123"}&pagination={"page":5,"itemsPerPage":10}, который не сможет быть привязан по умолчанию связывателем моделей.

Вы можете реализовать свою собственную модель связующего, как

public class NestedModelBinder<T> : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var modelName = bindingContext.ModelName;
        var request = bindingContext.HttpContext.Request.Query.TryGetValue(modelName, out var modelValue);
        if (modelValue.Count ==0)
        {
            return Task.CompletedTask;
        }
        try
        {
            var model = JsonConvert.DeserializeObject<T>(modelValue);
            if (model == null)
            {
                return Task.CompletedTask;
            }
            bindingContext.Result = ModelBindingResult.Success(model);
            return Task.CompletedTask;
        }
        catch (Exception ex)
        {
            return Task.CompletedTask;
        }
    }
}

Использование

[HttpGet("[action]")]
public IActionResult GetItems([ModelBinder(typeof(NestedModelBinder<Filter>))]Filter filter, [ModelBinder(typeof(NestedModelBinder<Pagination>))]Pagination pagination)
{
    var request = HttpContext.Request.Query;
    // ... get items from db with specified filter and pagination
    return Ok();
}

Еще одно замечание: оставьте Filter.IsActive на стороне сервера и filter.isLive на стороне клиента.

0 голосов
/ 14 января 2019

Просмотр модели:

public class ViewModel
{
    public Filter Filter{ get; set; }
    public Pagination Pagination  { get; set; }
}

Метод действия:

public IActionResult GetItems([FromQuery] ViewModel model)

Клиент:

params: {
    filter.isActive: true,
    filter.name: 'test123',
    pagination.page: 5,
    pagination.itemsPerPage: 10,
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...