Flurl数组编码

5
我正在尝试将包含字符串数组的一些数据发布到一个端点,但收到错误消息“无效数组”。

我是这样做的:

   .PostUrlEncodedAsync(new
     {
        amount = 1000,
        allowed_source_types = new[] { "card_present" },
        capture_method = "manual",
        currency = "usd"
     });

在此发布的结果为:

amount=1000&allowed_source_types=card_present&capture_method=manual&currency=usd

API供应商抱怨我发布的数组无效。当我这样做时:
    .PostUrlEncodedAsync(
             "amount=1000&allowed_source_types[]=card_present&capture_method=manual&currency=usd"
    );

这段文字的英译中文如下:

发布此内容的结果:

amount=1000&allowed_source_types[]=card_present&capture_method=manual&currency=usd

API供应商很满意,我得到了预期的结果。

问题:这是一个错误吗?allowed_source_types参数是否应该包括最初在这里详细说明的[ ]


1
在URL术语中,使用allowed_source_types [] = card_present将参数名为allowed_source_types []的参数值设置为单个值card_present--这与设置名为allowed_source_types的参数不同。 API当然可以使用其中带有[]的参数名称(如果在发送到服务器时正确编码),但这并不是标准。 Flurl没有被要求添加[]是不正确的。当然,棘手的部分是您无法在C#中指定具有[]的名称的属性,因此需要另一种机制。 - Jeroen Mostert
1
值得注意的是,还要检查API是否接受传递多值参数的“标准”方式(a=val1&a=val2&a=val3),或者是否也使用其他方式(a[]=val1,val2,val3)。后者也不是通用库应该在未经请求的情况下执行的操作。(话虽如此,标准实际上并没有关于多值参数的规定,但第一种方式是自古以来浏览器使用的方式,因此被称为“标准”。API可能会有不同的想法。) - Jeroen Mostert
@JeroenMostert 你评论中的一切都是完全正确的,而你所描述的大多数“标准”正是Flurl所做的,所以我邀请你把它放在一个答案中。 PostUrlEncodedAsync 对字典提供了特殊处理,这是我能想到的最好的方式来获得添加[] 的方法。 - Todd Menier
@ToddMenier:我完全没有使用过Flurl的经验,所以对于那些有经验的人来说,可能还有更好的答案。具体来说,在Flurl中调用这个API的“正确”方式会很好(当然,自己编写一个文本查询字符串肯定是可行的,但那是最不理想的方式)。 - Jeroen Mostert
@JeroenMostert - 感谢您提供的详细信息。我肯定学到了一些东西。我曾尝试传递类似于a=val1&a=val2&a=val3的等效值,但API返回了“无效数组”错误。 - Stephen McDowell
2个回答

6

这不是一个错误。正如评论中所提到的,没有标准来对集合进行URL编码,但可以像这样进行:

x[]=1,2,3

这种做法比起像这样做的方式要少得多:

x=1&x=2&x=3

后者是Flurl如何实现它

按照API要求的方式进行操作的问题在于,在C#标识符中[]不是有效的,因此典型的对象表示法无法工作。但是Flurl对Dictionary对象进行了特殊处理,因此您最好这样做:

.PostUrlEncodedAsync(new Dictionary<string, object>
{
    ["amount"] = 1000,
    ["allowed_source_types[]"] = "card_present", // or string.Join(",", allowedSourceTypes)
    ["capture_method"] = "manual",
    ["currency"] = "usd"
 });

1
感谢提供详细信息。传递字典的操作已按预期完成。并且感谢您给了我们 Flurl。你让 C# 世界变得更美好了! - Stephen McDowell

0
我遇到了一个类似的问题,我使用Flurl将一个字符串数组传递给GET请求。首先,我用逗号","将数组的每个成员连接起来,但是在发送请求时,逗号被编码为"%2",所以Flurl在设置查询参数时有一个名为"isEnabled"的选项,允许你将其设置为true,当它为true时,它会跳过编码。
public async Task<IEnumerable<User>> GetGroupUsersAsync(string realm, string[] groupIds)
    {
        string groupIdsStr = string.Join(",", groupIds);

        return await GetBaseUrl(realm)
            .AppendPathSegment($"/realms/{realm}/custom-endpoint/users/get")
            .SetQueryParam("groupIds", groupIdsStr, true)
            .GetJsonAsync<IEnumerable<User>>()
            .ConfigureAwait(false);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接