การกำหนดเส้นทางแอตทริบิวต์สำหรับการดำเนินการสองรายการนำไปสู่เทมเพลตเส้นทาง OData ที่ไม่ถูกต้อง

ดังนั้นฉันจึงมีสองฟังก์ชันที่ส่งคืนลูกค้า ซึ่งได้รับฟีดจากพารามิเตอร์สองตัวที่แตกต่างกัน อันหนึ่งคือ 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;
        }
    }
}

ในขณะที่ฟังก์ชันที่สองทำงานตามที่ตั้งใจไว้ ฟังก์ชันแรกไม่ทำงาน และฟังก์ชัน SureInitialized() จะส่ง 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] ในการประกาศวิธีการ การโทรจะล้มเหลวโดยบอกว่าไม่ทราบวิธีการดีซีเรียลไลซ์เนื่องจากไม่ได้ผูกไว้กับชุดเอนทิตีของลูกค้าฉันเดา

การลองใช้วิธีนี้ทำให้เกิดข้อความแสดงข้อผิดพลาดเดิมว่าไม่พบทรัพยากร:

        builder.EntityType<CustomerDTO>().Collection.Function("CustomerByNo").Returns<SingleResult<CustomerDTO>>().Parameter<int>("No");

person Peter    schedule 15.05.2018    source แหล่งที่มา


คำตอบ (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")
person J.Loscos    schedule 15.05.2018
comment
ขอบคุณ! แต่นี่ไม่ค่อยได้ผล เพิ่ม SingleResult ของ CustomerDTO ในการส่งคืน แต่ก็ไม่สำคัญอยู่ดี มันแค่ให้ 404 กับฉัน - person Peter; 16.05.2018
comment
เพียงเพื่อให้แน่ใจว่าคุณใช้ URL ที่ถูกต้อง URL ของฟังก์ชัน odata ที่กำหนดเองคือ yourhost/CustomerByCNO(key) ชื่อของคอนโทรลเลอร์ไม่อยู่ใน url - person J.Loscos; 16.05.2018
comment
ฉันทำ :) ตรวจสอบการแก้ไขของฉัน บางทีนั่นอาจจะให้ข้อมูลภายในเพิ่มเติมแก่คุณ - person Peter; 16.05.2018
comment
ลองกับ builder.Function(CustomerByCNO).ReturnsCollectionFromEntitySet‹CustomerDTO›(Customer).Parameter‹int›(No) ด้วยวิธีนี้จะรู้ว่าประเภทผลลัพธ์นั้นมาจาก EntitySet ของลูกค้า - person J.Loscos; 16.05.2018
comment
builder.Function(CustomerByNo).ReturnsFromEntitySet‹CustomerDTO›(Customer).Parameter‹int›(No); ทำงานเหมือนมีเสน่ห์ ขอบคุณ! :D - person Peter; 16.05.2018
comment
ดี :) ฉันอัปเดตคำตอบเพื่อรวมวิธีแก้ปัญหาที่ถูกต้อง - person J.Loscos; 16.05.2018