In a previous post I elaborated on the problem of magic strings in OData service queries, and gave a quick (but lacking in depth) statically typed helper solution.
A commenter mynkow left a note stating that my solution would not work with nested objects. I initially replied asking if he could give an example (as I hadn’t run into that scenario yet being a noob to OData). He didn’t get back to me, but it wasn’t long before I ran into the problem he was talking about.
If we go back to LinqPad and look again at the Netflix OData api. Let’s say we want to pull down the People, their related TitlesDirected and the TitlesDirected ScreenFormats. (No real world scenario there – just made it up because they’re related properties). The OData query (with magic strings) would look like:
(from x in People.Expand("TitlesDirected/ScreenFormats")
If you tried to take the above and translate it to my “no magic string” fix from the previous post you would get something like.
(from x in People.Expand(p => p.TitlesDirected /* Now what? dead end. /ScreenFormats*/ )
Now that the problem in my solution was apparent, and using his example as a quick guide (It wasn’t quite what I was looking for, but had the general theme). The solution became more than a few lines of code and I wanted to wrap some tests around the whole thing just to verify it was all working correctly…
ODataMuscle was born:
Sorry for the name. Just think of “Strong Typing” your OData queries and giving them a little Muscle. I threw this little project up on github since this blog is not the best place to version code and if anyone felt inclined to extend it they could easily fork it and do so.
I hacked the initial version together, and once a co-worker of mine was done with it I think he cleaned it up nicely.
This new version now supports expanding not only child properties, but grandchild properties and grandchild properties of collections. (That doesn’t seem to translate well…)
EX: our little Netflix example from above would now look like
(from x in People.Expand(p => p.TitlesDirected.Expand(p2 => p2.ScreenFormats))
Which would translate into the following query
Thanks to mynkow for the initial feedback and I hope this helps someone else…