Reputation: 1762
I am having a problem binding an array of key value pair objects in MVC5. This is the JSON:
{
"expiration": "2013-12-03T04:30:41.206Z",
"conditions": [
{
"acl": "private"
},
{
"bucket": "ryvus.upload.test"
},
{
"Content-Type": "application/vnd.ms-excel"
},
{
"success_action_status": "200"
},
{
"key": "fc42ae8a-1f6e-4955-a669-8272ad650cb9.csv"
},
{
"x-amz-meta-qqfilename": "simpleupload.csv"
}
]
}
If I attempt to bind conditions to a Dictionary<string, string>
like this:
// View Model
public class ResponseVM
{
public DateTime Expiration { get; set; }
public Dictionary<string, string> Conditions { get; set; }
}
// Controller Action
public ActionResult MyHandler(ResponseVM s3Response)
{
//do something
return JSON(null);
}
I get a 6 entries with keys of "0","1","2","3","4","5" and null values. I seem so close but I've tried a bunch of different types without success, the Dictionary<string, string>
was the best I could get.
Am I missing something completely obvious here?
Upvotes: 3
Views: 2917
Reputation: 4793
I think the problem lies with the fact that the conditions
structure cannot be mapped to a key value pair... the conditions
structure is actually
an array of objects of different types, where for example the first object can be modelled such:
public class ACL {
public string acl { get; set; }
}
the next object like:
public class Bucket {
public string bucket { get; set; }
}
etc. It's not a bindable key value pair.
To get your conditions structure to bind to a KeyValuePair<TKey, TValue>
structure you want your JSON to look more like this:
{
"expiration": "2013-12-03T04:30:41.206Z",
"conditions": [
{
Key: "acl",
Value: "private"
},
{
Key: "bucket",
Value: "ryvus.upload.test"
},
...
]
}
EDIT: if you cannot change the JSON schema and you are not going to write a custom binder then the following structure should work, .. but it's
not pretty because you have and instance of NVPair
for each item in conditions
.
Your models:
public class NVPair {
public string acl { get; set; }
public string bucket { get; set; }
[JsonProperty("Content-Type")]
public string ContentType { get; set; }
public string success_action_status { get; set; }
public string key { get; set; }
...
}
public class ResponseVM
{
public DateTime Expiration { get; set; }
public List<NVPair> Conditions { get; set; }
}
This way there will be a seperate item for each nvp. But it should bind.
If you don't wanna you JSON.Net's JsonProperty
attrib you can use DataContract
like here
Upvotes: 0
Reputation: 15420
Since the JSON scheme can't be changed, the easiest way is the change the class to match the JSON.
public class ResponseVM
{
public DateTime Expiration { get; set; }
public List<Dictionary<string, string>> Conditions { get; set; }
}
Condition is a list of maps.
By the way, the purpose of view models (VM) is for abstracting the view. It's not for input.
Upvotes: 1
Reputation: 797
$.ajax({
type: 'POST',
dataType: 'json',
data: JSON.stringify(data),
url: "your url",
contentType: 'application/json; charset=utf-8',
success: function (t) {
// code here
}
});
Try it.
I didn't bind to dictionary, but array works fine.
Upvotes: 0