OData 路由异常
本文关键字:异常 路由 OData | 更新日期: 2023-09-27 18:37:12
我是新手,所以我将从代码开始,然后我将解释。问题是这个
[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);
}
我有这两个操作,但对于一个我想按字符串搜索,另一个按数字搜索(尽管这不是问题)。如果我以这种方式离开它,它将适用于 (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)
{ ... }
}
我得到了一个实验
{"复杂类型 'System.Web.Http.SingleResult'1[[OData_Path.Employee, OData_Path, 版本=1.0.0.0,区域性=中性,公钥令牌=空]]' 指 实体类型"OData_Path.Employee"通过属性"可查询"。
如果我在 WebApiConfig 中更改该方法的返回类型
builder.Function("GetByKeyFromConfig").Returns<Employee>().Parameter<string>("Key");
我明白这个我不知道为什么。
{"路径模板'Employees/GetByKeyFromConfig(Key={key})' 控制器"Foo"中的操作"GetByKey"不是有效的 OData 路径 模板。请求 URI 无效。由于"员工"细分市场 引用集合,这必须是请求中的最后一个段 URI 或它后面必须跟有可以绑定的函数或操作 否则所有中间段都必须引用单个 资源。
我已经搜索并试图得到解释,但每次我找到答案都不起作用。 我挣扎了好几天。
从 2 个答案中获取更新后
仍有无效的 OData 路径模板例外
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());
控制器代码
[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")]
虽然您可以使用 OData 函数解决问题,但更干净的解决方案是使用备用键。正如 Fan 所指出的,Web API OData 提供了备用键的实现,允许您使用更直接的语法按姓名或编号请求员工:
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);
}
这个关于 OData/Webapi 的函数支持的文档能帮助你吗? http://odata.github.io/WebApi/#04-06-function-parameter-support 您的第二种方法存在一些问题。
-
你被调用 Employees/GetByKeyFromConfig(Key={key}),所以你应该声明这样的函数:
builder.EntityType<Employee>().Collection.Function("GetByKeyFromConfig")
-
你应该使用命名空间调用,比如 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应该可以工作。
您粘贴的代码有两个问题,1.您尝试将函数绑定到员工集合,模型构建不正确。它应该是这样的 var employeeType = builder。实体类型();员工类型 .Collection.Function("GetByKeyFromConfig").返回()。参数("键");您可以参考链接 https://github.com/OData/ODataSamples/tree/master/WebApi/v4/ODataFunctionSample 中的示例,了解绑定函数的不同方法。
- 在 ODataRoute 中,我们要么需要使用命名空间指定函数,要么在注册方法"config.EnableUnqualifiedNameCall(unqualifiedNameCall: true);".请参阅链接 http://odata.github.io/WebApi/#03-03-attrribute-routing 并搜索不合格。
如果这不能解决您的问题,请告诉我。