Sobre la base @ sugerencia de utilizar un RouteValueDictionary
de masa de agua subterránea, escribí esta función recursiva para apoyar los tipos anónimos anidados, anteponiendo los parámetros anidados por las teclas de sus padres.
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);
}
Ejemplo de uso:
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
se convierte en:
"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"
Esperanza esto ayuda a otra persona en una situación similar.
Editar: Como DrewG señaló, esto no es compatible con las matrices. Implementar adecuadamente el soporte para matrices anidadas arbitrariamente con tipos anónimos no sería trivial, y como ninguna de las API que he usado también acepta matrices (no estoy seguro de que haya incluso una forma estandarizada de serializarlas con codificación de formularios), Les dejaré eso a ustedes si necesitan apoyarlos.
var dict = props.ToDictionary (x => x.Name, x => x.GetValue (a_source, null)) – Jordan
Hemos llegado hasta aquí ... podemos hacer que sea un trazador de líneas: 'var dict = a .GetType(). GetProperties(). ToDictionary (x => x.Name, x => x.GetValue (a, null)); ' – kape123
@ kape123, de hecho.De hecho, las últimas versiones de .NET ya no requieren la llamada a 'ToArray()', lo cual es bueno. En cualquier caso, la respuesta, tal como está, encaja muy bien en SO sin envoltura de palabras, así que lo dejo tal como está. – kbrimington