2

WebApi model binding fails when a property in the viewmodel inherits from Dictionary<string, string>. The same model binding works when the data type of the property is changed to just Dictionary<string, string>.

Below is an example of the binding not working.

When I submit the webpage data to the ApiController the binding will not bind the MyDictionary<string, string> ExtraData property. If I change the property to Dictionary<string, string> ExtraData property then Api controller will bind correctly. However this is not an option because the MyDictionary class has additional functionality that I need.

I have a class that inherits from Dictionary<> that looks like the one below:

public class MyDictionary<TKey, TVal> : Dictionary<TKey, TVal>
{
}

I have a class that has a property of the type MyDictionary

public class HomeModel
{
    public string Name{ get; set; }
    public MyDictionary<string, string> ExtraData { get; set; }

    public HomeModel()
    {
        ExtraData = new MyDictionary<string, string>();
    }
}

I have a ApiController like this (it does NOT bind correctly. ExtraData.Count always returns zero):

public class HomeApiController : ApiController
{
    // POST api/homeapi
    [HttpPost]
    [ActionName("Complex")]
    public string PostComplex([FromBody]HomeModel model)
    {
        return string.Format("vm.ExtraData.Count = {0}", model.ExtraData.Count);
    }
}

The html form snippet looks like this:

    <ul>
    <li>
        <input type="text" name="ExtraData[0].Key" value="Key1"/>
        <input type="text" name="ExtraData[0].Value" value="Value1"/>
    </li>
    <li>
        <input type="text" name="ExtraData[1].Key" value="Key2"/>
        <input type="text" name="ExtraData[1].Value" value="Value2"/>
    </li>
    <li>
        <input type="text" name="ExtraData[2].Key" value="Key3"/>
        <input type="text" name="ExtraData[2].Value" value="Value3"/>
    </li>
</ul>

Any ideas as to why model binding does not work with an inherited property of Dictionary<string, string>?

Data is being submitted to ApiController through a simple post as follows:

  var sendFormData = function (addr) {
            var jqxhr = $.post(addr, $('form').serialize())
                .success(function (x) {
                    alert(x);
                })
                .error(function () {
                    alert("Failure");
                });
            return false;
        };

        $("#submitWebApi").click(function () {
            $("form").submit(sendFormData('api/homeapi/complex'));
        });
Randall Hoffpauir
  • 275
  • 1
  • 4
  • 11
  • I believe you may be able to do what you want if you 'decorate' your custom dictionary along the lines of [this SO question and answer](http://stackoverflow.com/questions/11235041/custom-serialisation-of-a-dictionary-in-a-datacontract). Not sure what `DataContract` specific config you'd need to do but it should be a start. Otherwise, it may be easier to encapsulate the extra functionality as extension methods to the generic Dictionary class. – Sixto Saez Jun 11 '13 at 19:51
  • If you comment out the line in the constructor of the `HomeModel` class that initialized the dictionary does the dictionary still have no entries? is it null in this case, empty or does it contain data? – Joanna Derks Jun 11 '13 at 19:56
  • @JoannaTurban When I comment out the line in the constructor the dictionary is initialized but it still has no entries. – Randall Hoffpauir Jun 11 '13 at 21:11
  • @SixtoSaez The serialization is the reason that we have to have the custom dictionary, but it does not help in this situation. Tried the DataContract but it doesn't seem to make a difference here. – Randall Hoffpauir Jun 11 '13 at 21:24

0 Answers0