Web Api 2.2 OData V4 Function Routing (Маршрутизация функций OData V4)

У меня есть проект Web Api 2.2, работающий с OData v4. Обычная конфигурация EntitySet работает должным образом со всеми http-командами. Когда у меня возникла проблема, я пытаюсь открыть пользовательскую функцию. Я начал с попытки сделать что-то отличное от стандартных примеров, но я полностью поддержал попытки заставить работать базовую функцию примера.

Вот моя конфигурация запуска (прямо из примеров MS):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;

namespace Test.Service
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {

            // other entitysets that don't have functions

            builder.EntitySet<Product>("Products");
            builder.Namespace = "ProductService";
            builder.EntityType<Product>().Collection
                .Function("MostExpensive")
                .Returns<double>();

            config.MapODataServiceRoute(
                "odataroute"
                , "odata"
                , builder.GetEdmModel()                        
                );
        }
    }
}

А вот и мой контроллер:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;

namespace Test.Service.Controllers
{
    public class ProductsController : ODataController
    {
        private EntityContext db = new EntityContext();

        [EnableQuery]
        public IQueryable<Product> GetProducts()
        {
            return db.Products;
        }

        [HttpGet]
        public IHttpActionResult MostExpensive()
        {
            double test = 10.3;
            return Ok(test);
        }
    }
}

Обычный GET отлично работает:

http://something/odata/Products

Однако следующее всегда дает мне 404:

http://something/odata/Products/ProductService.MostExpensive()

Я пробовал много разных вещей с пространством имен и т. Д. Итак, это работает не так, как все примеры, но я не понимаю, как копнуть глубже, чтобы понять, что идет не так. Метаданные, предоставленные http://something/odata, не дают никаких подсказок. Есть ли другой способ узнать, где (и как) должна отображаться эта функция?

РЕДАКТИРОВАТЬ: вот ссылка на пример Microsoft, за которым я следую: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-actions-and-functions < / а>


person snow_FFFFFF    schedule 14.08.2014    source источник
comment
Просто любопытно, а вы пробовали: something / odata / Products / MostExhibited?   -  person Andrea Scarcella    schedule 14.08.2014
comment
Да, я пробовал любое количество различных комбинаций: например odata / Products / MostExicing, odata / Products / MostExicing (), odata / Products / Default.MostExicing () (последняя, ​​когда я явно не задавал пространство имен)   -  person snow_FFFFFF    schedule 14.08.2014
comment
Спасибо, я также заметил, что нет атрибута типа ответа [ResponseType (typeof (decimal))].   -  person Andrea Scarcella    schedule 14.08.2014
comment
Спасибо за предложение, но атрибут ResponseType, похоже, недоступен в этой версии WebApi (или мне не хватает использования ...). И во всех примерах, которые я видел, в этом нет необходимости (я добавил ссылку на приведенный выше пример MS). Странно то, что я могу добавить несвязанную функцию без проблем, я просто не могу привязать функцию к набору сущностей.   -  person snow_FFFFFF    schedule 14.08.2014


Ответы (3)


Измените элемент, как показано ниже. Это рекомендуемый способ, если в URL-адресе запроса есть точка:

 <system.webServer>
        <modules runAllManagedModulesForAllRequests="true" />
 </system.webServer>

и если

http://something/odata/Products/ProductService.MostExpensive()

запрашивается, я могу получить данные:

{
@odata.context: "http://localhost:14853/odata/$metadata#Edm.Double",
value: 3
}
person Tan Jinfu    schedule 15.08.2014
comment
В моем web.config есть очень похожая строка: ‹add name = ExtensionlessUrlHandler-Integrated-4.0 path = . verb = type = System.Web.Handlers.TransferRequestHandler preCondition = IntegratedMode, runtimeVersionv4.0 / ›- единственное отличие, которое я вижу с вашим, если атрибут path. Если я поменяю его на ваш, все будет с 500 (внутренняя ошибка сервера) - person snow_FFFFFF; 16.08.2014
comment
Подозрительно выглядят и атрибут пути, и глагол. Для глагола используйте , а для пути, если / не работает для вас, попробуйте и * / odata /. - person Tan Jinfu; 16.08.2014
comment
Извините, что мне потребовалось так много времени, чтобы принять этот ответ, но я не смог потратить время на то, чтобы попробовать его. Модули ‹runAllManagedModulesForAllRequests = true /›, похоже, решили все мои проблемы .... хотя я не уверен, почему его не было по умолчанию. Спасибо! - person snow_FFFFFF; 04.09.2014
comment
Это можно сделать без запуска всех управляемых модулей для каждого запроса (см. Ссылку). Запуск всех управляемых модулей может быть дорогостоящим и вызывать ошибки: britishdeveloper.co.uk/2010/06/ - person Bvrce; 15.06.2015

Я знаю, что этот вопрос возник не недавно, но я нашел другой ответ, который мне подходит. Если вы хотите удалить пространство имен из URL-адреса, вы можете использовать

config.EnableUnqualifiedNameCall(true);

Тогда ваш URL-адрес будет выглядеть так:

http://something/odata/Products/MostExpensive

См. http://odata.github.io/WebApi/#06-01-custom-url-parsing. Это доступно в пакете NuGet Microsoft.AspNet.OData.

person Don 01001100    schedule 02.02.2016
comment
Добро пожаловать! Эта функция недоступна в версии 5.3.0 этого пакета (это версия, используемая мной в загруженном мной образце решения), но она доступна в версии 5.7.0, поэтому я предполагаю, что ее не было все эти месяцы. назад. - person Don 01001100; 02.02.2016
comment
Я не мог заставить работать какое-либо решение на основе web.config. В любом случае это было предпочтительнее, поскольку пространство имен кажется совершенно излишним. - person Luke Puplett; 21.06.2016
comment
Этот метод расширения отсутствует в Microsoft.AspNet.OData nuget 6.1.0. Обходной путь можно найти здесь github.com/OData/WebApi/blob/OData60/OData/test/E2ETest/ - person Victor Wilson; 30.01.2018

Затем вы можете попробовать добавить деталь, не заменяя ее. Мой выглядит так, как показано ниже, и он может работать.

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  <clear/>
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="/*"
      verb="*" type="System.Web.Handlers.TransferRequestHandler"
      preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
person QianLi    schedule 18.08.2014
comment
Изменение пути с *. to / * действительно помогает в моем случае. - person VAV; 05.03.2015