【问题标题】:OData controller method with multiple parameters具有多个参数的 OData 控制器方法
【发布时间】:2020-09-06 01:05:20
【问题描述】:

我需要用这个分配创建一个 OData 控制器。

http://xxxxxx/odata/mock/Itens(NumContrato='1234',IdItem='10')/Pedidos

ItensController

public class ItensController : ODataController
{
    [HttpPost]
    [ODataRoute("(NumContrato={NumContrato},IdItem={IdItem})/Pedidos")]
    public IQueryable<Pedido> Pedidos([FromODataUri] string NumContrato, [FromODataUri] string IdItem)
    {
        ... do something
    }
}

WebApiConfig.cs

...
config.Routes.MapODataServiceRoute(
        "ODataRoute",
        "odata/mock",
        model: GetModel(),
        new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
...

public static IEdmModel GetModel()
{
    ODataModelBuilder builder = new ODataConventionModelBuilder();
    ...
    builder.EntitySet<Dominio.ODataSapFake.Item>("Itens");
    builder.EntitySet<Dominio.ODataSapFake.LinhaDeServico>("LinhasDeServicos");
    builder.EntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");
    var a = builder.Entity<Dominio.ODataSapFake.Item>().Collection.Action("Pedidos");
    a.Parameter<string>("NumContrato");
    a.Parameter<string>("IdItem");
    a.ReturnsCollectionFromEntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");
    ...
    return builder.GetEdmModel();
}

调用服务时出错

<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <m:code/>
    <m:message xml:lang="en-US">
        No HTTP resource was found that matches the request URI 'http://localhost:4492/odata/mock/Itens(NumContrato='100',IdItem='00040')/Pedidos'.
    </m:message>
    <m:innererror>
        <m:message>No routing convention was found to select an action for the OData path with template '~/entityset/key/navigation'.
        </m:message>
        <m:type/>
        <m:stacktrace/>
    </m:innererror>
</m:error>

【问题讨论】:

  • 您还应该发布Item 的结构,这样可以更快地解决问题:)
  • 我同意,但它是一个巨大的类,不知道自定义路由。顺便说一句,这就是我解决问题的方法。 :)
  • 酷,我看到你现在已经添加了那个标签,你应该发布你的解决方案作为答案,你是使用属性表示法还是CustomRouteConvention。文档在自定义路由docs.microsoft.com/en-us/odata/webapi/routing-abstract 上非常好
  • 当你的类很大时,你只需要包含主要元素,比如类名、关键属性和你在问题中引用的任何其他属性,比如过滤器或在这种情况下Pedidos。只需添加一个省略号 ... 来表示省略的代码行。听起来我很迂腐,但经常通过写一个好问题的过程来帮助你解决问题,你仍然可以发布它,你可以发布你的解决方案,你仍然会发表评论。
  • 当然不是!我需要多参与,多写……练习!

标签: c# api odata custom-routing


【解决方案1】:

要么你的 URL 不正确,要么你的配置不正确,让我们探索这两种可能性:

假设配置正确,你声明了名为PedidosAction有2个参数,它绑定到collection,没有绑定到一个项目。 . 符合你定义的网址其实是:

~/Itens/Pedidos(NumContrato='1234',IdItem='10')

假设 URL 正确,那么您需要将端点配置为 Item 绑定 Action 并且我们还假设 Itens 记录已经具有键 @ 987654325@ 和 IdItem 定义:

builder.EntitySet<Dominio.ODataSapFake.LinhaDeServico>("LinhasDeServicos");
builder.EntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");
var itens = builder.EntitySet<Dominio.ODataSapFake.Item>("Itens");
// Key should be defined by attribute notation, but we can redefine it here for clarity
itens.EntityType.HasKey(x => x.NumContrato);
itens.EntityType.HasKey(x => x.IdItem);
// declare the Action bound to an Item
itens.Item.Action("Pedidos")
    .ReturnsCollectionFromEntitySet<Dominio.ODataSapFake.Pedido>("Pedidos");

更新 1 - 获取支持:

Action 支持 HTTP Post,OP 已经用它装饰了方法,但是如果您打算支持 HTTP GET,那么您必须将端点配置为 Function。语法还是一样的。

  • 不要忘记删除[HttpPost]属性,考虑用[EnableQuery][HttpGet]替换它

更新 2 - 使用复合键进行项目导航

如果Item 数据记录有一个名为Pedidos 的导航属性,并且您的意图是支持沿此属性路径向下的标准项目导航,那么您不需要在配置中包含此信息。

  • 删除[HttpPost],这是一个GET请求。
  • 删除[ODataRoute] 属性,默认路由应该可以工作
  • 确保使用关键属性的名称,使用与配置中声明的相同的大小写和顺序。
    • 如果您使用自动配置,则顺序将与您的数据模型中的 Key 属性列规范相匹配。
  • 对于 OData v3,您可能需要遵循以下建议:Odata v3 Web Api navigation with composite key

【讨论】:

  • 谢谢兄弟! URL 是正确的,所以... items.Item.Action(...) 没有找到。针对 items.EntityType.Action(...) 进行了更改,但发生了同样的错误。
  • ...Item 有钥匙。
  • 不知道重要不重要,不过Pedidos也是一个Item属性。
  • 是的,这可能会引起一些麻烦,但是操作是 POST 端点,所以请确保您 POST 对它,如果您需要支持 GET 我需要更改我的答案,请告诉我: )
  • 嗯......再一次,你是对的!我的服务需要返回结果,所以... GET 是最合适的。 ACTIONS 是否需要使用 POST?请用 GET 告诉我答案。我尝试了一些功能,但在 OData V3 中它不可用。对吗?
猜你喜欢
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
相关资源
最近更新 更多