I had such a problem with this as well. I was posting JSON to an action, yet my JsonProperty names were ignored. Thus, my model properties were always empty.
public class MyModel
{
[JsonProperty(PropertyName = "prop1")]
public int Property1 { get; set; }
[JsonProperty(PropertyName = "prop2")]
public int Property2 { get; set; }
[JsonProperty(PropertyName = "prop3")]
public int Property3 { get; set; }
public int Foo { get; set; }
}
I am posting to an action using this custom jquery function:
(function ($) {
$.postJSON = function (url, data, dataType) {
var o = {
url: url,
type: 'POST',
contentType: 'application/json; charset=utf-8'
};
if (data !== undefined)
o.data = JSON.stringify(data);
if (dataType !== undefined)
o.dataType = dataType;
return $.ajax(o);
};
}(jQuery));
And I call it like this:
data = {
prop1: 1,
prop2: 2,
prop3: 3,
foo: 3,
};
$.postJSON('/Controller/MyAction', data, 'json')
.success(function (response) {
...do whatever with the JSON I got back
});
Unfortunately, only foo was ever getting bound (odd, since the case is not the same, but I guess the default modelbinder isn't case-sensitive)
[HttpPost]
public JsonNetResult MyAction(MyModel model)
{
...
}
The solution ended up being rather simple
I just implemented a generic version of Dejan's model binder which works very nicely for me. It could probably use some dummy checks (like making sure the request is actually application/json), but it's doing the trick right now.
internal class JsonNetModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
controllerContext.HttpContext.Request.InputStream.Position = 0;
var stream = controllerContext.RequestContext.HttpContext.Request.InputStream;
var readStream = new StreamReader(stream, Encoding.UTF8);
var json = readStream.ReadToEnd();
return JsonConvert.DeserializeObject(json, bindingContext.ModelType);
}
}
When I want to use it on a specific action, I simply tell it that I want to use my custom Json.Net model binder instead:
[HttpPost]
public JsonNetResult MyAction([ModelBinder(typeof(JsonNetModelBinder))] MyModel model)
{
...
}
Now my [JsonProperty(PropertyName = "")] attributes are no longer ignored on MyModel and everything is bound correctly!