Created
September 13, 2012 02:41
-
-
Save prabirshrestha/3711497 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace Api | |
| { | |
| using System; | |
| using System.Collections.Generic; | |
| using System.ComponentModel; | |
| using System.Diagnostics; | |
| using System.IO; | |
| using System.Net; | |
| using System.Threading; | |
| using System.Threading.Tasks; | |
| public class SampleApi | |
| { | |
| private const string UserAgent = "Api SDK"; | |
| private const int BufferSize = 1024 * 4; //4kb | |
| [EditorBrowsable(EditorBrowsableState.Never)] | |
| public Func<Uri, HttpWebRequestWrapper> HttpWebRequestFactory { get; set; } | |
| #if (!SILVERLIGHT || NETFX_CORE) | |
| public virtual object Api(string httpMethod, string path, object parameters, Type resultType) | |
| { | |
| Stream input; | |
| var httpHelper = PrepareRequest(httpMethod, path, parameters, resultType, out input); | |
| if (input != null) | |
| { | |
| try | |
| { | |
| using (var stream = httpHelper.OpenWrite()) | |
| { | |
| var buffer = new byte[BufferSize]; | |
| int bytesRead; | |
| while (true) | |
| { | |
| bytesRead = input.Read(buffer, 0, buffer.Length); | |
| if (bytesRead <= 0) | |
| break; | |
| stream.Write(buffer, 0, bytesRead); | |
| stream.Flush(); | |
| } | |
| } | |
| } | |
| catch (WebExceptionWrapper ex) | |
| { | |
| if (ex.GetResponse() == null) throw; | |
| } | |
| finally | |
| { | |
| input.Dispose(); | |
| } | |
| } | |
| Stream responseStream = null; | |
| object result = null; | |
| bool read = false; | |
| try | |
| { | |
| responseStream = httpHelper.OpenRead(); | |
| read = true; | |
| } | |
| catch (WebExceptionWrapper ex) | |
| { | |
| var response = ex.GetResponse(); | |
| if (response == null) throw; | |
| if (response.StatusCode != HttpStatusCode.NotModified) | |
| responseStream = httpHelper.OpenRead(); | |
| read = true; | |
| } | |
| finally | |
| { | |
| if (read) | |
| result = ProcessResponse(httpHelper, responseStream, resultType); | |
| } | |
| return result; | |
| } | |
| #endif | |
| public virtual IAsyncResult BeginApi(string httpMethod, string path, object parameters, Type resultType, object userState) | |
| { | |
| throw new NotImplementedException(); | |
| } | |
| public virtual object EndApi(IAsyncResult asyncResult) | |
| { | |
| throw new NotImplementedException(); | |
| } | |
| //public virtual Task<object> ApiAsync(string httpMethod, string path, object parameters, Type resultType, object userState, CancellationToken cancellationToken) | |
| //{ | |
| // Stream input; | |
| // var httpHelper = PrepareRequest(httpMethod, path, parameters, resultType, out input); | |
| // Task<object> task = null; | |
| // Task writeTask; | |
| // if (input == null) | |
| // { | |
| // var tcs = new TaskCompletionSource<object>(); | |
| // tcs.TrySetResult(null); | |
| // writeTask = tcs.Task; | |
| // } | |
| // else | |
| // { | |
| // writeTask = httpHelper | |
| // .OpenWriteTaskAsync(cancellationToken) | |
| // .Then(writeStream => | |
| // { | |
| // using (var stream = writeStream) | |
| // { | |
| // var buffer = new byte[BufferSize]; | |
| // int bytesRead; | |
| // while (true) | |
| // { | |
| // bytesRead = input.Read(buffer, 0, buffer.Length); | |
| // if (bytesRead <= 0) | |
| // break; | |
| // stream.Write(buffer, 0, bytesRead); | |
| // stream.Flush(); | |
| // } | |
| // } | |
| // }); | |
| // writeTask = writeTask.Catch( | |
| // t => | |
| // { | |
| // if (t.IsFaulted) | |
| // { | |
| // var ex = t.Exception.GetBaseException() as WebExceptionWrapper; | |
| // if (ex.GetResponse() != null) | |
| // return true; | |
| // } | |
| // return false; | |
| // }); | |
| // writeTask = writeTask.Finally(() => input.Dispose()); | |
| // } | |
| // bool read = false; | |
| // var readTask = writeTask.Then(() => httpHelper.OpenReadTaskAsync(cancellationToken)) | |
| // .Then(() => read = true); | |
| // var catchReadTask = readTask.Catch(t => | |
| // { | |
| // var tcs = new TaskCompletionSource<bool>(); | |
| // if (t.IsFaulted) | |
| // { | |
| // var ex = t.Exception.GetBaseException() as WebExceptionWrapper; | |
| // var response = ex.GetResponse(); | |
| // if (response == null) | |
| // { | |
| // tcs.TrySetResult(false); | |
| // return tcs.Task; | |
| // } | |
| // if (response.StatusCode != HttpStatusCode.NotModified) | |
| // { | |
| // return httpHelper.OpenReadTaskAsync(cancellationToken) | |
| // .Then(() => | |
| // { | |
| // read = true; | |
| // return true; | |
| // }); | |
| // } | |
| // read = true; | |
| // } | |
| // tcs.TrySetResult(false); | |
| // return tcs.Task; | |
| // }); | |
| // catchReadTask.Finally(() => { }); | |
| // return task; | |
| //} | |
| public virtual Task<object> ApiAsync(string httpMethod, string path, object parameters, Type resultType, object userState, CancellationToken cancellationToken) | |
| { | |
| Stream input; | |
| var httpHelper = PrepareRequest(httpMethod, path, parameters, resultType, out input); | |
| Task task; | |
| if (input == null) | |
| { | |
| var tcs = new TaskCompletionSource<object>(); | |
| tcs.SetResult(null); | |
| task = tcs.Task; | |
| } | |
| else | |
| { | |
| throw new NotImplementedException(); | |
| } | |
| bool read = false; | |
| return | |
| task | |
| .Then(() => httpHelper.OpenReadTaskAsync(cancellationToken)) | |
| .ContinueWith(t => | |
| { | |
| if (t.IsFaulted) | |
| { | |
| var ex = t.Exception.GetBaseException() as WebExceptionWrapper; | |
| if (ex == null) | |
| { | |
| t.Wait(); | |
| } | |
| else | |
| { | |
| var response = ex.GetResponse(); | |
| if (response == null) t.Wait(); | |
| if (response.StatusCode != HttpStatusCode.NotModified) | |
| { | |
| return httpHelper | |
| .OpenReadTaskAsync(cancellationToken) | |
| .Then(stream => | |
| { | |
| read = true; | |
| return CompletedTask(stream); | |
| }); | |
| } | |
| else | |
| { | |
| read = true; | |
| return CompletedTask(t.Result); | |
| } | |
| } | |
| throw new InvalidAsynchronousStateException(); | |
| } | |
| else if (t.IsCanceled) return CancelledTask<Stream>(); | |
| else | |
| { | |
| read = true; | |
| return CompletedTask(t.Result); | |
| } | |
| }) | |
| .Unwrap() | |
| .ContinueWith(t => | |
| { | |
| if (t.IsFaulted) t.Wait(); | |
| else if (t.IsCanceled) return CancelledTask<object>(); | |
| else if (read) | |
| { | |
| var tcs = new TaskCompletionSource<object>(); | |
| var result = ProcessResponse(httpHelper, t.Result, resultType); | |
| tcs.TrySetResult(result); | |
| return tcs.Task; | |
| } | |
| throw new InvalidAsynchronousStateException(); | |
| }) | |
| .Unwrap(); | |
| } | |
| public virtual Task<object> ApiAsync(string httpMethod, string path, object parameters, Type resultType) | |
| { | |
| return ApiAsync(httpMethod, path, parameters, resultType, null, CancellationToken.None); | |
| } | |
| private static Task<T> CancelledTask<T>() | |
| { | |
| var tcs = new TaskCompletionSource<T>(); | |
| tcs.TrySetCanceled(); | |
| return tcs.Task; | |
| } | |
| private static Task<T> CompletedTask<T>(T result) | |
| { | |
| var tcs = new TaskCompletionSource<T>(); | |
| tcs.TrySetResult(result); | |
| return tcs.Task; | |
| } | |
| [EditorBrowsable(EditorBrowsableState.Never)] | |
| protected HttpWebRequestWrapper CreateHttpWebRequest(Uri uri) | |
| { | |
| if (HttpWebRequestFactory != null) | |
| return HttpWebRequestFactory(uri); | |
| return new HttpWebRequestWrapper((HttpWebRequest)WebRequest.Create(uri)); | |
| } | |
| [EditorBrowsable(EditorBrowsableState.Never)] | |
| protected object JsonDeserialize(string json, Type resultType) | |
| { | |
| return SimpleJson.DeserializeObject(json, resultType); | |
| } | |
| [EditorBrowsable(EditorBrowsableState.Never)] | |
| protected object JsonSerialize(object json) | |
| { | |
| return SimpleJson.SerializeObject(json); | |
| } | |
| private HttpHelper PrepareRequest(string httpMethod, string path, object parameters, Type resultType, out Stream input) | |
| { | |
| input = null; | |
| var uri = new Uri("https://graph.facebook.com" + AddStartingSlashIfNotPresent(path)); | |
| var request = CreateHttpWebRequest(uri); | |
| request.AllowAutoRedirect = false; | |
| #if !(SILVERLIGHT || NETFX_CORE) | |
| request.AllowWriteStreamBuffering = true; | |
| request.UserAgent = UserAgent; | |
| #endif | |
| return new HttpHelper(request); | |
| } | |
| private object ProcessResponse(HttpHelper httpHelper, Stream responseStream, Type resultType) | |
| { | |
| IDictionary<string, object> result = PrepareResultForResponse(httpHelper); | |
| var response = httpHelper.HttpWebResponse; | |
| if (response.StatusCode == HttpStatusCode.NotModified) | |
| return result; | |
| string responseString; | |
| using (var stream = responseStream) | |
| { | |
| using (var reader = new StreamReader(stream)) | |
| { | |
| responseString = reader.ReadToEnd(); | |
| } | |
| } | |
| result["body"] = JsonDeserialize(responseString, resultType); | |
| return result; | |
| } | |
| [DebuggerStepThrough] | |
| private IDictionary<string, object> PrepareResultForResponse(HttpHelper httpHelper) | |
| { | |
| var response = httpHelper.HttpWebResponse; | |
| var result = new JsonObject(); | |
| result["status"] = (int)response.StatusCode; | |
| var headers = new JsonObject(); | |
| foreach (var headerName in response.Headers.AllKeys) | |
| headers[headerName] = response.Headers[headerName]; | |
| result["headers"] = headers; | |
| return result; | |
| } | |
| /// <summary> | |
| /// Add starting slash if not present. | |
| /// </summary> | |
| /// <param name="input"></param> | |
| /// <returns></returns> | |
| private static string AddStartingSlashIfNotPresent(string input) | |
| { | |
| if (string.IsNullOrEmpty(input)) | |
| return "/"; | |
| // if not null or empty | |
| if (input[0] != '/') | |
| { | |
| // if doesn't start with / then add / | |
| return "/" + input; | |
| } | |
| else | |
| { | |
| // else return the original input. | |
| return input; | |
| } | |
| } | |
| } | |
| public class SampleApiAttachment | |
| { | |
| public string FileName { get; set; } | |
| public string ContentType { get; set; } | |
| private object _attachment; | |
| public object Attachment | |
| { | |
| get { return _attachment; } | |
| set | |
| { | |
| if (value != null) | |
| { | |
| if (value is Stream || value is byte[]) | |
| _attachment = value; | |
| } | |
| _attachment = value; | |
| } | |
| } | |
| } | |
| public class ProgressData | |
| { | |
| public long TotalBytes { get; set; } | |
| public long ReadBytes { get; set; } | |
| public double Percentage { get; set; } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment