Спираючись на пропозицію @ GWB використовувати a 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, які я використовував, також не приймав масиви (я не впевнений, що існує навіть стандартизований спосіб їх серіалізації за допомогою кодування форми), Я залишу це для вас, якщо вам потрібно їх підтримати.