Web API Odata 未返回正确的元数据

Web API Odata not returning correct metadata

我在 Web API 中使用 OData v4 与我的 AngularJS Web 应用程序通信。

更具体地说,我正在尝试使用 Kendo UI 网格显示我的数据。

我的问题是,我的 Web API 没有 return 正确的元数据,导致 Kendos 数据源无法显示数据。

我正在进行分页,为此我需要 "count" 属性 在我对 Kendo UI 网格数据源的响应中才能正常工作。

我期待 Web API 的响应应该如下所示: http://docs.oasis-open.org/odata/odata-json-format/v4.0/errata02/os/odata-json-format-v4.0-errata02-os-complete.html#_Toc403940644

但是,我在响应中看到的结果是:

{
  "@odata.context":"http://localhost:1983/odata/$metadata#TestReports","value":[
    {
      "Id":1,"Name":"Test Testesen","Purpose":"Kendo UI Grid Test","Type":"Rumraket","ReportedDate":"2015-02-04T10:03:59.4173323+01:00"
    },{
      "Id":2,"Name":"Gunner Testesen","Purpose":"OData Web API Test","Type":"Sutsko","ReportedDate":"2015-02-04T10:03:59.4173323+01:00"
    },{
      "Id":3,"Name":"Bertram Didriksen","Purpose":"Server Paging Test","Type":"Flyver","ReportedDate":"2015-02-04T10:03:59.4173323+01:00"
    },{
      "Id":4,"Name":"Oluf Petersen","Purpose":"Test","Type":"B\u00e5d","ReportedDate":"2015-02-04T10:03:59.4173323+01:00"
    },{
      "Id":5,"Name":"Alfred Butler","Purpose":"Opvartning","Type":"Batmobil","ReportedDate":"2015-02-04T10:03:59.4173323+01:00"
    }
  ]
}

我检索数据的代码是:

$scope.pendingReports = {
                dataSource: {
                    type: "odata",
                    transport: {
                        read: {
                            beforeSend: function (req) {
                                req.setRequestHeader('Accept', 'application/json;odata=fullmetadata');
                            },
                            url: "/odata/TestReports",
                            dataType: "odata"                                    
                        },
                        parameterMap: function (options, type) {                            
                            var paramMap = kendo.data.transports.odata.parameterMap(options);

                            console.log(paramMap);

                            delete paramMap.$inlinecount; // <-- remove inlinecount parameter
                            delete paramMap.$format; // <-- remove format parameter

                            console.log(paramMap);

                            return paramMap;
                        }
                    },
                    schema: {
                        data: function (data) {
                            return data; // <-- The result is just the data, it doesn't need to be unpacked.
                        },
                        total: function (data) {
                            return data.length; // <-- The total items count is the data length, there is no .Count to unpack.

                        }
                    },
                    pageSize: 5,
                    serverPaging: true,
                    serverSorting: true
                },
                sortable: true,
                pageable: true,
                dataBound: function () {
                    this.expandRow(this.tbody.find("tr.k-master-row").first());
                },
                columns: [
                    {
                        field: "Name",
                        title: "Navn"
                    }, {
                        field: "ReportedDate",
                        title: "Indberetet den"
                    }, {
                        field: "Purpose",
                        title: "Formål"
                    }, {
                        field: "Type",
                        title: "Type"
                    }, {
                        field: "options",
                        title: "Muligheder"
                    }
                ]
            };

我的 WebApiConfig class 目前是这样的:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create());

            config.MapODataServiceRoute(
                routeName: "odata",
                routePrefix: "odata",
                model: GetModel()
                );
        }

        public static Microsoft.OData.Edm.IEdmModel GetModel()
        {
            ODataModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet<TestReport>("TestReports");

            return builder.GetEdmModel();
        }
    }

有人对我如何让 Web API 获得 return 正确的元数据有什么建议吗?

显然 Kendo UI 网格不支持 OData v4。

解决方法是修改 Kendo 数据源的 parameterMap,并告诉它使用 $count 而不是 $inlinecount。

除此之外,我必须告诉架构将“@odata.count”读作 "total" 值。

在我将之前发布的代码编辑到下面的颂歌之后,我的回复中得到了正确的数据:

$scope.pendingReports = {
                dataSource: {
                    type: "odata",
                    transport: {
                        read: {
                            beforeSend: function (req) {
                                req.setRequestHeader('Accept', 'application/json;odata=fullmetadata');
                            },
                            url: "/odata/TestReports",
                            dataType: "json"                                    
                        },
                        parameterMap: function (options, type) {                            
                            var d = kendo.data.transports.odata.parameterMap(options);

                            delete d.$inlinecount; // <-- remove inlinecount parameter                                                        

                            d.$count = true;

                            return d;
                        }
                    },
                    schema: {
                        data: function (data) {
                            return data.value; // <-- The result is just the data, it doesn't need to be unpacked.
                        },
                        total: function (data) {
                            return data['@odata.count']; // <-- The total items count is the data length, there is no .Count to unpack.
                        }
                    },
                    pageSize: 5,
                    serverPaging: true,
                    serverSorting: true
                },
                sortable: true,
                pageable: true,
                dataBound: function () {
                    this.expandRow(this.tbody.find("tr.k-master-row").first());
                },
                columns: [
                    {
                        field: "Name",
                        title: "Navn"
                    }, {
                        field: "ReportedDate",
                        title: "Indberetet den"
                    }, {
                        field: "Purpose",
                        title: "Formål"
                    }, {
                        field: "Type",
                        title: "Type"
                    }, {
                        field: "options",
                        title: "Muligheder"
                    }
                ]
            };