Как вызвать маршрут MVC с поддержкой OData с помощью `DataServiceContext` из Microsoft.OData.Client? - PullRequest
0 голосов
/ 05 октября 2018

В моем .Net Core API есть простой маршрут, который вручную обрабатывает экземпляр ODataQuerySettings.Я с трудом пытаюсь вызвать этот API, используя класс DataServiceContext из клиентского пакета OData.Можно ли даже использовать DataServiceContext с простым маршрутизацией MVC с поддержкой OData?Или мне нужно будет предоставить данные другим способом, чтобы соответствовать более строгим стандартам OData?


Пример API

[AllowAnonymous]
[HttpGet("Products")]
public ActionResult<PageResult<IEnumerable<Product>>> GetData(
    ODataQueryOptions<Product> oDataQueryOptions)
{
    IEnumerable<Product> data = ProductService.GetData();

    IQueryable results = data
        .AsQueryable()
        .Skip(oDataQueryOptions.Skip?.Value ?? 0)
        .Take(oDataQueryOptions.Top?.Value ?? 3);

    return new OkObjectResult(
        new PageResult<object>(
            results.Cast<object>(),
            Request.GetNextPageLink(3),
            data.Length));
}

При получении результатов с помощью этого API я получаюожидаемые значения:

  • URL: localhost/api/Products?$skip=1
  • Результаты:
{
    "items": [{
            "id": 2,
            "text": "Second"
        }, {
            "id": 3,
            "text": "Third"
        }, {
            "id": 4,
            "text": "Fourth"
        }
    ],
    "nextPageLink": "http://localhost/api/products?$skip=4",
    "count":9
}

Потребительское приложение

Затем я приступил к созданиюпример клиентского приложения, использующего пакет Microsoft.OData.Client NuGet (точнее, v7.5.1).

Вот как выглядит простой клиент:

class Product
{
    public int Id { get; set; }
    public string Text { get; set; }
}

class Program
{
    static void Main()
    {
        var context = new DataServiceContext(new Uri("http://localhost/api"));

        var results = context
            .CreateQuery<Product>("products")
            .Skip(1)
            .ToList();
    }
}

При вызове ToList для извлечения/ материализуя результаты, я получаю следующее исключение:

System.InvalidOperationException: Ответная полезная нагрузка не является допустимой полезной нагрузкой ответа.Убедитесь, что элемент верхнего уровня является допустимым элементом Atom или JSON или принадлежит пространству имен 'http://docs.oasis -open.org / odata / ns / data '.

Похоже, это связано с тем, что я не возвращаю «стандартный ODATA» ответ, а вместо этого сырой json.

Затем я попытался использовать формат Json на DataServiceContext, как это, но этоне помогло:

var context = new DataServiceContext(new System.Uri("http://localhost/api"));
context.Format.UseJson(CreateEdmModel())       

...

private static IEdmModel CreateEdmModel()
{
    var model = new EdmModel();
    model.AddEntityType(typeof(Product).Namespace, nameof(Product));

    return model;
}

Как я могу правильно получить результаты из API, используя DataServiceContext из пользовательского приложения?Я вижу 2 варианта, но мне нужна помощь с обоими:

  1. Изменить потребителя, чтобы он работал с необработанным выводом Json

Это должно быть выполнимо, но теперь мне интересно, нужна ли мне дополнительная логика в клиенте (например, построение модели EDM), а также потеря некоторой функциональности, например, невозможность использования методов .GetAllPages, которые автоматическиперебирать страницы в службе OData и объединять их.

Измените вывод самого API, чтобы он выдавал «ODATA-совместимый» Json

Похоже, это приведет к наименьшему объему работы у потребителей.Но как мне это сделать, сохраняя ручную подкачку на месте (то есть я не могу использовать стандартные [EnableQuery] с IQueryable возвращаемыми значениями на чисто автоматическом маршруте, потому что мне нужно передать свойства OData в наш слой Dapper: ORM отсутствуетна месте здесь).Я знаю, что есть специальные схемы Json для OData, такие как «application / json; odata.metadata = минимальный», которые отличаются от того, что я сейчас выводю.

В прошлом я пользовался службами данных WCF и неНе помню, чтобы у меня была такая проблема: в то время я смог подключить DataServiceContext к службе WCF без необходимости создавать специальные выходные форматы или даже создавать какие-либо модели Edm в клиенте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...