1

我正在使用 AngularJS 和 KendoUI 来创建一个网格,该网格从 WebAPI 网络服务中获取数据。对于网格,我希望允许服务器端排序、分页、过滤和分组。为此,我正在尝试使用KendoGridBinderEx库。

我已经下载了 KendoGridBinderEx 源代码,运行示例项目,它运行良好。但是,当我在项目中执行完全相同的操作时,当我尝试对网格中的列进行过滤时出现以下错误:

System.Linq.Dynamic.ParseException:“MyEntity”类型中不存在属性或字段“test”

“测试”是我在过滤器中输入的内容,所以它应该是过滤器文本;它不应该寻找名为“test”的属性或字段。

我已经调试并使用 Fiddler 看到请求中发送的请求的过滤器部分与示例中的工作请求完全相同,所以我认为问题不在请求端。

对于我所有的代码块,我正在简化所有内容以节省空间,并删除不相关的内容。例如,我正在删除我的数据库代码,并动态生成一个实体列表,因为这样做仍然会出现问题,因此我知道这不是我的实体框架代码的问题。

这是我的 JS 代码:

    var myDataSource = {
        transport: {
            read: {
                url: function () {
                    return url;
                },
                type: 'post',
                dataType: 'json'
            },
            parameterMap: function (options, operation) {
                if (options.filter) {
                    KendoGrid_FixFilter(myDataSource, options.filter);
                }

                if (operation === "read") {
                    // convert the parameters to a json object
                    return kendo.stringify(options);
                }

                return options;
            }
        },
        serverPaging: true,
        serverSorting: true,
        serverFiltering: true,
        serverGrouping: true
        schema: {
            data: 'data',
            groups: 'groups',
            aggregates: 'aggregates',
            total: 'total',
            model: {
                id: "id",
                fields: {
                    id: { type: "number" },
                    name: { type: "string" },
                    description: { type: "string" }
                }
            }
        },
    };

这是我的 WebAPI 控制器代码:

    [System.Web.Http.Route("api/MyEntity")]
    [System.Web.Http.HttpPost]
    public KendoGridEx<MyEntity, MyEntity> GetMyEntities(KendoGridApiRequest request)
    {
        var entList = new List<MyEntity>();
        for (int i = 0; i < 10; i++)
        {
            var newEntity = new MyEntity
            {
                Id = i,
                Name = "test",
                Description = "description"
            };
            entList.Add(newEntity);
        }
        return entList.AsQueryable().ToKendoGridEx<MyEntity, MyEntity>(request);
    }

因此,如果我在“名称”列上设置一个“包含”过滤器,其值为“测试”,则会出现上述错误。关于为什么的任何想法?

4

3 回答 3

0

“MyEntity”类型中不存在属性或字段“test”。

我认为只能找到值 Id,Name,Description.. 消息是“我搜索属性和字段..”

而 Id,Name,Description 是唯一的“属性或字段”。

--'test' 是一个值,而不是属性或字段--

于 2015-09-02T15:31:45.017 回答
0

您可以做的是在 kendo-grid 将这些属性名称发送到服务器之前修改属性名称。

因此 filter.field 值 'name' 被转换为 'Name'。

请参阅此修改后的 KendoGrid_FixFilter javascript 函数:

// kendoDataSource = kendo.data.DataSource
// filter = kendo filter
function KendoGrid_FixFilter(kendoDataSource, kendoFilter, depth) {
    if ((!kendoDataSource) || (!kendoFilter)) return;

    if (!depth) depth = 0;
    // console.log(depth + " - FixDatesInFilter:" + JSON.stringify(kendoFilter));

    $.each(kendoFilter.filters, function (idx, filter) {
        //console.log("filter = " + idx + " = " + JSON.stringify(filter));

        if (filter.hasOwnProperty("filters")) {
            depth++;
            KendoGrid_FixFilter(kendoDataSource, filter, depth);
        }
        else {
            $.each(kendoDataSource.schema.model.fields, function (propertyName, propertyValue) {

                if (filter.field == propertyName) {
                    // console.log("before = " + filter.field);
                    filter.field = filter.field.toPascalCase();
                    // console.log("after = " + filter.field);
                }

                if (filter.field == propertyName && propertyValue.type == 'date') {
                    filter.value = kendo.toString(filter.value, _DefaultDateFormat); // "MM/dd/yyyy"
                    // console.log("changed = " + filter.value);
                }
            });
        }
    });
}

您已经在数据源中使用了这个函数。

CamelCase/PascalCase 的示例代码可能是这样的:

String.prototype.toCamelCase = function () {
    console.log("String.prototype.toCamelCase");
    return this
        .replace(/\s(.)/g, function ($1) { return $1.toUpperCase(); })
        .replace(/\s/g, '')
        .replace(/^(.)/, function ($1) { return $1.toLowerCase(); });
};

String.prototype.toUpperCaseFirstChar = function () {
    console.log("String.prototype.toUpperCaseFirstChar");
    return this.substr(0, 1).toUpperCase() + this.substr(1);
};


String.prototype.toPascalCase = function () {
    console.log("String.prototype.toPascalCase");
    return this.toCamelCase().toUpperCaseFirstChar();
};
于 2015-09-04T18:50:52.043 回答
0

经过一天的努力,我终于在今天发布了。当然,在提出问题后仅几分钟,我就偶然发现了答案!

问题最终是我的客户端 JS 代码和我的实体之间的列名大小写不同。在我的 WebApiConfig 中,我正在使用

        // Web API configuration and services
        var settings = config.Formatters.JsonFormatter.SerializerSettings;
        settings.Formatting = Formatting.Indented;
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();

此代码使得当我的 WebAPI 返回数据时,所有字段名称都转换为驼峰式大小写。这是因为我想在 JS 端使用骆驼大小写的所有内容,但在 C# 端使用 Pascal 大小写。

让我失望的第一件事是其他 KendoGridApiRequest 操作,例如排序,在属性名称方面似乎不区分大小写。另一件事是错误消息说它正在寻找过滤器值作为属性;它应该说“'MyEntity'类型中不存在属性或字段'name'”;那么我可能会立即知道是外壳把它扔掉了。

现在我需要弄清楚如何将请求属性转换回 Pascal 大小写。在最坏的情况下,我必须将所有内容都转换为相同的情况,但这将是很多工作(实体比我的示例显示的要复杂得多)。

于 2015-09-02T15:39:19.200 回答