1

In the following snippet I do not understand the difference between the code underneath the "//this fails", and the code under "//this works" (which is provided as boilerplate code when creating an Azure function.) NOTE: I realize that the cast to object isn't necessary, BUT ReadAsAsync returns object....

public static class FunctionTest
{
    [FunctionName("TestFunction")]
    public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)]HttpRequestMessage req, TraceWriter log)
    {
        log.Info("C# HTTP trigger function processed a request.");

        // parse query parameter
        string name = req.GetQueryNameValuePairs()
          .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
          .Value;

        //if nothing in the query parameter - lets' look into the body
        if (name == null)
        {
            //this fails
            dynamic abc = (object) @"{""name"":""test""}";
            string test = abc?.name;

            // this works
            dynamic data = await req.Content.ReadAsAsync<object>();
            name = data?.name;
        }

        return name == null
          ? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
          : req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
    }
}
3
  • 1
    And what is error message? Commented May 10, 2018 at 0:27
  • Error message: Anonymously Hosted DynamicMethods Assembly: 'string' does not contain a definition for 'name'. Commented May 10, 2018 at 0:29
  • 1
    And that is correct. The string is not json (or xml or yaml ...). Commented May 10, 2018 at 0:31

1 Answer 1

3

The first line:

dynamic abc = (object) @"{""name"":""test""}";

will take a string value and cast it into an object. That doesn't mean that it will treat the string as JSON and make a new dynamic object with a name property. It's still a string and the contents don't matter.

The second line however:

dynamic data = await req.Content.ReadAsAsync<object>();

calls the ReadAsAsync method with a generic type of object. This actually gives you a JObject cast as an object with various properties meaning that you could do this:

name = data["name"];

And because it is dynamic, that effectively translates your code into the above. However, almost every time I see dynamic, it's a code smell and this is no difference. Instead make a concrete class with the right properties and use that. That way you will have compile time type checking instead of relying on the dynamic object. For example:

public class Foo    {
    public string Name { get; set; }
}

And use it like this:

Foo data = await req.Content.ReadAsAsync<Foo>();
Sign up to request clarification or add additional context in comments.

5 Comments

I get what you are saying, but I disagree that ReadAsAsync is really a JObject. JObject is an object defined by Newtonsoft, and hence I sure the .Net framework would not cast that to Object, which then works with dynamic. Do you have any reference documentation that actually says its returning a Jobject??
Your RIGHT! ? data.GetType() on the field that was returned from ReadAsAsync!!! {Name = "JObject" FullName = "Newtonsoft.Json.Linq.JObject"}
Newtonsoft had been part of the MVC template for many years now.
so why return it as object? why not return it as a jobject?
Your code is responsible for specifying it as an object.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.