我是新手,所以我将从代码开始,之后我会解释。 问题是这个
[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")]
答案 0 :(得分:1)
关于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 :(得分:0)
您粘贴的代码有两个问题, 1.您尝试将函数绑定到Employees集合,模型构建不正确。 应该是这样的 var employeeType = builder.EntityType(); employeeType .Collection.Function(“GetByKeyFromConfig”)。返回()。参数(“Key”); 您可以参考链接https://github.com/OData/ODataSamples/tree/master/WebApi/v4/ODataFunctionSample中的示例来了解绑定函数的不同方法。
如果这不能解决您的问题,请告诉我。
答案 2 :(得分:0)
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);
}