3

JSON.NET deserializes it fine, but whatever mvc uses for controller parameter binding barfs hard. Can I do anything else to make this work?

The 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 gives me for this exact string (Pulled from fiddler, extras snipped for your reading pleasure)

    "TemporaryExtendedProperties":{"Options": 
        [{"PropKey":"NE","PropVal":"NEBRASKA"}, 
         {"PropKey":"CORN","PropVal":"CHILDREN OF"}, 
         {"PropKey":"COW","PropVal":"MOO"}]}

Weird deserialized values in Locals panel

Why does MVC mangle the binding from this perfectly fine json string and how can I get it to not do so? I have complete control over the json structure and creation.

Edit
I tried changing the type of Question.TemporaryExtendedProperties to List<KeyValuePair<string, List<QuestionExtendedProp>>>, but that didn't work either. Here's the new json (which matches exactly what System.Web.Script.Serialization.JavaScriptSerializer serializes an object to!)

{
   TemporaryExtendedProperties: [
      {
         Key: 'Options',
         Value: [
            {
               PropKey: 'NEBRASKA',
               PropVal: 'NE'
            },
            {
               PropKey: 'DOG',
               PropVal: 'CORN'
            },
            {
               PropKey: 'MEOW???',
               PropVal: 'COW'
            }
         ]
      }
   ]
}

That didn't work either. It's deserialized by the controller to a List<blah,blah> properly, with a count of 1 (as expected), but the Key and Value are both null. Json.NET again handles it perfectly.

Ugh.

Community
  • 1
  • 1
scaryman
  • 1,880
  • 1
  • 19
  • 30
  • It looks like your mvc view is sending back a single Question object. Is that correct? – Chris Carew Mar 28 '12 at 19:54
  • 1
    Possible duplicate: http://stackoverflow.com/questions/4710729/post-json-dictionary – StriplingWarrior Mar 28 '12 at 19:59
  • I snipped a lot of code, the view is actually returning a wrapper object that has success status, timing info, exception if it's there AND all of the newly created questions (now with their primary key IDs and some extra generated stuff) – scaryman Mar 28 '12 at 19:59
  • I tried avoiding a dictionary and instead using a list of key/value pairs, but it mangles that as well. JSON.NET again works perfectly. – scaryman Mar 28 '12 at 20:37
  • I can't tell what the problem is from your question. What exactly do you think you should see and what exactly are y ou giving it? The TemporaryExtendedProperties json you give has one key, Options, whose value is an array of objects with PropKey and PropValue properties, right? – Jason Goemaat Mar 30 '12 at 17:05
  • The problem is that mvc won't bind the incoming json to a Dictionary> (from the title). It's getting exactly the json shown in the first half of the question. I tried to be as clear as possible... – scaryman Mar 30 '12 at 18:45

1 Answers1

1

I ended up just removing 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. My controller now 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);
}
scaryman
  • 1,880
  • 1
  • 19
  • 30
  • Can you actually answer the question? Sometimes the answer is "do something else instead" – scaryman May 20 '14 at 19:56
  • Heh, I'm way too frustrated with this to spend more time on it. We were unwilling to change the DTO sooooo... I ended up using WebAPI since it uses json.net and handles the deserialization just fine. It was just disappointing because you had the most precise version of this question on SO and there was no answer :-/ I may offer a bounty for this. – Allen Rice May 20 '14 at 21:27