PowerShell v3 added some very useful web cmdlets that make working with web services and pages much easier. In previous versions, it was common practice to use the WebClient class but this wasn’t straight forward in the least bit. Recently, I’ve been working with ASP.NET MVC4 Web API and found that the new additions to PowerShell to be extremely handy. Here are a couple techniques to make working with the cmdlets against Web API a pleasant experience.
The Invoke-RestMethod Cmdlet
The Invoke-RestMethod cmdlet is very easy to use. That’s my favorite part. It’s much easier than using Fiddler or Curl and it’s installed right out of the box. I did another blog post about how to use the cmdlet to access Reddit APIs and pull down the hot posts in a Subreddit. Aside from invoking the GET verb, the Invoke-RestMethod cmdlet has a Method parameter that accepts any of the HTTP verbs as fodder. This enables for PUTs, POSTs, DELETEs oh my!.
A Simple Web API
Assume that I have a simple CodeMonkey class with a couple basic properties.
My Web API is also very simple. It exposes a GET, PUT, POST and DELETE.
Accessing Code Monkeys
By default, the Invoke-RestMethod uses the GET verb and will retrieve entities from the API. Invoke-RestMethod also converts JSON directly into PowerShell objects that can be piped to all your favorite formatting and processing cmdlets.
Just as easily, we can grab a single monkey by tacking on the Id in a very RESTful manner.
Since the objects coming back to the pipeline are PSCustomObjects, we have the ability to use cmdlets like Select-Object to process the returned data. There is a caveat when piping collections of objects returned by this cmdlet. You may notice that using cmdlets like Select-Object and Where-Object don’t behave as expected. You’ll have to use the GetEnumerator method of the list that is returned in order to actually access the inner objects and process them as expected.
Posting New Code Monkeys
In addition to getting entities, the Invoke-RestMethod cmdlet can easily modify them as well. Since the Invoke-RestMethod cmdlet can invoke PUT and POST requests, it is necessary to serialize data in a way that the Web API will find meaningful. To accomplish this, we can use a combination of PowerShell hashtables and the new ConvertTo-Json cmdlet. It’s as simple as creating a hashtable that matches your data transfer object, converting it to a JSON string and passing it to the Body parameter of Invoke-RestMethod.
While using Web API, it’s important to use the correct content type. I struggled quite a bit with this in the beginning. If you don’t set the content type to application/json, the request will have an application/x-www-form-urlencoded content type and the Web API won’t know what to do with it. I saw some very strange behavior. Null CodeMonkeys or CodeMonkeys without properties set!
Updating Existing Code Monkeys
Just like when POSTing new code monkeys to the API, we can also PUT, or update, existing code monkeys. This is accomplish almost exactly the same way as a POST with only a change to the Method and the URI that we specify.
Removing Code Monkeys
Equally as easy is deleting existing monkeys. No need for a body here. We only need to specify the Delete method and the Id.
Nested Object Support
Web API, Invoke-RestMethod and ConvertTo-Json support nested objects. Keep in mind that the ConvertTo-Json and ConvertFrom-Json cmdlets have a Depth property. By default, these cmdlets will serialize 3 levels deep. To create nested objects, just create a hash table that matches the format of your data transfer object and convert it to JSON. Web API will happily deserialize it if it matches the new DTO. Also notice the support for arrays of objects.
Why should I use this to test my Code Monkeys?
This is just another tool in the toolbox for developers or admins alike to easily access web services. What I find especially appealing is the close similarities in the JSON and PowerShell hashtable syntax. It really helped me to visualize how my data would be sent across the wire. Being in PowerShell, I found it extremely flexible to quickly modify the data or request. I haven’t found an easier way to consume a web service!
So what do you think? Could you use this technique to conquer your Code Monkeys?