Основываясь на предложении @ GWB об использовании RouteValueDictionary
, я написал эту рекурсивную функцию для поддержки вложенных анонимных типов, добавляя префикс этих вложенных параметров с помощью ключей их родителей.
public static string EncodeHtmlRequestBody(object data, string parent = null) {
var keyValuePairs = new List<string>();
var dict = new RouteValueDictionary(data);
foreach (var pair in dict) {
string key = parent == null ? pair.Key : parent + "." + pair.Key;
var type = pair.Value.GetType();
if (type.IsPrimitive || type == typeof(decimal) || type == typeof(string)) {
keyValuePairs.Add(key + "=" + Uri.EscapeDataString((string)pair.Value).Replace("%20", "+"));
} else {
keyValuePairs.Add(EncodeHtmlRequestBody(pair.Value, key));
}
}
return String.Join("&", keyValuePairs);
}
Пример использования:
var data = new {
apiOperation = "AUTHORIZE",
order = new {
id = "order123",
amount = "101.00",
currency = "AUD"
},
transaction = new {
id = "transaction123"
},
sourceOfFunds = new {
type = "CARD",
provided = new {
card = new {
expiry = new {
month = "1",
year = "20"
},
nameOnCard = "John Smith",
number = "4444333322221111",
securityCode = "123"
}
}
}
};
string encodedData = EncodeHtmlRequestBody(data);
encodedData
становится:
"apiOperation=AUTHORIZE&order.id=order123&order.amount=101.00&order.currency=AUD&transaction.id=transaction123&sourceOfFunds.type=CARD&sourceOfFunds.provided.card.expiry.month=1&sourceOfFunds.provided.card.expiry.year=20&sourceOfFunds.provided.card.nameOnCard=John+Smith&sourceOfFunds.provided.card.number=4444333322221111&sourceOfFunds.provided.card.securityCode=123"
Надеюсь, это поможет кому-то еще в подобной ситуации.
Редактировать: Как указывал DrewG, он не поддерживает массивы. Правильно реализовать поддержку произвольно вложенных массивов с анонимными типами было бы нетривиально, и поскольку ни один из API, которые я использовал, также не принимал массивы (я не уверен, что существует даже стандартизированный способ сериализации их с кодированием формы), Я оставлю это вам, ребята, если вам нужно их поддержать.