Skip to content

Instantly share code, notes, and snippets.

@dhlavaty
Created January 2, 2013 09:54
Show Gist options
  • Save dhlavaty/4433398 to your computer and use it in GitHub Desktop.
Save dhlavaty/4433398 to your computer and use it in GitHub Desktop.
Simplest method to do a REST API calls in c# with basic .NET classes (no external library needed). I use it when communicationg with Recurly.com REST services.
/*
Simplest method to do a REST API calls in c# with basic .NET classes.
I use it when communicationg with Recurly.com REST services.
*/
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Transactions;
using System.Web.Mvc;
using System.Xml;
/// <summary>
/// Helping class, that solves problem that Microsoft has done. See remarks.
/// </summary>
/// <remarks>
/// 1. When you use <see cref="System.Net.WebClient"/>, you cannot get response status (200 - OK, 404 - Not Found, ...)
///
/// 2. When you use <see cref="System.Net.WebRequest"/>, you cannot change HTTP headers before sending request
///
/// 3. Use <see cref="System.Net.HttpWebRequest"/> directly is not possible.
///
/// Solution:
///
/// Microsoft hase done a "great job" again. Most useful method <see cref="System.Net.WebClient.GetWebRequest"/>
/// is <c>protected</c>. So we must use this class as a hack.
/// </remarks>
public class BetterWebClient : System.Net.WebClient
{
/// <summary>
/// See <see cref="System.Net.WebRequest.GetWebRequest"/>
/// </summary>
/// <param name="address">See <see cref="System.Net.WebRequest.GetWebRequest"/></param>
/// <returns>See <see cref="System.Net.WebRequest.GetWebRequest"/></returns>
public virtual System.Net.WebRequest GetWebRequestX(Uri address)
{
return this.GetWebRequest(address);
}
}
public class RestApi
{
/// <summary>
/// Makes a REST API call (I'm using it with Recurly.com service)
/// </summary>
/// <remarks>
/// It will return either a response from a REST API call.
/// If any error was during comunication, this method returns empty string.
/// </remarks>
/// <param name="url">URL to fetch</param>
/// <returns>Returns a string, representing XML of the object.</returns>
/// <param name="method"><see cref="System.Net.WebRequestMethods.Http"/></param>
public string Fetch(string url, string method = System.Net.WebRequestMethods.Http.Get, string xmlToSend = "")
{
DateTime startedOnUtc = DateTime.UtcNow;
string responseData = null;
string responseHeaders = null;
int responseStatusCode = 0;
try {
BetterWebClient webClient = new BetterWebClient();
webClient.Proxy = null;
webClient.Headers.Add(System.Net.HttpRequestHeader.Accept, "application/xml");
// You can use BASIC authorization like so (you must implement your own Recurly.ApiKeyBase64String):
webClient.Headers.Add(System.Net.HttpRequestHeader.Authorization, "Basic " + Recurly.ApiKeyBase64String);
if (false == String.IsNullOrWhiteSpace(xmlToSend))
{
webClient.Headers.Add(System.Net.HttpRequestHeader.ContentType, "application/xml; charset=utf-8");
}
var webRequest = webClient.GetWebRequestX(new Uri(url));
webRequest.Method = method;
if (false == String.IsNullOrWhiteSpace(xmlToSend))
{
using (StreamWriter writer = new StreamWriter(webRequest.GetRequestStream(), Encoding.UTF8))
{
writer.WriteLine(xmlToSend);
}
}
else
{
if (method == System.Net.WebRequestMethods.Http.Put)
{
webRequest.ContentLength = 0; // ContentLength == 0 is required for PUT requests
}
}
using (System.Net.WebResponse response = webRequest.GetResponse())
{
ProcessResponse(response, out responseData, out responseHeaders, out responseStatusCode);
}
}
catch (System.Net.WebException ex)
{
using (ex.Response)
{
ProcessResponse(ex.Response, out responseData, out responseHeaders, out responseStatusCode);
}
responseData = "<!-- " + ex.Message + " -->\r\n\r\n" + responseData;
}
finally
{
/* YOU CAN (you should) LOG ALL YOUR COMMUNICATION WITH SERVER HERE like this:
var log = Log.CreateCommunicationLogObject();
log.StartedOnUtc = startedOnUtc;
log.FinishedOnUtc = DateTime.UtcNow;
log.RequestMethod = method;
log.RequestData = String.IsNullOrWhiteSpace(xmlToSend) ? null : xmlToSend;
log.RequestUrl = url;
log.ResponseData = responseData;
log.ResponseStatusCode = responseStatusCode;
log.ResponseHeaders = responseHeaders;
Log.Save();
*/
}
if (responseStatusCode >= 200 && responseStatusCode < 300)
{
// All 2xx HTTP statuses are OK
return responseData;
}
return String.Empty;
}
private static void ProcessResponse(System.Net.WebResponse response, out string recurlyResponse, out string responseHeaders, out int responseStatusCode)
{
recurlyResponse = responseHeaders = String.Empty;
responseStatusCode = 0;
using (var responseStream = response.GetResponseStream())
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(responseStream, Encoding.UTF8))
{
recurlyResponse = sr.ReadToEnd();
}
}
responseHeaders = response.Headers.ToString();
var httpWebResponse = response as System.Net.HttpWebResponse;
if (httpWebResponse != null)
{
responseStatusCode = (int)httpWebResponse.StatusCode;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment