【问题标题】:OData route exceptionOData 路由异常
【发布时间】:2016-06-17 07:58:43
【问题描述】:

我是新手,所以我将从代码开始,然后我会解释。 问题是这样的

[HttpGet, ODataRoute("({key})")]
public SingleResult<Employee> GetByKey([FromODataUri] string key)
{
var result = EmployeesHolder.Employees.Where(id => id.Name == key).AsQueryable();
return SingleResult<Employee>.Create<Employee>(result);
}


[HttpGet, ODataRoute("({key})")]
public SingleResult<Employee> Get([FromODataUri] int key)
{
var result = EmployeesHolder.Employees.Where(id => id.Id == key).AsQueryable();
return SingleResult<Employee>.Create<Employee>(result);
}

我有这 2 个操作,但对于一个我想按字符串搜索,另一个按数字搜索(尽管这不是问题)。如果我以这种方式离开它,它将适用于 (int) 情况,但对于字符串“....odata/Employees('someName')”,我将得到一个:HTTP 404(这是正常的)但如果我尝试使用字符串的方法更具体

webApiConfig 中的代码。

ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Employee>("Employees");
builder.Function("GetByKeyFromConfig").Returns<SingleResult<Employee>>().Parameter<string>("Key");

控制器中的代码

[ODataRoutePrefix("Employees")]
public class FooController : ODataController 
{

     [HttpGet, ODataRoute("GetByKeyFromConfig(Key={key})")]
            public SingleResult<Employee> GetByKey([FromODataUri] string key)
            { ... } 
}

我得到一个expcetion

{"复杂类型 'System.Web.Http.SingleResult`1[[OData_Path.Employee, OData_Path, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' 指的是 实体类型 'OData_Path.Employee' 通过属性 'Queryable'。"}

如果我在 WebApiConfig 中更改方法的返回类型

builder.Function("GetByKeyFromConfig").Returns<Employee>().Parameter<string>("Key");

我得到了这个,我不知道为什么。

{"路径模板'Employees/GetByKeyFromConfig(Key={key})' 控制器“Foo”中的操作“GetByKey”不是有效的 OData 路径 模板。请求 URI 无效。由于部分“员工” 引用一个集合,这必须是请求中的最后一个段 URI 或者后面必须跟一个可以绑定的函数或动作 否则所有中间段必须引用一个 资源。”}

我已经搜索并试图得到解释,但每次我找到答案都不起作用。我挣扎了好几天。


从2个答案中获取更新后

仍有无效的 OData 路径模板异常

WebApiConfig 代码

 ODataModelBuilder builder = new ODataConventionModelBuilder();
            builder.EntitySet<Employee>("Employees").EntityType.HasKey(p => p.Name);

            var employeeType = builder.EntityType<Employee>();
                employeeType.Collection.Function("GetByKey").Returns<Employee>().Parameter<int>("Key");



            config.EnableUnqualifiedNameCall(unqualifiedNameCall: true);
            config.MapODataServiceRoute(
                   routeName: "ODataRoute",
                   routePrefix: null,
                   model: builder.GetEdmModel());

控制器代码

  [EnableQuery, HttpGet, ODataRoute("Employees/GetByKey(Key={Key})")]
        public SingleResult<Employee> GetByKey([FromODataUri] int Key)
        {
            var single = Employees.Where(n => n.Id == Key).AsQueryable();
            return SingleResult<Employee>.Create<Employee>(single);
        }

我也尝试过使用特定的命名空间

builder.Namespace = "NamespaceX";
[EnableQuery, HttpGet, ODataRoute("Employees/NamespaceX.GetByKey(Key={Key})")]

[EnableQuery, HttpGet, ODataRoute("Employees/NamespaceX.GetByKey")]

【问题讨论】:

  • 如果下面的任何答案解决了您的问题,请点击复选标记考虑accepting it。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己提供了一些声誉。没有义务这样做。

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


【解决方案1】:

这个关于 OData/Webapi 功能支持的文档可以帮助你吗? http://odata.github.io/WebApi/#04-06-function-parameter-support 你的第二种方法有问题。

  1. 你是用 Employees/GetByKeyFromConfig(Key={key}) 调用的,所以你应该像这样声明函数:

    builder.EntityType<Employee>().Collection.Function("GetByKeyFromConfig") 
    
  2. 您应该使用命名空间调用,例如Employees/yournamespace.GetByKeyFromConfig

第一个场景可以使用这个功能吗? http://odata.github.io/WebApi/#04-17-Alternate-Key

希望对你有帮助,谢谢。

Update: 函数声明是现在,因为你的ODataRoute错误而显示的错误信息,删除你的ODataRoute,那个函数可以被称为Employees/Default.GetByKey(1),WebAPI/OData默认可以路由到这个函数。

或者给ODataRoute添加命名空间,默认是Default,改builder.Namespace是不对的,要改函数的命名空间:

var func = employeeType.Collection.Function("GetByKey").Returns<Employee>().Parameter<int>("Key");
func.Namespace = "NamespaceX";

然后像 [EnableQuery, HttpGet, ODataRoute("Employees/NamespaceX.GetByKey(Key={Key})")] 这样的 ODataRoute 应该可以工作。

【讨论】:

    【解决方案2】:

    您粘贴的代码有两个问题, 1.您尝试将函数绑定到Employees集合,模型构建不正确。 它应该是这样的 var employeeType = builder.EntityType(); employeeType .Collection.Function("GetByKeyFromConfig").Returns().Parameter("Key"); 您可以参考链接https://github.com/OData/ODataSamples/tree/master/WebApi/v4/ODataFunctionSample中的示例了解不同的函数绑定方式。

    1. 在 ODataRoute 中,我们要么需要指定具有命名空间的函数,要么需要在注册方法“config.EnableUnqualifiedNameCall(unqualifiedNameCall: true);”中通过此配置启用非限定函数调用。 参考链接http://odata.github.io/WebApi/#03-03-attrribute-routing,搜索不合格。

    如果这不能解决您的问题,请告诉我。

    【讨论】:

      【解决方案3】:

      虽然您可以使用 OData 函数解决问题,但更简洁的解决方案是使用 alternate keys。作为Fan indicated,Web API OData 提供了一个implementation of alternate keys,允许您使用更直接的语法按姓名或编号请求员工:

      GET /Employees(123) 
      GET /Employees(Name='Fred')
      

      您需要将以下代码添加到您的 OData 配置中。

      using Microsoft.OData.Edm;
      using Microsoft.OData.Edm.Library;
      
      // config is an instance of HttpConfiguration
      config.EnableAlternateKeys(true);
      
      // builder is an instance of ODataConventionModelBuilder
      var edmModel = builder.GetEdmModel() as EdmModel;
      var employeeType = edmModel.FindDeclaredType(typeof(Employee).FullName) as IEdmEntityType;
      var employeeNameProp = employeeType.FindProperty("Name");
      
      edmModel.AddAlternateKeyAnnotation(employeeType, new Dictionary<string, IEdmProperty> { { "Name", employeeNameProp } });
      

      确保在将模型传递给config.MapODataServiceRoute 之前添加备用键注释

      在您的控制器中,添加一个按名称检索员工的方法(非常类似于您问题中的 GetByKey 方法)。

      [HttpGet]
      [ODataRoute("Employees(Name={name})")]
      public IHttpActionResult GetEmployeeByName([FromODataUri] string name)
      {
          var result = EmployeesHolder.Employees.FirstOrDefault(e => e.Name == name);
      
          if (result == null)
          {
              return this.NotFound();
          }
      
          return this.Ok(result);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-08
        • 1970-01-01
        • 2014-03-01
        相关资源
        最近更新 更多