使用Refit传递QueryString复杂对象数组参数遇问题求助
问题分析与解决方案
你的问题核心是Refit默认未正确序列化复杂对象数组类型的Query参数,导致生成了数组自身的公共属性(如Length、LongLength)而非期望的索引式参数格式。以下是针对性的解决步骤:
1. 修正Refit接口定义
首先完善接口参数的[Query]特性,同时显式声明分页参数的Query属性:
[Get("/Hierarchies/GetHierarchy")] [Headers("Authorization: Bearer")] Task<List<RestHierarchy>> GetHierarchyAsync( [Query(CollectionFormat = CollectionFormat.Multi)] SearchParameter<RestHierarchy>[]? searchParameters = null, [Query] int pageNumber = 1, [Query] int pageSize = 50);
2. 配置Refit使用正确的Query参数格式化器
Refit默认的参数格式化器无法处理复杂对象数组的索引式序列化,需要指定基于Json的格式化器,让它遍历数组元素并展开属性:
方式一:使用Newtonsoft.Json(Json.NET)
如果项目依赖Newtonsoft.Json,创建Refit客户端时添加如下配置:
var apiClient = RestService.For<IMyApiInterface>(new HttpClient { BaseAddress = new Uri("https://localhost/api/") }, new RefitSettings { QueryStringParameterFormatter = new NewtonsoftJsonQueryStringParameterFormatter(new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = { new StringEnumConverter() } // 确保枚举序列化为字符串 }) });
方式二:使用System.Text.Json
如果项目使用System.Text.Json,配置如下:
var apiClient = RestService.For<IMyApiInterface>(new HttpClient { BaseAddress = new Uri("https://localhost/api/") }, new RefitSettings { QueryStringParameterFormatter = new SystemTextJsonQueryStringParameterFormatter(new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new JsonStringEnumConverter() } // 枚举转字符串 }) });
3. 确保枚举类型正确序列化
修改SearchParameter<T>类,给LogicalOperator属性添加枚举转字符串的特性,保证生成的参数和Postman一致:
public class SearchParameter<T> { public string FieldName { get; set; } // 添加此特性,让枚举序列化为字符串而非数字 [JsonConverter(typeof(StringEnumConverter))] public LogicalOperators LogicalOperator { get; set; } public string? Value1 { get; set; } public string? Value2 { get; set; } [JsonIgnore] private Type? FieldType { get { Type ClassType = typeof(T); var member = ClassType.GetMembers().FirstOrDefault(a => a.Name == FieldName); return member is PropertyInfo info ? info.PropertyType : ((FieldInfo)member).FieldType; } } public override string ToString() { // 保留原有实现 } }
原理说明
之前的配置仅指定了CollectionFormat.Multi,但Refit默认会将数组本身视为一个普通对象,序列化它的公共属性(如数组的Length)。通过配置Json-based的Query格式化器,Refit会遍历数组中的每个SearchParameter对象,将其属性展开为searchParameters[0].FieldName=xxx的索引式格式,与后端API的[FromQuery]绑定规则匹配。
内容的提问来源于stack exchange,提问作者user19246845
相关产品推荐
相关产品推荐

