两个动作的属性路由导致 "Not valid OData path template"
Attribute routing for two actions leads to a "Not valid OData path template"
所以我有两个 return 客户的功能,它们由两个不同的参数提供。一个是客户的ID,一个是他的客户编号。
我的控制器:
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Web.OData;
using System.Web.OData.Routing;
using Models;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using System.Web.OData.Extensions;
using Importing;
using Objects;
using Microsoft.OData;
namespace Controllers
{
public class CustomersController : ODataController
{
// GET: CustomerByCNO(5)
[HttpGet]
[ODataRoute("CustomerByCNO({key})")]
[EnableQuery]
public SingleResult<CustomerDTO> GetCustomerByCNO([FromODataUri]string key)
{
Import i = new Import();
var customer = i.GetCustomer(key).ProjectTo<CustomerDTO>().AsQueryable();
return SingleResult.Create(customer);
}
// GET: Customer(5)
[HttpGet]
[ODataRoute("Customer({id})")]
[EnableQuery]
public SingleResult<CustomerDTO> Get([FromODataUri]int id)
{
Import i = new Import();
var customer = i.GetCustomer(id).ProjectTo<CustomerDTO>().AsQueryable();
return SingleResult.Create(customer);
}
}
}
初始化:
using AutoMapper;
using Models;
using Objects;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using Microsoft.OData.Edm;
namespace API
{
public static class WebApiConfig
{
public static void ConfigureAPI(HttpConfiguration config)
{
config.MapODataServiceRoute(
routeName: "odata",
routePrefix: "",
model: GetEdmModel()
);
config.EnsureInitialized();
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder
{
Namespace = "Controllers",
ContainerName = "DefaultContainer"
};
builder.EntitySet<CustomerDTO>("Customer")
.EntityType.HasKey(c => c.Id)
.CollectionProperty(c => c.CustomFields);
var edmModel = builder.GetEdmModel();
return edmModel;
}
}
}
虽然第二个函数按预期工作,但第一个函数没有,并且 EnsureInitialized() 函数抛出 InvalidOperationException 说它不是有效的 OData 路径模板并且没有找到资源。我怎样才能让它工作?不太确定我在这里遗漏了什么。
更新 1:
将控制器方法更改为:
[HttpGet]
[ODataRoute("CustomerByNo(No={no})")]
public SingleResult<CustomerDTO> CustomerByNo([FromODataUri] int no)
{
Import i = new Import();
var customer = i.GetCustomer(no.ToString()).ProjectTo<CustomerDTO>().AsQueryable();
return SingleResult.Create(customer);
}
在配置中增加这一行:
builder.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");
做到了,所以我至少可以访问这些功能。我也不得不将参数更改为 int,似乎它不喜欢字符串?但是,return 值未反序列化并照常显示。另外,如果我在方法声明中保留 [EnableQuery] 行,调用将崩溃,说它不知道如何反序列化,因为我猜它没有绑定到 Customer 的实体集。
然而,以这种方式尝试会导致原始错误消息,即找不到资源:
builder.EntityType<CustomerDTO>().Collection.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");
您必须在约定模型中声明您的自定义 odata 函数:
FunctionConfiguration customerByCNOFunction = builder.Function("CustomerByCNO");
customerByCNOFunction.Returns<CustomerDTO>();
customerByCNOFunction.Parameter<string>("key");
更新:
我的第一个答案是声明一个函数,returns 是一种在 odata 中不可查询的类型。
要启用查询,该函数需要 return 来自实体集的 odata 实体:
builder.Function("CustomerByNo").ReturnsFromEntitySet<CustomerDTO>("Customer").Parameter<int>("No")
所以我有两个 return 客户的功能,它们由两个不同的参数提供。一个是客户的ID,一个是他的客户编号。
我的控制器:
using System.Linq;
using System.Net;
using System.Web.Http;
using System.Web.OData;
using System.Web.OData.Routing;
using Models;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using System.Web.OData.Extensions;
using Importing;
using Objects;
using Microsoft.OData;
namespace Controllers
{
public class CustomersController : ODataController
{
// GET: CustomerByCNO(5)
[HttpGet]
[ODataRoute("CustomerByCNO({key})")]
[EnableQuery]
public SingleResult<CustomerDTO> GetCustomerByCNO([FromODataUri]string key)
{
Import i = new Import();
var customer = i.GetCustomer(key).ProjectTo<CustomerDTO>().AsQueryable();
return SingleResult.Create(customer);
}
// GET: Customer(5)
[HttpGet]
[ODataRoute("Customer({id})")]
[EnableQuery]
public SingleResult<CustomerDTO> Get([FromODataUri]int id)
{
Import i = new Import();
var customer = i.GetCustomer(id).ProjectTo<CustomerDTO>().AsQueryable();
return SingleResult.Create(customer);
}
}
}
初始化:
using AutoMapper;
using Models;
using Objects;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using Microsoft.OData.Edm;
namespace API
{
public static class WebApiConfig
{
public static void ConfigureAPI(HttpConfiguration config)
{
config.MapODataServiceRoute(
routeName: "odata",
routePrefix: "",
model: GetEdmModel()
);
config.EnsureInitialized();
}
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder
{
Namespace = "Controllers",
ContainerName = "DefaultContainer"
};
builder.EntitySet<CustomerDTO>("Customer")
.EntityType.HasKey(c => c.Id)
.CollectionProperty(c => c.CustomFields);
var edmModel = builder.GetEdmModel();
return edmModel;
}
}
}
虽然第二个函数按预期工作,但第一个函数没有,并且 EnsureInitialized() 函数抛出 InvalidOperationException 说它不是有效的 OData 路径模板并且没有找到资源。我怎样才能让它工作?不太确定我在这里遗漏了什么。
更新 1:
将控制器方法更改为:
[HttpGet]
[ODataRoute("CustomerByNo(No={no})")]
public SingleResult<CustomerDTO> CustomerByNo([FromODataUri] int no)
{
Import i = new Import();
var customer = i.GetCustomer(no.ToString()).ProjectTo<CustomerDTO>().AsQueryable();
return SingleResult.Create(customer);
}
在配置中增加这一行:
builder.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");
做到了,所以我至少可以访问这些功能。我也不得不将参数更改为 int,似乎它不喜欢字符串?但是,return 值未反序列化并照常显示。另外,如果我在方法声明中保留 [EnableQuery] 行,调用将崩溃,说它不知道如何反序列化,因为我猜它没有绑定到 Customer 的实体集。
然而,以这种方式尝试会导致原始错误消息,即找不到资源:
builder.EntityType<CustomerDTO>().Collection.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");
您必须在约定模型中声明您的自定义 odata 函数:
FunctionConfiguration customerByCNOFunction = builder.Function("CustomerByCNO");
customerByCNOFunction.Returns<CustomerDTO>();
customerByCNOFunction.Parameter<string>("key");
更新:
我的第一个答案是声明一个函数,returns 是一种在 odata 中不可查询的类型。 要启用查询,该函数需要 return 来自实体集的 odata 实体:
builder.Function("CustomerByNo").ReturnsFromEntitySet<CustomerDTO>("Customer").Parameter<int>("No")