【问题标题】:OData: Custom Action never worksOData:自定义操作永远不会起作用
【发布时间】:2015-09-30 13:49:11
【问题描述】:

我快疯了。我尝试了很多通过网络找到的不同方法。但是似乎无法完成这项工作。这是我尝试的最后一件事。

modelBuilder.EntitySet<User>("Users").EntityType.Action("IsEmailAvailable")
.Returns<bool>()
.Parameter<string>("email");

我这样配置我的实体。

[HttpPost]
public bool IsEmailAvailable(ODataActionParameters parameters)
{
    return true;
}

这是我控制器中的操作。

当我做类似的事情时

http://localhost:11111/odata/Users

我按预期获得了实体。但是,如果我这样做了

http://localhost:11111/odata/Users/IsEmailAvailable

我得到了错误:

消息:“OData 路径无效。”,ExceptionMessage:“无效 检测到的动作。 'IsEmailAvaliable' 不是可以绑定到的操作 'Collection([App.Models.Models.User Nullable=False])'.", 异常类型:“Microsoft.Data.OData.ODataException”,StackTrace:“在 System.Web.Http.OData.Routing.DefaultODataPathHandler.ParseAtEntityCollection(IEdmModel 模型、ODataPathSegment 以前的、IEdmType 以前的EdmType、字符串 段)在 System.Web.Http.OData.Routing.DefaultODataPathHandler.ParseAtCollection(IEdmModel 模型、ODataPathSegment 以前的、IEdmType 以前的EdmType、字符串 段)在 System.Web.Http.OData.Routing.DefaultODataPathHandler.ParseNextSegment(IEdmModel 模型、ODataPathSegment 以前的、IEdmType 以前的EdmType、字符串 段)在 System.Web.Http.OData.Routing.DefaultODataPathHandler.Parse(IEdmModel 模型,字符串 odataPath)在 System.Web.Http.OData.Routing.ODataPathRouteConstraint.Match(HttpRequestMessage request, IHttpRoute route, String parameterName, IDictionary`2 values, HttpRouteDirection routeDirection)"

【问题讨论】:

  • 你能张贴你的 /$metadata 页面吗?
  • 我不知道那是什么? ://
  • 好吧,里面写了很多东西,因为我还有其他实体。我应该寻找什么?

标签: c# api routing odata


【解决方案1】:

好吧,冷静下来后,因为我疯了为什么这不起作用,我开始思考并找到问题的原因。我不知何故安装了 V1-3 和 V4 版本的 Odata。因此,当我使用构建器时,它变得很困惑。所以我取消了 V1-3 并修复了编译器错误,它工作正常。感谢 Sam Xu 的努力。

【讨论】:

    【解决方案2】:

    我在my sample project 中测试过,它应该可以工作。见我的newest commit

    WebApiConfig.cs 中,我使用与您类似的代码添加了两个操作:

    builder.EntitySet<Customer>("Customers")
        .EntityType.Collection.Action("IsEmailAvailable")
        .Returns<bool>()
        .Parameter<string>("email");
    
    builder.EntitySet<Customer>("Customers")
        .EntityType.Action("IsEmailAvailable").Returns<bool>()
        .Parameter<string>("email");
    

    在哪里

    1. 第一个绑定到实体类型的集合。
    2. 第二个绑定到实体类型。

    CustomersController中,有两种方法:

    [HttpPost]
    public bool IsEmailAvailable(ODataActionParameters parameters)
    {
        ...
    }
    
    [HttpPost]
    public IHttpActionResult IsEmailAvailable(int key, ODataActionParameters parameters)
    {
        ...
    }
    

    在哪里

    1. 绑定到实体类型集合的操作将路由到第一个方法。
    2. 绑定到实体类型的操作将路由到第二种方法。

    具体实现可以参考我的项目。

    测试

    绑定到集合

    1. 返回“真”

    请求:

    POST http://localhost:33082/odata/Customers/Extra.IsEmailAvailable
    Content-Type: application/json
    Content: 
    {"email":"saxu@microsoft.com"}
    

    回复:

    {
      "@odata.context":"http://localhost:33082/odata/$metadata#Edm.Boolean","value":true
    }
    
    1. 返回“假”

    请求:

    POST http://localhost:33082/odata/Customers/Extra.IsEmailAvailable
    Content-Type: application/json
    Content: 
    {"email":"abc@microsoft.com"}
    

    回复:

    {
      "@odata.context":"http://localhost:33082/odata/$metadata#Edm.Boolean","value":false
    }
    

    绑定到实体类型

    1. 返回NotFound(在我的实现中,我硬键必须是“3”,否则返回“NotFound (404)”

    请求:

    POST http://localhost:33082/odata/Customers(2)/Extra.IsEmailAvailable
    Content-Type: application/json
    Content: 
    {"email":"saxu@microsoft.com"}
    

    回复:

    HTTP/1.1 404 Not Found
    
    1. 返回一个字符串(在我的实现中,如果键是 3,并且电子邮件是“saxu@microsoft.com”,我很难返回一个字符串)

    请求:

    POST http://localhost:33082/odata/Customers(3)/Extra.IsEmailAvailable
    Content-Type: application/json
    Content: 
    {"email":"saxu@microsoft.com"}
    

    回复:

    {
      "@odata.context":"http://localhost:33082/odata/$metadata#Edm.String","value":"Your input email is :saxu@microsoft.com"
    }
    
    1. 返回假。类似,省略。

    此外,您还可以参考以下几种材料:

    1. http://blogs.msdn.com/b/odatateam/archive/2014/12/08/function-amp-action-in-web-api-v2-2-for-odata-v4-0-type-scenario.aspx
    2. http://odata.github.io/WebApi/#04-07-action-parameter-support

    希望对您有所帮助。谢谢。

    【讨论】:

      【解决方案3】:

      埃格

      下面的错误信息是有意义的。它告诉“IsEmailAvaliable”可以与 Collection 一起调用。

      IsEmailAvaliable' is not an action that can bind to 'Collection([App.Models.Models.User Nullable=False])'
      

      来自您的模型构建代码:

      modelBuilder.EntitySet<User>("Users").EntityType.Action("IsEmailAvailable")
      .Returns<bool>()
      .Parameter<string>("email");
      

      您定义IsEmailAvailable 绑定到User 类型,而不是User 类型的集合。

      有两种方法可以让它工作:

      1. 保持模型构建代码不变,但你应该这样称呼它:

        http://localhost:11111/odata/Users(key)/Namespace.IsEmailAvailable

      2. 修改模型构建代码为:

        modelBuilder.EntitySet("Users").EntityType.Collection.Action("IsEmailAvailable") .返回() .Parameter("email");

      注意:我在调用 Action 之前添加了 Collection。然后你可以这样称呼它:

      http://localhost:11111/odata/Users/Namespace.IsEmailAvailable

      注意:如果您使用的是 OData V4 相关库,Namespace 是必需的。

      【讨论】:

      • modelBuilder.EntitySet&lt;User&gt;("Users").EntityType.Collection.Action("IsEmailAvailable").Returns&lt;bool&gt;().Parameter&lt;string&gt;("email"); 我把它改成了这个。并添加了modelBuilder.Namespace = "Extra"; 行。当我打电话给localhost:11111/odata/ApiUsers/Extra.IsEmailAvailable 时,我仍然收到同样的错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多