1

I'm trying to do a POST request with a JSON object as the body. The JSON object contains nested types that are predefined models in a library I am using, but when I use [FromBody] attribute only the root model gets binded while the nested models are null.

I've tried without using the [FromBody] attribute, but it also only binds the root level model.

POST Object Example: Foo would be a model that takes a Bar object. Bar would be a model that has properties name and firstLetter.

{
  "foo": [
    {
      "bar": {
        "name": "bar",
        "firstLetter": "b"
      }
    },
    {
      "bar": {
        "name": "bar1",
        "firstLetter": "b"
      }
    }
  ]
}

The Controller route looks like:

[HttpPost("example-route")]
public async Task<ActionResult<string>> Static([FromBody]Request request){
 //Some Action
}

The Request class would look like:

//Request class
public class Request{
  [JsonConstructor]
  public Request(Bar b){
    this.Bar = b;
  }  

  public List<Bar> Bar = { get; set; }
}

//Bar class
public class Bar {

  public Bar(string name, string firstLetter){
     this.Name = name;
     this.FirstLetter = firstLetter;
  }

  public string Name { get; set; }
  public string FirstLetter { get; set; }

}

When I'd call this, Bar will get assigned, but its properties of Name and FirstLetter will still be null.

Edit:I'll add the List in the example, but I may have oversimplified.The actual request looks more like:

{
    "prop1": "field1",
    "prop2": "4",
    "prop3": {
        "userId": "2",
        "customerId": "4",
        "type": {
            "userType": "Manager",
            "contactInfo": [
                {
                    "system": "email",
                    "value": "test@test.com"
                },
                {
                    "system": "phone",
                    "value": "555-555-5555"
                }
            ]
        }
    }
}

Where prop1, prop2, prop3, type and contactInfo are all models defined in a library I'm using. I'm trying to get the ContactInfo object, and so far it can assigns two objects to ContactInfo when I step through, but their properties (system and value) are both null. I checked spelling and casing, but no issues there.

avenmia
  • 2,015
  • 4
  • 25
  • 49

1 Answers1

3

Your Request class must match exactly what you have in the JSON, and take care ot the nestings:

public class Request
{
  public List<BarContainer> foo {get; set;}
  // Your constructor should initialize this list.
}

public class BarContainer
{
  public Bar bar {get; set;}
}

public class Bar
{
  [JsonProperty("name")]
  public string Name { get; set;}
  [JsonProperty("firstLetter")]
  public string FirstLetter { get; set;}
}

NOTE: the deserialization is case sensitive, so you need to use the exacty names in the JSON, bar, foo, name, firstLetter or use attributes or configuration to support the different casing of the property names:

JotaBe
  • 38,030
  • 8
  • 98
  • 117
  • If the library I'm using doesn't have the JSON property attribute in its models, then it won't bind correct? – avenmia May 09 '19 at 15:07
  • I suppose you're using JSON.NET (the deafult .NET serializer) and the JSON properties and the object properties names must have the same case, or use the offered alternatives. – JotaBe May 09 '19 at 15:12