You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 16:54:09