9

My ASP.NET Core endpoint accepts a JSON form as its input and calls a method that expects a dynamic argument. I am attempting to call the method like this:

[HttpPost]
public IActionResult InitializeAction([FromBody] dynamic jsonData)
{
    return this.Ok(this.MyMethod(jsonData));
}

When I POST the JSON {"test": "value"} to this method, I would expect identical behavior to doing the following:

[HttpPost]
public IActionResult InitializeAction([FromBody] dynamic jsonData)
{
    return this.Ok(this.MyMethod(new {test = "value"}));
}

However, the JSON value retrieved using the [FromBody] parameter does not get converted to a standard .NET dynamic argument, and is instead a JsonDocument or JsonElement or something along those lines.

How do I receive or serialize the JSON from the HTTP Post as a .NET dynamic object?

1
  • I am aware that I can use dynamic data = JsonConvert.DeserializeObject<dynamic>(jsonData.ToString()) to get what I am looking for. Is there a way to get my intended result without first converting the jsonData argument to a string, or is this the right answer? Commented Aug 4, 2020 at 22:07

2 Answers 2

14

The incoming JSON body can be converted to a dynamic object by using JsonConvert.DeserializeObject on the JSON string.

[HttpPost]
public IActionResult InitializeAction([FromBody] dynamic jsonData)
{
    dynamic data = JsonConvert.DeserializeObject<dynamic>(jsonData.ToString());
    return this.Ok(this.MyMethod(data));
}
Sign up to request clarification or add additional context in comments.

2 Comments

I'd stay away from dynamic as much as possible especially in this case because you can use JObject or ExpandoObject both of which are better suited for this case @MichaelWang 's solution is better
@mare This question is not about what data type is best for processing JSON. I needed to pass a dynamic object to an existing library and the data I needed to pass was formatted as JSON. I agree that using another data type would be better if I was doing any further processing on the data, but I am not.
9

UPDATE 31/07/2020

If convert object to ExpandoObject , you can access test directly.

    [HttpPost]
    [Route("/init")]
    public IActionResult Init([FromBody] dynamic jsonData)
    {
        var converter = new ExpandoObjectConverter();
        var exObjExpandoObject = JsonConvert.DeserializeObject<ExpandoObject>(jsonData.ToString(), converter) as dynamic;

        return this.Ok(this.MyMethod(exObjExpandoObject));
    }

    public string MyMethod(dynamic obj)
    {
        return obj.test;
    }

enter image description here

If use object , you need to get value by GetProperty.

    [HttpPost]
    [Route("/init2")]
    public IActionResult InitializeAction([FromBody] dynamic jsonData)
    {
        return this.Ok(this.MyMethod2(jsonData));
    }

    public string MyMethod2(dynamic obj)
    {
        JsonElement value = obj.GetProperty("test");
        return value.ToString();
    }

enter image description here





The ExpandoObject is a convenience type that allows setting and retrieving dynamic members. It implements IDynamicMetaObjectProvider which enables sharing instances between languages in the DLR. Because it implements IDictionary and IEnumerable, it works with types from the CLR. This allows an instance of the ExpandoObject to cast to IDictionary.

To use the ExpandoObject with an arbitrary JSON, you can write the following program:

    [HttpPost]
    [Route("/init")]
    public IActionResult InitializeAction([FromBody] dynamic jsonData)
    {
        var converter = new ExpandoObjectConverter();
        var exObj = JsonConvert.DeserializeObject<ExpandoObject>(jsonData.ToString(), converter);

        Debug.WriteLine($"exObj.test = {exObj?.test}, type of {exObj?.test.GetType()}") as dynamic;

        return this.Ok(exObj.test);
    }

Screenshots of Test:

enter image description here

enter image description here

Reference
Working with the Dynamic Type in C#

6 Comments

Interestingly, I can do the same thing more simply using dynamic data = JsonConvert.DeserializeObject<dynamic>(jsonData.ToString()). But is doing a dual conversion of the JSON value from the POST to a string and then to a dynamic object really the best way to achieve this result?
ExpandoObject enables you to add and delete members of its instances at run time and also to set and get values of these members. It supports dynamic binding, which enables you to use standard syntax like exObj.test
Those are nice features, but I do not need the functionality of ExpandoObject, as once my .NET Core endpoint converts the incoming JSON data, it passes it to a method from an existing .NET library that only needs a dynamic object. I will not be accessing or manipulating the converted result in my own code.
string jsonData = "{\"test\":\"value\"}"; dynamic jsonObj = JsonConvert.DeserializeObject<dynamic>(jsonData);
I wouldn't use dynamic type on incoming parameters. Rather use ExpandoObject or JObject.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.