所以我有两个函数返回一个客户,它由两个不同的参数提供。一个是客户的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:
将Controller方法更改为:
[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,似乎它不喜欢字符串?但是,返回值不会反序列化并像往常一样显示。此外,如果我在方法声明中保留[EnableQuery]行,则调用将崩溃,说它不知道如何反序列化,因为它不绑定到Customer的实体集我猜。
然而,尝试这种方式会导致原始错误消息,即无法找到资源:
builder.EntityType<CustomerDTO>().Collection.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");
答案 0 :(得分:1)
您必须在约定模型中声明自定义odata函数:
FunctionConfiguration customerByCNOFunction = builder.Function("CustomerByCNO");
customerByCNOFunction.Returns<CustomerDTO>();
customerByCNOFunction.Parameter<string>("key");
更新:
我的第一个答案是声明一个返回odata中不可查询的类型的函数。 要启用查询,该函数需要从实体集返回odata实体:
builder.Function("CustomerByNo").ReturnsFromEntitySet<CustomerDTO>("Customer").Parameter<int>("No")