【问题标题】:OData Unbound function send and receive primitive collectionOData Unbound 函数发送和接收原始集合
【发布时间】:2014-10-02 05:24:27
【问题描述】:

需要一个示例,说明如何将原始类型的集合传递给未绑定的函数/或操作,以及如何返回原始类型的集合。
例如整数列表或数组。
这是一个简单的例子。

List<int> GetEvenNumbers(List<int> numbers)
{
// loop through numbers collection and return a list of the even numbers
}

以下站点讨论了使用函数/动作,但没有解释传递/接收集合。

http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/odata-actions-and-functions

https://aspnet.codeplex.com/sourcecontrol/latest#Samples/WebApi/OData/v4/

我什至在“Show Me How With Code”上发布了一条建议,但没有收到回复。
http://aspnet.uservoice.com/forums/228522-show-me-how-with-code/suggestions/6264729-odata-v4-passing-collection-as-parameter-to-unbou

这是我有的一些代码,但它似乎不起作用。

// in the controller
[HttpGet]
[ODataRoute("GetEvenNumbers(numbers={numbers})")]
public IHttpActionResult GetEvenNumbers(List<int> numbers)
{
    List<int> evenNumbers = new List<int>();
    foreach (var number in numbers)
    {
        if (number % 2 == 0)
        {
            evenNumbers.Add(number);
        }
    }
    return Ok(evenNumbers);
}

// in the WebApiConfig
var testCollectionFunction = builder.Function("GetEvenNumbers");
testCollectionFunction.CollectionParameter<int>("numbers");
testCollectionFunction.ReturnsCollection<int>();

在 WCF 中这很简单,但在 OData 中就不是那么简单了。

【问题讨论】:

    标签: c# asp.net-web-api odata


    【解决方案1】:

    据我所知,webapi odata 不允许在 Functions 参数中进行集合。但是您可以使用 Actions 作为解决方法。

    模型构建器:

            var testCollectionFunction = modelBuilder.Action("GetEvenNumbers");
            testCollectionFunction.CollectionParameter<int>("numbers");
            testCollectionFunction.ReturnsCollection<int>();
    

    控制器:

        [HttpPost]
        [ODataRoute("GetEvenNumbers")]
        public IHttpActionResult GetEvenNumbers(ODataActionParameters parameter)
        {
            IEnumerable<int> numbers = parameter["numbers"] as IEnumerable<int>;
            List<int> evenNumbers = new List<int>();
            foreach (var number in numbers)
            {
                if (number % 2 == 0)
                {
                    evenNumbers.Add(number);
                }
            }
            return Ok(evenNumbers);
        }
    

    请求:

    POST http://localhost:44221/odata/GetEvenNumbers HTTP/1.1
    Host: localhost:44221
    Connection: keep-alive
    Content-Length: 17
    
    {"numbers":[1,2]}
    

    回复:

    HTTP/1.1 200 OK
    Content-Type: application/json; odata.metadata=full
    OData-Version: 4.0
    Content-Length: 109
    
    {
      "@odata.context":"http://localhost:44221/odata/$metadata#Collection(Edm.Int32)","value":[
        2
      ]
    }
    

    【讨论】:

    • 请原谅我的无知,但我如何从浏览器 URL 调用它?我试过localhost:49771/odata/GetEvenNumbers(numbers=[1,2]) AND localhost:49771/odata/GetEvenNumbers([1,2]) AND localhost:49771/odata/GetEvenNumbers({1,2}) 但似乎都不起作用。
    • @goroth,金福也在他的request部分给出了用法。对于 Action 请求,您应该使用 Post 方法,并且 url 应该是:localhost:49771/odata/GetEvenNumbers 请求正文与 request 部分相同,但我认为您应该添加一个标头:内容类型:应用程序/json
    • 如果您不熟悉如何向 OData 服务请求,可以查看odata.org/getting-started/basic-tutorial/#operation。希望这会有所帮助
    • 这在我从浏览器中提供 URL 时工作正常,但在使用代码执行时不起作用,为什么?
    • 仅供参考,许多 OOTB OData 配置将与默认 MVC Action Route Resolvers 冲突,该解析器通过控制器方法的前缀映射允许的 Http Method。因此,经常会看到前缀为 Get 的 Action 无法正确解析。通常是 404 或 503 响应。根据经验,避免使用 Http 动词前缀命名您的方法,除非它与您的预期 Http 方法 匹配。如果您在实施此解决方案时遇到问题,请将您的操作名称更改为 EvenNumbersCalculateEvenNumbers 甚至 PostEventNumbers
    【解决方案2】:

    所以我想提供和更新这篇文章。我正在使用 Web API 2.2 使用 OData v4。我能够将参数传递给未绑定的函数。

    这是我的注册方法中的构建器代码。

    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Employee>("Employees");
    
    //other stuff here
    builder.Function("EmployeesWithParameters")
           .ReturnsCollectionFromEntitySet<Employee>("Employees")
           .CollectionParameter<string>("Ids");
    

    这是我的控制器上的实际方法调用。

        [HttpGet]
        [ODataRoute("EmployeesWithParameters(Ids={Ids})")]
        public IQueryable<Employee> EmployeesWithParameters([FromODataUri]string[] Ids)
        {
            IQueryable<Employee> result = db.Employees.Where(p => Ids.Contains(p.EmployeeId) );
    
            return result; ;
        }
    

    【讨论】:

    • 将多个 ID 传递给此函数时,您的 GET 请求是什么样的?
    • @9Rune5 很抱歉,我无法再访问此系统来生成示例。
    • 没问题Cyrus,我坚持到了最后。 :)
    【解决方案3】:

    正如 Cyrus 的回答所说,OData 函数既可以返回集合,也可以将它们作为参数。

    就我而言,我有一个名为“MostPopular”的函数,定义为:

            var mostPopFunc = svcHist.Collection.Function("MostPopular");
            mostPopFunc.Parameter<DateTime>("From");
            mostPopFunc.CollectionParameter<ServiceCodes>("ServiceCodes");
            mostPopFunc.CollectionParameter<int>("ServiceUnits");
            mostPopFunc.Parameter<string>("SearchCCL");
            mostPopFunc.Parameter<int>("ListLength").OptionalParameter = true;
            mostPopFunc.ReturnsCollection<ciExternalPartnerPopularResult.MarcIdPopularity>();
    

    由于这个函数绑定到一个实体集,我不需要提供路由映射,函数声明被缩减为:

    [HttpGet]
    public async Task<IHttpActionResult> MostPopular([FromODataUri] DateTimeOffset from, [FromODataUri] IEnumerable<ServiceCodes> serviceCodes, 
                                                     [FromODataUri] IEnumerable<int> serviceUnits,
                                                     [FromODataUri] string searchCcl, [FromODataUri] int listLength = ListLengthDefault)
    { // ...
    }
    

    int 和其他简单类型不需要[FromODataUri] 装饰,但我并不在意它们。考虑到参数的数量,这个函数有点重,但我没时间想出一个更好的接口。

    最后,要从 PostMan(或浏览器)调用它,GET 请求看起来像这样:

    {{url}}/ServiceHistories/Default.MostPopular(From=2016-10-07T12:41:59Z,ServiceCodes=['OnLoan'],ServiceUnits=[6471,6473],SearchCCL='TI+SE=Harry',ListLength=10)
    

    这迫使我修改我的 web.config 因为时间戳:

    <system.web>
      <!-- This web service accepts datetimeoffset as a parameter and requires the ":" character to be supplied as part of the URL -->
      <httpRuntime targetFramework="4.5" requestPathInvalidCharacters="&lt;,&gt;,%,&amp;,\,?" />
    </system.web>
    

    【讨论】:

      猜你喜欢
      • 2014-09-18
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2022-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多