5

I have a dynamic object (it's actually json) that I pass into my MVC WebApi controller.

The json object contains multiple lists within an anonymous object that are submitted to the controller from another application via client.PostAsJsonAsync("myapiurl", objectGraph).

What I need to do to validate the object on the MVC side, is to get the count of objects in each list. I can access the lists dynamically via mydynamicobject.mylist and individual items via mydynamicobject.mylist[index] but I can't seem to be able to get a count of mydynamicobject.mylist.

What I've tried so far:

  • LINQ extension methods - doesn't work on dynamic
  • Enumerable.Count(mydynamicobject.mylist) - can't infer type

Any other ideas? The count is actually correctly available in the dynamic object's base but obviously not accessible as a property. Help!

This works now:

// This is a MVC/WebApi method
public dynamic Post(dynamic mydynamicobject)

if (((ICollection)mydynamicobject.mylist).Count == 0)
{
// do something
}

The code that sends the dynamic object (different app):

HttpClient client = new HttpClient();  
client.DefaultRequestHeaders.Accept.Add
  (new MediaTypeWithQualityHeaderValue("application/json")); 

var objectGraph = new { mylist = new { Id = 1 }, mylist2 = new { Name = "ABC" } }; 
var r = client.PostAsJsonAsync("api/mycontroller", objectGraph).Result;
tereško
  • 58,060
  • 25
  • 98
  • 150
Alex
  • 75,813
  • 86
  • 255
  • 348
  • 1
    At what point does `mydynamicobject.mylist` fail - compile-time or execution time? – Jon Skeet Nov 29 '12 at 20:42
  • I only can't get to the count of the list within the dynamic object. The failure depends on what I try. Enumerable.Count will say that it can't infer the type and to specify it explicitly. – Alex Nov 29 '12 at 20:44
  • Sorry, I meant with `Enumerable.Count` - is the error at execution time, or compile time? What *is* the execution-time type of `mydynamicobject.mylist`? – Jon Skeet Nov 29 '12 at 20:46
  • That's at execution time. Not sure what the type would be considering that the object is dynamic. At creation time it's a simple list in an anonymous type (e.g. new x { new a { a1 = 1 }, new b { b1 = 1 } }). – Alex Nov 29 '12 at 20:51
  • That code wouldn't compile - if you could produce a short but *complete* example, it would make it much easier to make sure we gave you something that worked. – Jon Skeet Nov 29 '12 at 20:53
  • @JonSkeet Looking forward to your clarification as to why it works this way in a minute. (At the moment in a Ruby/Javascript project at work, so i'm out of C# practice) – Chris Pfohl Nov 29 '12 at 20:55
  • 1
    @Alex: `mylist` isn't a list herre - it's just an object with a single `Id` property. I'm surprised that works at all, in terms of casting it to `ICollection`... – Jon Skeet Nov 29 '12 at 21:05
  • Indeed, are you sure that this is the JSON you are posting? Because it shouldn't work at all, since `mylist` is not a list. Also, can you try to remove the cast to `ICollection` and check if `mydynamicobject.mylist.Count == 0` works for you? The cast seems to be redundant in this case. – Paolo Moretti Nov 29 '12 at 21:14
  • Yes, that should be JSON. The `mydynamicobject.mylist.Count` doesn't work (it returns null). You are right in that my test program above wasn't actually a list; I've changed that and made it a real list. The ICollection code works as before. – Alex Nov 29 '12 at 21:16
  • Looks like this now: `var objectGraph = new { mylist = new { mylistobject1= new { Id = 1 }, mylistobject2 = new { Id = 2 } }, (...)` – Alex Nov 29 '12 at 21:21

1 Answers1

11

If they are arrays, I believe you're looking for their Length property.

mydynamicobject.mylist.Length

Alternatively, I think you might be able to get away with casting mydynamicobject.mylist to an IEnumerable and then hand it to IEnueramble.Count like so:

IEnumerable.Count((IEnumerable)mydynamicobject.mylist);

you could also do as Paolo mentioned:

((ICollection)mydynamicobject.mylist).Count

Although I can't take credit for that one.

Chris Pfohl
  • 18,220
  • 9
  • 68
  • 111
  • 1
    You mean `ICollection.Count` – Paolo Moretti Nov 29 '12 at 20:45
  • I'm sorry, I wasn't clear enough. You can either try to cast it to `ICollection` and then check for [`ICollection.Count`](http://msdn.microsoft.com/en-us/library/system.collections.icollection.count.aspx), or cast it to `IEnumerable` and use the LINQ extension method [`Enumerable.Count`](http://msdn.microsoft.com/en-us/library/bb535181.aspx) – Paolo Moretti Nov 29 '12 at 20:50
  • I was able to cast it to ICollection. Seems a little ugly-ish code, but at least it works. Thank you! – Alex Nov 29 '12 at 20:51
  • @JonSkeet would far more "ept" at explaining why the compiler and dynamic behaves this way. I'd have to go dig out my copy of C# in Depth...and that would almost be like stealing Jon's answer. – Chris Pfohl Nov 29 '12 at 20:55