.NET Core 6+OData 8下Radzen Blazor配置及查询问题排查
问题描述
当前使用 Radzen(其文档及示例仅适配.NET Core 6以下、OData 8以下版本)时遇到两个问题:
- 服务器返回的响应类型不匹配
- 过滤查询执行报错
相关代码
服务端请求代码
public async Task<ODataServiceResult<PersonDto>> GetPeopleAsync(string filter = default(string), int? top = default(int?), int? skip = default(int?), string orderby = default(string), string expand = default(string), string select = default(string), bool? count = default(bool?)) { var uri = new Uri(http.BaseAddress, $"api/Persons"); uri = uri.GetODataUri(filter: filter, top: top, skip: skip, orderby: orderby, expand: expand, select: select, count: count); var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri); var response = await http.SendAsync(httpRequestMessage); return await response.ReadAsync<ODataServiceResult<PersonDto>>(); }
控制器代码
[EnableQuery(MaxExpansionDepth = 10, MaxNodeCount = 1000)] [HttpGet] public IEnumerable<PersonDto> Get() { var people = context.Persons.ConvertToDto().AsQueryable(); return people; }
具体现象
- 无过滤的查询请求
https://localhost:7069/api/Persons?$top=5&$skip=0&$count=true可正常返回5条结果 - 带过滤的查询请求
https://localhost:7069/api/Persons?$filter=(LastName+%3d%3d+null+%3f+%27%27+%3a+LastName).ToLower().Contains(%27s%27.ToLower())&$top=5&$skip=0&$count=true执行报错,错误信息如下:
{"Message":"请求URI中指定的查询无效。在'(LastName == null ? '' : LastName).ToLower().Contains('d'.ToLower ())'的第10位位置预期有')'或运算符。","ExceptionMessage":"')'
问题分析与解决建议
1. 过滤查询报错问题
OData 8对查询语法的兼容性和严格性有变化,Radzen生成的三元表达式写法不符合OData 8规范。OData 8中处理空值需用coalesce函数替代三元运算符,正确的过滤表达式应改为:
coalesce(LastName, '').ToLower().Contains('s'.ToLower())
对应的编码后请求参数为:$filter=coalesce(LastName%2C+%27%27).ToLower().Contains(%27s%27.ToLower())
同时需确认项目中正确配置了OData 8的查询支持,EnableQuery特性参数设置符合当前版本要求,且PersonDto的属性已正确标记OData相关特性(如KeyAttribute)。
2. 响应类型不匹配问题
控制器返回IEnumerable<PersonDto>,但客户端期望ODataServiceResult<PersonDto>。OData 8中,EnableQuery特性需要处理可查询数据源才能生成符合规范的响应(包含count、分页元数据等),需修改控制器代码返回IQueryable<PersonDto>:
[EnableQuery(MaxExpansionDepth = 10, MaxNodeCount = 1000)] [HttpGet] public IQueryable<PersonDto> Get() { var people = context.Persons.ConvertToDto().AsQueryable(); return people; }
另外要确保客户端ReadAsync<ODataServiceResult<PersonDto>>()方法能正确解析OData 8的响应格式,适配新版本的响应结构差异。
内容的提问来源于stack exchange,提问作者demis15

