首页 > 解决方案 > Asp.net Core/ODATA 控制器在从 Postman 发送时未接收到 id

问题描述

我正在探索 OData。

我一直在关注使用 OData -通过 Referbruv集成现有的 ASP.NET Core 3.x API !

我的 EdmModel 遵循他的,如下所示:

    internal static IEdmModel GetEdmModel() {
        // create OData builder instance
        var builder = new ODataConventionModelBuilder();

        // CLIENTS
        // map the entities set which are the types returned from the endpoint onto the OData pipeline
        // the string parameter is the name of the controller 
        // which supplies the data of type Client entity model in this case
        builder.EntitySet<ClientIndexDto>("ODataClient").EntityType.HasKey(x => x.id);
        builder.EntitySet<ClientDetailsDto>("ODataClientDetails").EntityType.HasKey(x => x.id);


        // configure a function onto the builder, AllClients 
        // which is same as the name provided in the ODataRoute
        builder.Function("AllClients")
            .ReturnsCollectionFromEntitySet<ClientIndexDto>("ODataClient");

        builder.Function("ClientById")
            .ReturnsCollectionFromEntitySet<ClientDetailsDto>("ODataClientDetails")
            .Parameter<int>("id");


        return builder.GetEdmModel();
    }

这部分:

builder.Function("ClientById")
            .ReturnsCollectionFromEntitySet<ClientDetailsDto>("ODataClientDetails")
            .Parameter<int>("id");

处理通过 ID 获取客户。

为了完整起见,我在我的 StartUp.cs 文件中为 OData 提供了以下内容:

        app.UseEndpoints(endpoints => { 
            endpoints.MapControllers();
            endpoints.Select().Filter().OrderBy().Expand().Count().MaxTop(10);
            endpoints.MapODataRoute("odata", "odata", GetEdmModel());
        });

返回的 $metadata 如下:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema Namespace="JobsLedger.MODELS.API.App.Client" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="ClientIndexDto">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Int32" Nullable="false" />
                <Property Name="ClientNo" Type="Edm.String" />
                <Property Name="Active" Type="Edm.Boolean" Nullable="false" />
                <Property Name="ClientFirstName" Type="Edm.String" />
                <Property Name="ClientLastName" Type="Edm.String" />
                <Property Name="Company" Type="Edm.Boolean" Nullable="false" />
                <Property Name="CompanyName" Type="Edm.String" />
                <Property Name="MobilePhone" Type="Edm.String" />
                <Property Name="IsWarrantyCompany" Type="Edm.Boolean" Nullable="false" />
                <Property Name="JobsCount" Type="Edm.String" />
            </EntityType>
            <EntityType Name="ClientDetailsDto">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Int32" Nullable="false" />
                <Property Name="ClientNo" Type="Edm.String" />
                <Property Name="Company" Type="Edm.Boolean" Nullable="false" />
                <Property Name="IsWarrantyCompany" Type="Edm.Boolean" Nullable="false" />
                <Property Name="CompanyName" Type="Edm.String" />
                <Property Name="ClientFirstName" Type="Edm.String" />
                <Property Name="ClientLastName" Type="Edm.String" />
                <Property Name="MobilePhone" Type="Edm.String" />
                <Property Name="DeActivated" Type="Edm.String" />
                <Property Name="CreatedOn" Type="Edm.String" />
                <Property Name="CreatedBy" Type="Edm.String" />
                <Property Name="ModifiedOn" Type="Edm.String" />
                <Property Name="ModifiedBy" Type="Edm.String" />
                <Property Name="SuburbId" Type="Edm.Int32" Nullable="false" />
                <NavigationProperty Name="Address" Type="JobsLedger.MODELS.Common.Address.AddressDto" />
                <NavigationProperty Name="ClientJobs" Type="Collection(JobsLedger.MODELS.API.App.Job.ClientJobDto)" />
                <NavigationProperty Name="ClientNotes" Type="Collection(JobsLedger.MODELS.Common.Notes.ClientNoteDto)" />
            </EntityType>
        </Schema>
        <Schema Namespace="JobsLedger.MODELS.Common.Address" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="AddressDto">
                <Key>
                    <PropertyRef Name="Address1" />
                </Key>
                <Property Name="Address1" Type="Edm.String" Nullable="false" />
                <Property Name="Address2" Type="Edm.String" />
                <Property Name="SuburbId" Type="Edm.Int32" Nullable="false" />
                <Property Name="SuburbName" Type="Edm.String" />
                <Property Name="StateShortName" Type="Edm.String" />
                <Property Name="Postcode" Type="Edm.String" />
            </EntityType>
        </Schema>
        <Schema Namespace="JobsLedger.MODELS.API.App.Job" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="ClientJobDto">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Int32" Nullable="false" />
                <Property Name="JobNo" Type="Edm.String" />
                <Property Name="AgentJobNo" Type="Edm.String" />
                <Property Name="Type" Type="Edm.String" />
                <Property Name="Status" Type="Edm.String" />
                <Property Name="WarrantyCompany" Type="Edm.String" />
                <Property Name="NumberOfVisits" Type="Edm.String" />
                <Property Name="CreatedOn" Type="Edm.String" />
                <Property Name="CreatedBy" Type="Edm.String" />
                <Property Name="ModifiedOn" Type="Edm.String" />
                <Property Name="ModifiedBy" Type="Edm.String" />
                <NavigationProperty Name="JobNotes" Type="Collection(JobsLedger.MODELS.Common.Notes.JobNoteDto)" />
                <NavigationProperty Name="JobVisits" Type="Collection(JobsLedger.MODELS.API.App.Job.JobVisitDto)" />
            </EntityType>
            <EntityType Name="JobVisitDto">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Int32" Nullable="false" />
                <Property Name="DateCreated" Type="Edm.String" />
                <Property Name="VisitDate" Type="Edm.String" />
                <Property Name="StartTime" Type="Edm.String" />
                <Property Name="EndTime" Type="Edm.String" />
            </EntityType>
        </Schema>
        <Schema Namespace="JobsLedger.MODELS.Common.Notes" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <EntityType Name="JobNoteDto">
                <Key>
                    <PropertyRef Name="Id" />
                </Key>
                <Property Name="Id" Type="Edm.Int32" Nullable="false" />
                <Property Name="JobId" Type="Edm.Int32" Nullable="false" />
                <Property Name="Details" Type="Edm.String" />
                <Property Name="NoteType" Type="Edm.String" />
                <Property Name="CreatedOnDate" Type="Edm.String" />
                <Property Name="CreatedOnTime" Type="Edm.String" />
                <Property Name="CreatedBy" Type="Edm.String" />
                <Property Name="ModifiedOnDate" Type="Edm.String" />
                <Property Name="ModifiedOnTime" Type="Edm.String" />
                <Property Name="ModifiedBy" Type="Edm.String" />
            </EntityType>
            <EntityType Name="ClientNoteDto">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Int32" Nullable="false" />
                <Property Name="Details" Type="Edm.String" />
                <Property Name="NoteType" Type="Edm.String" />
                <Property Name="CreatedOnDate" Type="Edm.String" />
                <Property Name="CreatedOnTime" Type="Edm.String" />
                <Property Name="CreatedBy" Type="Edm.String" />
                <Property Name="ModifiedOnDate" Type="Edm.String" />
                <Property Name="ModifiedOnTime" Type="Edm.String" />
                <Property Name="ModifiedBy" Type="Edm.String" />
            </EntityType>
        </Schema>
        <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <Function Name="AllClients">
                <ReturnType Type="Collection(JobsLedger.MODELS.API.App.Client.ClientIndexDto)" />
            </Function>
            <Function Name="ClientById">
                <Parameter Name="id" Type="Edm.Int32" Nullable="false" />
                <ReturnType Type="Collection(JobsLedger.MODELS.API.App.Client.ClientDetailsDto)" />
            </Function>
            <EntityContainer Name="Container">
                <EntitySet Name="ODataClient" EntityType="JobsLedger.MODELS.API.App.Client.ClientIndexDto" />
                <EntitySet Name="ODataClientDetails" EntityType="JobsLedger.MODELS.API.App.Client.ClientDetailsDto" />
                <FunctionImport Name="AllClients" Function="Default.AllClients" EntitySet="ODataClient" IncludeInServiceDocument="true" />
                <FunctionImport Name="ClientById" Function="Default.ClientById" EntitySet="ODataClientDetails" IncludeInServiceDocument="true" />
            </EntityContainer>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

我的控制器如下:

using JobsLedger.API.Controllers.API.App.Interfaces;
using JobsLedger.API.ControllerServices.API.App.ClientService.Interfaces;
using JobsLedger.DATA;
using JobsLedger.DATA.Repositories.Interfaces;
using JobsLedger.MODELS.API.App.Client;

using Microsoft.AspNet.OData;
using Microsoft.AspNet.OData.Routing;
using Microsoft.AspNetCore.Mvc;

using System;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Authorization;

namespace JobsLedger.API.Controllers.API.App {

    [Route("api/[controller]")]
    [ApiController]
    [Authorize(Roles = "TenantAdmin,Admin,Employee")]
    public class ODataClientController : ODataController, IClientController {
        private readonly IClientServices _clientServices;

        public ODataClientController( IClientServices clientServices) {
            _clientServices = clientServices;
        }

        [HttpGet]
        [EnableQuery()]
        [ODataRoute("AllClients()")]
        public IActionResult Get() 
        {
            return Ok(_clientServices.GetAllClientsAsDto());
        }

        [HttpGet]
        [EnableQuery]
        [ODataRoute("ClientById(id={id})")]
        public IActionResult Get(int id) {
            return Ok(_clientServices.GetClient(id));
        }

我想获得一个 ID 为“5”的客户端,所以我在 Postman 中使用以下 get 命令:

https://localhost:44301/odata/ClientById(id=5)?

正如教程所示 - “id = 5”周围有括号

它到达端点,但 id 设置为“0”。

在此处输入图像描述

鉴于我的 EdmModel、#MetaData 和单个 Id 的控制器操作,为什么当我发送带有 GET 的命令时,(Id=5)我得到 Id=0?我需要做什么来解决这个问题?

标签: c#asp.net-coreodata

解决方案


在文章评论中,Referbruv 还提到了 .net core 3.1 中的路由问题。所以,你可以在 3.0 中尝试它,如果它在那里工作,那就是 3.1 的问题。

如果你可以用id=来做,那么基于attr-routing这应该可以工作。

[ODataRoute("ClientById({id})")]


推荐阅读