用于删除 m:m 个实体之间关系的 OData 属性路由

OData attribute routing for deleting relationship between m:m entities

该场景是一个使用 OData v4 的应用程序,服务器端 API 基于使用 ODataLib 的 Entity Framework 模型,客户端使用 [=44= 的 OData 客户端代码生成器扩展]

我无法让 OData 属性路由用于删除 m:m 关系中实体的关系,客户端为此生成 DELETE 请求,格式为:

http://developer4:8080/odata/tblTestRestaurant(241)/tblTestDishes/$ref?$id=http://developer4:8080/odata/tblTestDish(1)

用于创建 link 的 POST 的属性路由工作正常 - 相关的实体标识符在主体中编码,并且以下控制器操作方法声明有效(控制器本身具有 [ODataRoutePrefix("tblTestRestaurant")]):

    [ODataRoute("({pRestaurantID})/tblTestDishes/$ref")]
    [HttpPost]
    [EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
    public async Task<IHttpActionResult> PostAttachtblTestDishes([FromODataUri] int pRestaurantID,
        [FromBody] Uri uri) { ... }

但是我无法为 DELETE 得到类似的东西,其中相关实体的 ID 是使用 URL.

中的 $ref?id=... 语法指定的

我已经尝试使用 ODataRoute 属性执行以下操作:

    [ODataRoute("({pRestaurantID})/tblTestDishes/$ref")]
    [HttpDelete]
    public async Task<IHttpActionResult> TestRemoveRef1([FromODataUri] int pRestaurantID,
        [FromODataUri] Uri relatedUri)
    {
        throw new NotImplementedException();
    }
    [ODataRoute("({pRestaurantID})/tblTestDishes/$ref")]
    [HttpDelete]
    public async Task<IHttpActionResult> TestRemoveRef2([FromODataUri] int pRestaurantID,
        [FromODataUri] string relatedUri)
    {
        throw new NotImplementedException();
    }
    [ODataRoute("({pRestaurantID})/tblTestDishes/$ref?$id={pRelated}")]
    [HttpDelete]
    public async Task<IHttpActionResult> TestRemoveRef3([FromODataUri] int pRestaurantID,
        [FromODataUri] string pRelated)
    {
        throw new NotImplementedException();
    }
    [ODataRoute("({pRestaurantID})/tblTestDishes/$ref?$id={pRelated}")]
    [HttpDelete]
    public async Task<IHttpActionResult> TestRemoveRef4([FromODataUri] int pRestaurantID,
        [FromODataUri] Uri pRelated)
    {
        throw new NotImplementedException();
    }

但是上述控制器操作中的 none 被命中以响应对 http://developer4:8080/odata/tblTestRestaurant(241)/tblTestDishes/$ref?$id=http://developer4:8080/odata/tblTestDish(1) 的 DELETE 请求。

我让它工作的唯一方法是不使用属性路由,而是依赖 OData 路由约定,即

    [HttpDelete]
    public async Task<IHttpActionResult> DeleteRef([FromODataUri] int key,
        [FromODataUri] string relatedKey, string navigationProperty)
    {
        throw new NotImplementedException();
    }

此方法依赖于测试字符串 navigationProperty 来确定要修改实体上的哪个集合导航 属性 - 相反,我更愿意使用属性路由,并在我的控制器中为每个集合使用单独的操作方法导航 属性.

我特别使用了很多教程和文档https://damienbod.wordpress.com/2014/06/10/getting-started-with-web-api-and-odata-v4/

我也经历了一些 OData WebApi 测试用例,特别是 this one 它混合使用了属性路由和 OData 路由约定 - 但不包含用于删除属性路由的示例 link秒。

所以我的问题是 - 我应该使用什么 ODataRoute 属性语法和方法参数,假设 ODataRoute 属性确实支持 URL 中的这个 ...$ref?id=... 语法删除;如果没有,那么还有哪些替代方案?

Web API OData 解析 $Id 中的 Uri 以创建附加到原始路径段的关键段。因此,如果您按如下方式更改模板,它应该可以工作:

[ODataRoute("({pRestaurantID})/tblTestDishes({pRelated})/$ref")]
[HttpDelete]
public async Task<IHttpActionResult> TestRemoveRef([FromODataUri] int pRestaurantID, [FromODataUri] int pRelated)
{
        ...
}

你可以参考我的示例工程here。希望它能帮助你。谢谢