我正在使用AngularJS和KendoUI来创建一个网格,该网格从WebAPI Web服务获取其数据。对于网格,我想允许服务器端排序,分页,过滤和分组。为此,我正在尝试使用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);
}
因此,如果我在“名称”列上设置“包含”过滤器,其值为“test”,则会出现上述错误。任何想法为什么?
答案 0 :(得分:0)
没有财产或字段&#39;测试&#39;存在于类型&#39; MyEntity&#39; ..
中我认为只能找到值Id,Name,Description .. 消息sais&#34;我搜索属性和字段..&#34;
并且ID,姓名,说明是唯一的&#39;属性或字段&#39;。
- &#39;测试&#39;是一个值,而不是属性或字段 -
答案 1 :(得分:0)
经过一天的挣扎,我终于在今天发布了SO。当然,在问了这个问题后的几分钟,我偶然发现了答案!
问题最终是我的客户端JS代码和我的实体之间的列名称大小不一。在我的WebApiConfig中,我正在使用
// Web API configuration and services
var settings = config.Formatters.JsonFormatter.SerializerSettings;
settings.Formatting = Formatting.Indented;
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
此代码使得当我的WebAPI返回数据时,所有字段名称都转换为驼峰大小写。这是因为我希望在JS方面使用camel case中的所有内容进行编码,而在C#方面使用Pascal大小写。
让我失望的第一件事就是其他KendoGridApiRequest操作(如Sort)在属性名称方面似乎不区分大小写。另一件事是错误消息说它正在寻找过滤器值作为属性;它应该说'MyEntity'类型中存在“没有属性或字段'名称”;然后我可能会马上知道它是将它扔掉的外壳。
现在我需要弄清楚我将如何将请求属性转换回Pascal案例。最糟糕的情况我必须将所有内容转换为相同的情况,但这将是很多工作(实体比我的示例更复杂)。
答案 2 :(得分:0)
您可以做的是在kendo-grid将这些属性名称发送到服务器之前修改属性名称。
所以filter.field值&#39;名称&#39;转换为&#39;名称&#39;。
看到这个修改过的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();
};