Asp.net mvc4 won't properly deserialize and bind dictionary <string, List <CustomType>> to json
JSON.NET deserializes it ok, but some kind of mvc is using to bind the barfs parameter to the controller. Is there anything else I can do to make this work?
Bits:
public partial class Question
{
public Dictionary<string, List<QuestionExtendedProp>> TemporaryExtendedProperties { get; set; }
}
And the controller method
[HttpPost]
public JsonResult SaveQuestions(Question[] questions)
{
var z =
JsonConvert.DeserializeObject(
"{'Options':[{'PropKey':'asdfasd','PropVal':'asdfalkj'},{'PropKey':'fdsafdsafasdfas','PropVal':'fdsafdas'}]}",
typeof (Dictionary<string, List<QuestionExtendedProp>>)) as Dictionary<string, List<QuestionExtendedProp>>;
//this deserializes perfectly. z is exactly what I want it to be
//BUT, questions is all wrong. See pic below
//lots of code snipped for clarity, I only care about the incoming questions object
return Utility.Save(questions);
}
Here's what MVC is giving me for that exact line (pushed out of the fiddler, extra options for your reading enjoyment)
"TemporaryExtendedProperties":{"Options":
[{"PropKey":"NE","PropVal":"NEBRASKA"},
{"PropKey":"CORN","PropVal":"CHILDREN OF"},
{"PropKey":"COW","PropVal":"MOO"}]}
Why is MVC blocking the binding from this perfectly fine json string and how can I get it to not do it? I have complete control over the structure and creation of the json.
Edit
I tried to change the Question.TemporaryExtendedProperties type to List<KeyValuePair<string, List<QuestionExtendedProp>>>
but that didn't work either. Here's the new json (which matches exactly what the System.Web.Script.Serialization.JavaScriptSerializer
object serializes!)
{
TemporaryExtendedProperties: [
{
Key: 'Options',
Value: [
{
PropKey: 'NEBRASKA',
PropVal: 'NE'
},
{
PropKey: 'DOG',
PropVal: 'CORN'
},
{
PropKey: 'MEOW???',
PropVal: 'COW'
}
]
}
]
}
It didn't work either. It is deserialized by the controller to List<blah,blah>
properly, with the number 1 (as expected), but Key
also Value
equal null
. Json.NET does a great job with this again.
Ugh.
source to share
I ended up just eliminating the need for a dictionary. The new code looks like this:
//Other half is autogenerated by EF in models folder
public partial class Question
{
public List<QuestionExtendedProp> TemporaryExtendedProperties { get; set; }
}
//Other half is autogenerated by EF in models folder
public partial class QuestionExtendedProp
{
public string DictionaryKeyValue { get; set; }
}
mvc handles this just fine. Now my controller looks like this
[HttpPost]
public JsonResult SaveQuestions(Question[] questions)
{
foreach (var q in questions)
{
//do regular question processing stuff
//20 lines later
IEnumerable<IGrouping<string, QuestionExtendedProp>> ExtendedPropGroups = q.TemporaryExtendedProperties.GroupBy(x => x.DictionaryKeyValue);
foreach (IGrouping<string, QuestionExtendedProp> group in ExtendedPropGroups)
{
string groupKey = group.Key;
foreach (var qexp in group)
{
//do things here
}
}
}
//rest of the stuff now that I've processed my extended properties...properly
return Utility.SaveQuestions(questions);
}
source to share