OData的路线例外 [英] OData route exception

查看:933
本文介绍了OData的路线例外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来这个,所以我将开始与code,之后我会解释。
问题是这样的。

  [HTTPGET,ODataRoute(({}键))]
公共SingleResult<员工> GetByKey([FromODataUri]字符串键)
{
VAR的结果= EmployeesHolder.Employees.Where(ID => id.Name ==键).AsQueryable();
返回SingleResult<员工> .Create<员工>(结果);
}
[HTTPGET,ODataRoute(({}键))]
公共SingleResult<员工>获取([FromODataUri] INT键)
{
VAR的结果= EmployeesHolder.Employees.Where(ID => id.Id ==键).AsQueryable();
返回SingleResult<员工> .Create<员工>(结果);
}

我有那些2行动,但对于一个我想通过一个字符串,并为其他按号码查找(虽然这不是问题)。如果我这样离开它,它会工作的(INT)案件,但字符串.... ODATA /员工('someName')我将获得:HTTP 404(和它的正常的),但如果我尝试更具体与需要一个字符串方法

code在webApiConfig。

  ODataModelBuilder建设者=新ODataConventionModelBuilder();
builder.EntitySet<员工>(员工);
builder.Function(\"GetByKeyFromConfig\").Returns<SingleResult<Employee>>().Parameter<string>(\"Key\");

code在控制器

  [ODataRoute preFIX(员工)]
公共类FooController的:ODataController
{     [HTTPGET,ODataRoute(GetByKeyFromConfig(键为{}键))]
            公共SingleResult&LT;员工&GT; GetByKey([FromODataUri]字符串键)
            {...}
}

我得到一个expcetion


  

{的复合型
  System.Web.Http.SingleResult`1 [OData_Path.Employee,OData_Path,
  版本= 1.0.0.0,文化=中立,公钥=空]指
  实体类型OData_Path.Employee通过属性可查询。}


如果我改变换取WebApiConfig方法键入

<$p$p><$c$c>builder.Function(\"GetByKeyFromConfig\").Returns<Employee>().Parameter<string>(\"Key\");

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


  

{路径模板上的员工/ GetByKeyFromConfig(键为{}键)
  在控制器'富'行动'GetByKey'是不是有效的OData路径
  模板。请求URI是无效的。由于段的员工
  是指一个集合,这必须是在请求中的最后一个段
  URI或者它必须遵循由可结合的功能或动作
  它,否则所有的中间段必须引用单个
  资源。}


我已经搜查,试图得到解释,但每次我找到了答案这是行不通的。我奋力天。


从2答案采取的更新后


  

仍然有无效的OData路径模板例外


WebApiConfig code

  ODataModelBuilder建设者=新ODataConventionModelBuilder();
            builder.EntitySet&LT;员工&GT;(员工)EntityType.HasKey(P =&GT; p.Name)。            VAR employeeType = builder.EntityType&LT;员工&GT;();
                employeeType.Collection.Function(GetByKey)返回&LT;员工&GT;()参数&LT; INT&GT;(钥匙);            config.EnableUnqualifiedNameCall(unqualifiedNameCall:真);
            config.MapODataServiceRoute(
                   routeName:ODataRoute
                   路线preFIX:空,
                   型号:builder.GetEdmModel());

控制器code

  [EnableQuery,HTTPGET,ODataRoute(员工/ GetByKey(键为{}键))]
        公共SingleResult&LT;员工&GT; GetByKey([FromODataUri] INT键)
        {
            VAR单= Employees.Where(N =&GT; n.Id ==键).AsQueryable();
            返回SingleResult&LT;员工&GT; .Create&LT;员工&GT;(单);
        }

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

  builder.Namespace =NamespaceX;
[EnableQuery,HTTPGET,ODataRoute(员工/ NamespaceX.GetByKey(键为{}键))]

  [EnableQuery,HTTPGET,ODataRoute(员工/ NamespaceX.GetByKey)]


解决方案

虽然可以使用OData的功能解决您的问题,一个清洁的解决方案是使用的备用键的。由于范表示,网页API的OData提供的实施交替键可以让你请求通过名称或编号员工提供一个更简单的语法:

  GET /员工(123)
GET /员工(名称='弗雷德)

您需要将以下code添加到您的OData配置。

 使用Microsoft.OData.Edm;
使用Microsoft.OData.Edm.Library;//配置是HttpConfiguration的一个实例
config.EnableAlternateKeys(真);//建设者是ODataConventionModelBuilder的一个实例
变种edmModel = builder.GetEdmModel()作为EdmModel;
VAR employeeType = edmModel.FindDeclaredType(typeof运算(员工).FullName)为IEdmEntityType;
VAR employeeNameProp = employeeType.FindProperty(名称);edmModel.AddAlternateKeyAnnotation(employeeType,新的字典&LT;字符串,IEdmProperty&GT; {{姓名,employeeNameProp}});

请确保您之前添加备用钥匙注释的 的传递模型来 config.MapODataServiceRoute

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

  [HTTPGET]
[ODataRoute(员工(名称= {}名))]
公共IHttpActionResult GetEmployeeByName([FromODataUri]字符串名称)
{
    VAR的结果= EmployeesHolder.Employees.FirstOrDefault(E =&GT; e.Name ==名);    如果(结果== NULL)
    {
        返回this.NotFound();
    }    返回this.Ok(结果);
}

I am new to this so i will start with the code and after that i will explain. The problem is this

[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);
}

I have those 2 actions but for one i want to search by a string and for the other by number (although this is not the problem). If i leave it this way it will work for the (int) case but for the string "....odata/Employees('someName')" i will get a : HTTP 404 (and it's normal) but if i try to be more specific with the method which takes a string

Code in webApiConfig.

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

Code in Controller

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

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

i get an expcetion

{"The complex type 'System.Web.Http.SingleResult`1[[OData_Path.Employee, OData_Path, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' refers to the entity type 'OData_Path.Employee' through the property 'Queryable'."}

If i change the return type in for the method in WebApiConfig

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

I get this which i have no idea why.

{"The path template 'Employees/GetByKeyFromConfig(Key={key})' on the action 'GetByKey' in controller 'Foo' is not a valid OData path template. The request URI is not valid. Since the segment 'Employees' refers to a collection, this must be the last segment in the request URI or it must be followed by an function or action that can be bound to it otherwise all intermediate segments must refer to a single resource."}

I have searched and tried to get explanation , but each time i found an answer it does not work. i am struggling for days.


After the updates taken from the 2 answers

still have the Invalid OData path template exception

WebApiConfig Code

 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());

Controller Code

  [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);
        }

I've also tried using a specific Namespace

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

And

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

解决方案

While you can solve your problem with OData functions, a cleaner solution would be to use alternate keys. As Fan indicated, Web API OData provides an implementation of alternate keys that will allow you to request Employees by name or number with a more straightforward syntax:

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

You will need to add the following code to your OData configuration.

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 } });

Make sure you add the alternate key annotations before you pass the model to config.MapODataServiceRoute.

In your controller, add a method to retrieve Employees by name (very similar to the GetByKey method in your question).

[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);
}

这篇关于OData的路线例外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆