2

I am attempting to make a PUT call to my Web API. I have set the following up in the WebApiConfig.cs to handle sending data back to my Web project in camel case.

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver
    = new CamelCasePropertyNamesContractResolver();

My data is coming from a row in a Kendo UI Grid. The javascript that makes the Ajax call is below:

...    
    save: function(e) {
        var dataItem = e.model;
        $.ajax({
            url: apiUrl() + "/roleLocationSecurable",
            type: 'PUT',
            headers: {
                'Authorization': 'Bearer ' + getTwtToken(),
                'LocationId': getCurrentLocation()
            },
            data: JSON.stringify(dataItem),
            dataType: 'json'
        }).done(function(data){
            //stuff when finished
        });
    }
...

The data being sent to the Web API looks like this:

"id":1,
"roleLocationId":5
"moduleId":5
...

The Action on my Web API 2.0 Controller looks like this:

[HttpPut]
[Route("roleLocationSecurable")
public IHttpActionResult UpdateRoleLocationSecurable(RoleLocationSecurableResource model)
{
    var roleLocationSecurable = Mapper.Map<RoleLocationSecurableResource, RoleLocationSecurable>(model);
    if(_roleService.UpdateRoleLocationSecurable(roleLocationSecurable))
    {
        return Ok();
    }
    return NotFound();
}

And the Model my controller is expecting has properties named like this:

public int? Id {get;set;}
public int RoleLocationId {get;set;}
public int ModuleId {get;set;}
....

What's happening is that my Ajax call is firing and the body of my PUT call includes all of the information from above, with the camel case keys. The Web API Controller is being called, but the values in my model are not populated with anything (the model is essentially blank).

The issue I think I have (and maybe I'm wrong) is that the Action on my Web API controller is expecting Pascal Case properties, and my Ajax call is sending Camel Case.

Since the CameCasePropertyNamesContractResolver is handling the serialization of data to camel case, why isn't it handling the deserialization? Is there a simple, easy way to fix this?

Any help on why the above code isn't working would be greatly appreciated.

Anna
  • 37
  • 1
  • 5
  • I forgot to mention, I went looking and found this question which is similar but was never answered: http://stackoverflow.com/questions/34364562/camel-cased-json-net-deserialization-from-web-api-request – Anna Aug 09 '16 at 20:32
  • You never mention what is actually happening. Is the passed in parameter null? Is it never reaching your method? What is actually being sent by the client, what have you found in your browsers debug console? – Igor Aug 09 '16 at 20:44
  • Good point @Igor. Post updated to include this information. – Anna Aug 09 '16 at 21:05

3 Answers3

2
services
    .AddMvc()
    .AddJsonOptions(options =>
    {
        options.SerializerSettings.ContractResolver
            = new Newtonsoft.Json.Serialization.DefaultContractResolver();
    });

Add this to your Startup.cs if you are in .Net Core project and it will keep the same as .Net class library.

Salomon Zhang
  • 1,553
  • 3
  • 23
  • 41
1

it looks like you are missing the contentType: "application/json" in your ajax call. In order for Web API to properly handle content negotiation and model binding it has to know what content type is being passed. Without telling the Web API what the content type is it is unable to map the content to the model thus showing it as null on the Action. Below is your snippet updated:

$.ajax({
    url: getApiUrl() + "/roleLocationSecurable",
    type: 'PUT',
    headers: {
        'Authorization': 'Bearer ' + getJwtToken(),
        'LocationId': getCurrentLocation()
    },
    data: dataItem,
    dataType: "json",
   **contentType: "application/json"**
})...

I was able to test this and I see a populated model.

Chad
  • 68
  • 6
1

Have you tried to annotate your model attributes with a JsonProperty. For example this:

[JsonProperty("Id")]
public int? Id {get;set;}

[JsonProperty("RoleLocationId ")]
public int RoleLocationId {get;set;}

[JsonProperty("ModuleId ")]
public int ModuleId {get;set;}

Remember to invoke this assembly: using Newtonsoft.Json;

t_plusplus
  • 4,079
  • 5
  • 45
  • 60
  • 2
    Thanks for this answer. I was hoping to find a solution without having to annotate every property on my models for updates. The accepted answer achieved this. – Anna Aug 10 '16 at 16:22
  • 1
    This is perfect for a one-off case where I can't responsibly update global serialization settings. – derekbaker783 Aug 20 '21 at 22:52