When submitting a JSON body to an MVC application I get the following exception during binding:
An item with the same key has already been added. This happens when a HTTP body has 2+ JSON properties that rely on case sensitivity for uniqueness. E.g.
{ "foo":1, "FOO":2 } The Content-Type must also be specified as application\json for the exception to occur.
I am not really sure what to do to stop this from happening. I tried a custom IModelBinder but this occurs before IModelBinder.BindModel(...) is even called. This all seems to happen in standard framework code before the request gets passed to me.
Full stack trace:
System.ArgumentException: An item with the same key has already been added. at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at System.Web.Mvc.JsonValueProviderFactory.AddToBackingStore(EntryLimitedDictionary backingStore, String prefix, Object value) at System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext controllerContext) at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext) at System.Web.Mvc.ControllerBase.get_ValueProvider() at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass21.<BeginInvokeAction>b__19(AsyncCallback asyncCallback, Object asyncState) How do I prevent this from occuring given that the JSON payload is perfectly valid?
Edit:
I've read a little more and I now believe the problem is in the behaviour of the default IValueProvider rather than the binder. I think if a content type of application\json is specified then the value provider is automatically parsing the JSON properties into a (case insensitive) dictionary for use by the ModelBinder afterwards. This makes more sense given the stack trace I had.
I am still not 100% sure how to accommodate for this. Is writing a custom IValueProvider for this controller the only choice here?
DefaultModelBinderis not case sensitive. What you are doing is creating an object with 2 properties with identical names which is not valid when binding (try creating a model with 2 identical properties - it wont compile). Are you trying to post back a collection?