Search code examples
c#jsondynamicasp.net-core-webapiexpandoobject

Understanding dynamic POST body parameter


I have a dotnet core Web API which accepts a body message containing JSON. I have tried writing this in various forms, eg:

[HttpPost]
public async Task<IActionResult> Create([FromBody] dynamic content)

Is difficult to retrieve the properties and does not return the properties by name.

[HttpPost]
public async Task<IActionResult> Create([FromBody] ExpandoObject content)

Is also difficult to retrieve properties from, though top level properties can be retrieved with ["details"] (though no deeper).

[HttpPost]
public async Task<IActionResult> Create([FromBody] JObject content)

This allows properties to be retrieved quite easily:

var firstName = content["contact"][0]["firstName"];
var accountName = content["generalDetails"]["accountName"];

The body message being sent is something like this and will not change in format.

{
    "details": {
        "phone": 0123456789,
        "email": "test@gmail.com",
        "county": "BF"
    },
    "admin": {
        "number": "gb12345"
    },
    "additional": {},
    "contact": [
        {
            "firstName": "Jeff",
            "lastName": "Bezos",
            "title": "Mr."
        },
        {
            "firstName": "Steve",
            "lastName": "Jobs",
            "title": "Mr."
        }
    ]
}

I want to make the body parameter dynamic (in some form) because the actual body content being sent is very large and contains many more properties than those in the example above. It seems prudent to avoid creating a large mapping/DTO class in case the design of the message does change in the future/further down the development path.

Is there a way to retrieve the properties of the dynamic or ExpandoObject values?


Solution


  • Disclaimer: When dealing with C# and typed languages, is always a better idea to create types than rely on things like dynamic, it gives you the safety and the performance that the language was designed for.


    Is difficult to retrieve the properties and does not return the properties by name.

    This is exactly how dynamic works, since the type is unknown, the IDE hints and the compiler itself cannot tell the properties that are bound to that type, so it gives you no suggestion about its properties, but you can access them anyway.

    Let's suppose that you have the following type:

    public class MyType
    {
       public int MyInt { get; set; }
       public string MyString { get; set; }
    }
    

    And then you do

    dynamic myObj = new MyType();
    

    If you type myObj. no property will be shown by your IDE, but anyway you can do, for example, Console.WriteLine(myObj.MyString) that it will work with no problem. The point here is that you need to know exactly the variable name and its type because if you try to do

    int myInt = myObj.MyInt + myObj.MyString;
    

    The compiler will accept with no problem, but you would have a problem at runtime, since the type will only be discovered during the program execution.

    In case you decide to go with a non-typed way of doing things, I would recommend to used dynamic instead of ExpandoObject and JObject, it will be a little lighter