So I'm trying to put together some very simple and elegant code samples to help people use my API. The latest language I'm tackling is C#.
I think the IETF OAuth2.0 standard I read implies the HTTP request Content-Type must be "application/x-www-form-urlencoded". The Django API server I have, currently seems to only support this Content-Type (for the OAuth resource). The other languages POST content this way by default!
After extensive research and several experiments I am wondering if I have missed something fundamental. Surely there would be a helpful library OR technique to create the ...urlencoded string OR at least someone else must have run into this???
I will outline some of the best solution I have so far bellow, but it just seems wrong.
Also from a bunch of internet browsing I figured I would use the HttpClient library. I like the fact that it uses the async model, which perhaps will be more useful for any developers using WPF or XAML or Windows 8 apps. It also works well for Consoles and Forms.
I use the Newtonsoft Json.Net library for serialization. First of all I create a POCO of the authorization strings. Then I serialize it to JSON, then to key/value pairs, then iterate through the key/value pairs catenating with the required '=' and '&' chars, then UTF-8, then escape the spaces etc.
//Setup HTTP request
HttpClient httpRequest = new HttpClient();
httpRequest.DefaultRequestHeaders.Add("Accept", "application/json");
string urlBase = "https://__secret__/api/v1/";
HttpResponseMessage msg = new HttpResponseMessage();
//POST to oauth to get token (must be sent as "application/x-www-form-urlencoded")
OAuthConfig oAuthCredentials = new OAuthConfig { client_id = client_id, client_secret = secret, username = "__secret__", password = "__secret__", grant_type = "__secret__" };
string jsonString = JsonConvert.SerializeObject(oAuthCredentials); //convert to JSON
Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString); //convert to key/value pairs
string urlEncodedData = ConvertToFormUrlEncodedFormat(values);
HttpContent payload = new StringContent(urlEncodedData, Encoding.UTF8, "application/x-www-form-urlencoded");
msg = httpRequest.PostAsync(urlBase + "oauth/access_token/", payload).Result;
string responseBodyAsText = msg.Content.ReadAsStringAsync().Result;
Console.WriteLine(responseBodyAsText);
Other options I could think of were...
Reflection, however digging into reflection in a code sample seems a bit manic.
It turns out that other than the OAuth setup, the rest of the API supports JSON type POSTs. So I guess I could write a function to walk through the oAuthConfig model and catenate a string, since that POCO model is unlikely to change and is the only model which requires urlEncoding that I can anticipate. That would save us from the slightly confusing use of the Dictionary. The use of the dictionary and then iterating is more generic, however perhaps a bit OTT.
I figure most of the time people will be using JSON, so showing how that might happen is useful.
In general it seems quite hard to serialize a POCO model to a string and/or to a urlEncoded string.
Questions
- does OAuth mandate urlencoded, could you convert server-side?
- is HttpClient the best choice, does async matter?
- is there a better simpler way to serialize a POCO to ...form-urlencoded?
Thanks for any useful comments you may have.