bflemi3
bflemi3

Reputation: 6790

Web API post deserializing json result but all properties null

I've been scratching my head on this one for a few days now.

Using the angular $http service I'm posting back to an api controller passing the Movie json object. And while the correct action is hit, all of the models properties, primitives and complex, are null or default. I've used the JsonProperty attribute because the json objects properties have different names than the c# model that I need to deserialize to. I've also tried using DataContract, being sure to set UseDataContractJsonSerializer to true on app start, but that had no effect also.

I should also note that I'm using web api 2.2.

Simplified Model:

public class Movie {

    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [JsonProperty(PropertyName = "id")]
    public int Id { get; set; }

    [JsonProperty(PropertyName = "title")]
    public string Title { get; set; }

    [JsonProperty(PropertyName = "year")]
    public int Year { get; set; }

    [JsonProperty(PropertyName = "release_dates")]
    public ReleaseDates ReleaseDates { get; set; }

    [JsonProperty(PropertyName = "ratings")]
    public Ratings Ratings { get; set; }

    [JsonProperty(PropertyName = "abridged_cast")]
    public ICollection<Character> Cast { get; set; }

    [JsonProperty(PropertyName = "users")]
    public ICollection<User> Users { get; set; }
}

Action:

public async Task<HttpResponseMessage> Post(Movie movie) {
    // do stuff
}

Call from the client (in debug I can see that the movie js object is hydrated with the proper data):

$http.post('/api/usermovies', { movie : movie });

This is the content in the request being sent from angular:

{
    "movie" : {
        "id" : "12897",
        "title" : "The Matrix",
        "year" : 1999,
        "release_dates" : {
            "theater" : "1999-03-31",
            "dvd" : "1999-09-21"
        },
        "ratings" : {
            "critics_rating" : "Certified Fresh",
            "critics_score" : 87,
            "audience_rating" : "Upright",
            "audience_score" : 85
        },
        "abridged_cast" : [{
                "name" : "Keanu Reeves",
                "id" : "162654049",
                "characters" : ["Neo"]
            }, {
                "name" : "Laurence Fishburne",
                "id" : "162669090",
                "characters" : ["Morpheus"]
            }, {
                "name" : "Carrie-Anne Moss",
                "id" : "162669130",
                "characters" : ["Trinity"]
            }, {
                "name" : "Hugo Weaving",
                "id" : "162709905",
                "characters" : ["Agent Smith"]
            }, {
                "name" : "Gloria Foster",
                "id" : "364627698",
                "characters" : ["The Oracle"]
            }
        ],
        "$$hashKey" : "00C"
    }
}

Tracing doesn't really turn up anything. The modelBinder seems to be properly associating the json with the correct model...

w3wp.exe Information: 0 : Request, Method=POST, Url=http://www.moovy.com/api/usermovies, Message='http://www.moovy.com/api/usermovies'

w3wp.exe Information: 0 : Message='UserMovies', Operation=DefaultHttpControllerSelector.SelectController

w3wp.exe Information: 0 : Message='Moovy.Api.Controllers.UserMoviesController', Operation=DefaultHttpControllerActivator.Create

w3wp.exe Information: 0 : Message='Moovy.Api.Controllers.UserMoviesController', Operation=HttpControllerDescriptor.CreateController

w3wp.exe Information: 0 : Message='Selected action 'Post(Movie movie)'', Operation=ApiControllerActionSelector.SelectAction

w3wp.exe Information: 0 : Message='Value read='Moovy.Models.Movie'', Operation=JsonMediaTypeFormatter.ReadFromStreamAsync

w3wp.exe Information: 0 : Message='Parameter 'movie' bound to the value 'Moovy.Models.Movie'', Operation=FormatterParameterBinding.ExecuteBindingAsync

w3wp.exe Information: 0 : Message='Model state is valid. Values: movie=Moovy.Models.Movie', Operation=HttpActionBinding.ExecuteBindingAsync

What to do, what to do?

Upvotes: 3

Views: 5777

Answers (2)

bflemi3
bflemi3

Reputation: 6790

I figured it out. This was because of a mistake in how I was passing the movie object in the request.

This...

$http.post('/api/usermovies', { movie : movie });

Should be changed to this...

$http.post('/api/usermovies', movie);

Deserialization from the json object with differing property names into the Movie object is working perfectly after that change.

Upvotes: 2

fuzzybear
fuzzybear

Reputation: 2405

Your class should be like this, in VS edit paste special , Paste Json as classes

public class Rootobject
{
public Movie movie { get; set; }
}

public class Movie
{
public string id { get; set; }
public string title { get; set; }
public int year { get; set; }
public Release_Dates release_dates { get; set; }
public Ratings ratings { get; set; }
public Abridged_Cast[] abridged_cast { get; set; }
public string hashKey { get; set; }
}

public class Release_Dates
{
public string theater { get; set; }
public string dvd { get; set; }
}

public class Ratings
  {
public string critics_rating { get; set; }
public int critics_score { get; set; }
public string audience_rating { get; set; }
public int audience_score { get; set; }
}

public class Abridged_Cast
{
public string name { get; set; }
public string id { get; set; }
public string[] characters { get; set; }
}

Upvotes: 0

Related Questions