Skip to content

Instantly share code, notes, and snippets.

@michaelbartnett
Created June 1, 2011 15:11
Show Gist options
  • Save michaelbartnett/1002498 to your computer and use it in GitHub Desktop.
Save michaelbartnett/1002498 to your computer and use it in GitHub Desktop.
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;
using System.Net.Browser;
namespace RESTUtil
{
public delegate void RESTTransactionCompletedHandler(object sender, RESTTransactionCompletedArgs args);
public class RESTWebClient
{
private const int BUFFERSIZE = 1024;
private HttpWebRequest uploadStringRequest; // Request object to do the actual sending
private string uploadStringData; // Data to be sent
// Buffers for Stream.BeginRead()
private byte[] uploadStringReadbuffer;
private StringBuilder uploadStringReadResult;
// Properties for polling status after transaction completes
public bool CurrentTransActionComplete { get; private set; }
public WebHeaderCollection ResponseHeaders { get; private set; }
public HttpStatusCode ResponseStatusCode { get; private set; }
public string ResponseStatusDescription { get; private set; }
public string CurrentResponseString
{
get
{
if (uploadStringReadResult != null) {
return uploadStringReadResult.ToString();
} else {
return string.Empty;
}
}
}
// Fire when transaction is completed (byteRead == 0)
public event RESTTransactionCompletedHandler UploadStringCompleted;
// Slightly mimics WebClient api
public void UploadStringAsync(Uri address, string method, string data)
{
// Initialize buffers
uploadStringReadbuffer = new byte[BUFFERSIZE];
uploadStringReadResult = new StringBuilder();
// Enable the Client http stack
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
// Create HttpWebRequest via WebRequestCreator.ClientHttp (implied because of RegisterPrefix)
uploadStringRequest = WebRequest.Create(address) as HttpWebRequest;
// Prepare request
uploadStringRequest.Method = method;
uploadStringData = data;
// Get stream to write to
uploadStringRequest.BeginGetRequestStream(UploadStringWrite, null);
}
private void UploadStringWrite(IAsyncResult iar)
{
// Get stream to write data to
Stream s = uploadStringRequest.EndGetRequestStream(iar);
StreamWriter sw = new StreamWriter(s);
// Write data
sw.Write(uploadStringData);
sw.Close();
// Get response async
uploadStringRequest.BeginGetResponse(UploadStringRead, null);
}
private void UploadStringRead(IAsyncResult iar)
{
HttpWebResponse response = null;
try {
// **************PUT requests fail after this line**************
response = uploadStringRequest.EndGetResponse(iar) as HttpWebResponse;
} catch (WebException we) {
response = we.Response as HttpWebResponse;
} catch (Exception e) {
System.Diagnostics.Debug.WriteLine(e);
}
// Set status properties so they can be checked later
ResponseHeaders = response.Headers;
ResponseStatusCode = response.StatusCode;
ResponseStatusDescription = response.StatusDescription;
// Get the response stream to read async
var stream = response.GetResponseStream();
var reader = new StreamReader(stream);
// Begin reading asynchronously ("driver" call to recursive read method)
stream.BeginRead(uploadStringReadbuffer, 0, BUFFERSIZE, UploadStringStreamCallback, stream);
}
private void UploadStringStreamCallback(IAsyncResult result)
{
// User state is always the Stream object
var stream = result.AsyncState as Stream;
// Read bytes, decode into string with UTF8, append to StringBuilder so we can reuse the byte buffer
var bytesRead = stream.EndRead(result);
uploadStringReadResult.Append(Encoding.UTF8.GetString(uploadStringReadbuffer, 0, bytesRead));
// If we read bytes, try to read again, otherwise we've reached the end of the stream
if (bytesRead > 0) {
stream.BeginRead(uploadStringReadbuffer, 0, BUFFERSIZE, UploadStringStreamCallback, stream);
} else {
// If we're done, invoke the callback
if (UploadStringCompleted != null) {
UploadStringCompleted.Invoke(this, new RESTTransactionCompletedArgs(uploadStringReadResult.ToString(), true));
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment