RestSharp and JSON.NET: how to get Content-Type: application/json and properly formatted JSON Body
When I'm in C# land I like to use the RestSharp library to make interacting with REST interfaces more straightforward. It is a pretty good library which has worked reliably in the half dozen or so projects I've used it in over the last couple of years.
One thing that I keep forgetting (and the purpose behind this article) is how to get RestSharp to send a Content-Type header of application/json and format the JSON in the bctly. Hopefully I'll be able to remember a bit better after doing some documentation here.
References
- RestSharp [restsharp.org]
- RestSharp JSON Parameter Posting [stackoverflow.com]
- Set 'Content-Type' header using RestSharp [stackoverflow.com]
- Split between RestSharp and JSON.NET [groups.google.com]
- How to add text to request body in RestSharp [stackoverflow.com]
- Missing RestClient.JsonSerializer property [groups.google.com]
- RestSharp Readme that isn't updated [github.com/restsharp]
- Newtonsoft JSON.NET [james.newtonking.com]
- Wireshark Network Protocol Analyzer [wireshark.org]
The Problem
When I setup a simple RestSharp Client and request and set it in motion, I see in WireShark that the request's content-type header sometimes ends up being set to application/x-www-form-urlencoded even after i set the RequestFormat to DataFormat.Json.
Also, it seems like the JSON data in the Request's body gets double-escaped or double-serialized sometimes when I'm working with JSON.NET objects and using the .AddBody method to populate the body of the RestRequest.
Most of the time something like this works for basic cases:
using RestSharp; // RestSharp dependency
/*
* Setup a RestRequest that should go out as content-type: application/json
*/
RestRequest Request = new RestRequest("/authorize");
Request.RequestFormat = DataFormat.Json;
Request.Method = Method.POST;
Request.AddBody(new { Username="Admin", Password="SomeEasilyGuessablePassword" });
/*
* RestClient that executes the request
* In RestSharp, the Request can specify a refinement URL
* That is why in the request above you see '/authorize'
* The full url ends up being: http://192.168.78.135/authorize
*/
RestClient Client = new RestClient("http://192.168.78.135/webapp");
var resp = Client.Execute(Request);
One Possible Solution
So, what is going on? It looks like RestSharp is trying to guess they content type based on what is in the request body. I need to pass in something that is obviously JSON for it to change its content-type header.
The best solution that I have found is to use NewtonSoft's JSON.NET and setup a JObject (Dynamic JSON Object) then add the JSON String from the JOBject as a Parameter in RestSharp:
using RestSharp; // RestSharp dependency
using Newtonsoft.Json.Linq; // JSON.NET
/*
* Setup a JSON Object which has 2 properties: Username and Password
* This object will be what is sent in the Request Body
*/
JObject AuthRequest = new JObject();
AuthRequest.Add("Username", "Admin");
AuthRequest.Add("Password", "SomeEasilyGuessablePassword");
/*
* Setup a RestRequest that holds the URL stub and is configured
* to send the Request Body as JSON
*
* We use the .AddParameter method to add our JSON in a way that
* does not induce double-serializing or excess escaping
*/
RestRequest Request = new RestRequest("/authorize/", Method.POST);
Request.RequestFormat = DataFormat.Json;
Request.AddParameter("text/json", AuthRequest.ToString(), ParameterType.RequestBody);
/*
* Setup a RestClient to execute the request and
* gather the response
*/
RestClient Client = new RestClient("http://192.168.78.135/webapp");
IRestResponse Response = Client.Execute(Request);
When I use this method I can see in WireShark that the content-type is set to Content-Type: application/json. I can also see that the data in the Request Body is properly formatted JSON.