如何在Refit的强类型对象中提交URL编码字典?Postman转Refit表单编码不一致问题求助
解决Refit中UrlEncoded表单字典类型无法正确编码的问题
你遇到的问题其实是Refit默认的UrlEncoded序列化机制的限制——它对IDictionary类型并不会自动展开成Postman那样的索引式键值对,而是直接调用了字典的ToString()方法,所以才会出现System.Collections.Generic.Dictionary...这种不符合预期的内容。
下面给你两种可行的解决方案:
方案1:改用List<KeyValuePair>替代字典(推荐)
Refit对集合类型(比如List<T>)的UrlEncoded序列化支持更好,能自动展开成你需要的Key[index].Property格式。你只需要修改请求实体的定义:
public record PostFeedbackRequest( string Body, bool AllowContact, string Context, List<KeyValuePair<string, int>>? QuestionsAnswers = null);
调用的时候传入List类型的参数即可:
var response = await Api.PostFeedback( new PostFeedbackRequest( "Test", true, "Refit", new List<KeyValuePair<string, int>> { new("Question", 2) }));
这样Refit生成的UrlEncoded数据就会和Postman的格式一致:Body=Test&AllowContact=True&Context=Refit&QuestionsAnswers%5B0%5D.Key=Question&QuestionsAnswers%5B0%5D.Value=2
方案2:自定义UrlEncoded参数转换器
如果你一定要保留IDictionary类型,可以通过实现Refit的IUrlEncodedParameterSerializer接口来定制序列化逻辑。
首先创建自定义转换器:
public class DictionaryUrlEncodedSerializer : IUrlEncodedParameterSerializer { private readonly DefaultUrlEncodedParameterSerializer _defaultSerializer = new(); public string Serialize(object? obj) { if (obj is PostFeedbackRequest request) { var parameters = new List<KeyValuePair<string, string>>(); // 添加基础字段 parameters.Add(("Body", request.Body)); parameters.Add(("AllowContact", request.AllowContact.ToString())); parameters.Add(("Context", request.Context)); // 处理字典字段 if (request.QuestionsAnswers != null) { int index = 0; foreach (var (key, value) in request.QuestionsAnswers) { parameters.Add(($"QuestionsAnswers[{index}].Key", key)); parameters.Add(($"QuestionsAnswers[{index}].Value", value.ToString())); index++; } } // 编码所有参数 return string.Join("&", parameters.Select(p => $"{Uri.EscapeDataString(p.Key)}={Uri.EscapeDataString(p.Value)}")); } // 其他类型回退到默认序列化 return _defaultSerializer.Serialize(obj); } }
然后在创建Refit客户端时注册这个转换器:
var refitSettings = new RefitSettings { UrlEncodedParameterSerializer = new DictionaryUrlEncodedSerializer() }; var api = RestService.For<IMyApi>("https://your-api-base-url", refitSettings);
这个转换器会专门处理你的PostFeedbackRequest类型,把字典展开成Postman风格的参数格式。
内容的提问来源于stack exchange,提问作者Steve Wilford
相关产品推荐
相关产品推荐

