Маршрутизация атрибутов для двух действий приводит к "Недопустимому шаблону пути OData"
Итак, у меня есть две функции, которые возвращают клиента, который получает два разных параметра. Один - это идентификатор клиента, а другой - его номер.
Мой контроллер:
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, кажется, что он не любит строки? Однако возвращаемое значение не десериализуется и отображается как обычно. Также, если я оставлю строку [EnableQuery] в объявлении метода, вызов завершится сбоем, сказав, что он не знает, как десериализовать, так как он не связан с набором сущностей Customer, как я полагаю.
Однако попытка сделать это приводит к исходному сообщению об ошибке, что ресурс не найден:
builder.EntityType<CustomerDTO>().Collection.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");
1 ответ
Вы должны объявить свои пользовательские функции odata в модели соглашения:
FunctionConfiguration customerByCNOFunction = builder.Function("CustomerByCNO");
customerByCNOFunction.Returns<CustomerDTO>();
customerByCNOFunction.Parameter<string>("key");
Обновить:
Мой первый ответ был для объявления функции, которая возвращает тип, не запрашиваемый в одатате. Чтобы включить запрос, функция должна возвращать сущность одататы из набора сущностей:
builder.Function("CustomerByNo").ReturnsFromEntitySet<CustomerDTO>("Customer").Parameter<int>("No")