|
|
Hi
I've just built overflow 7 using Stacky - loved using the library - thanks - http://bit.ly/overflow7
There were only a couple of problems - here are a very few notes I made as I went along:
- AnswerMethods.cs - it looks to me like GetQuestionAnswers() wrongly calls GetUserAnswers() instead of the overload of GetQuestionAnswers()
- QuestionMethods.cs - I added a hacky method:
public virtual void GetUnansweredQuestions(Action<IPagedList<Question>> onSuccess, Action<ApiException> onError = null, QuestionSort sortBy = QuestionSort.Activity, SortDirection sortDirection = SortDirection.Descending, int? page = null, int? pageSize = null, bool includeBody = false, bool includeComments = false, bool includeAnswers = false, DateTime? fromDate = null, DateTime? toDate = null, string[] tags = null)
{
GetQuestions(onSuccess, onError, "questions/unanswered", new string[0], null, null, page, pageSize, includeBody, includeAnswers, includeComments, fromDate, toDate, tags);
}
I'm sure this could be done better! - UrlClientSync.cs - I added some additional try...catch blocks just to assist with error handling - API calls often fail at the network level on WP7
- Project - the WP7 "Release" configuration is missing the WINDOWSPHONE #define
Hope that feedback helps - thanks for a superb library!
Stuart
|
|
Coordinator
Feb 27, 2011 at 4:48 AM
|
Thank you for the feedback. You app looks great! Would you mind sharing your changes to UrlClientAsync.cs?
|
|
|
|
Hopefully you've got mail!
If not, then my changes are a bit hacky - they just catch Exception - where as really going further down into WebException or IOException might be more appropriate:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HttpClient = System.Net.WebClient;
using System.Net;
#if WINDOWSPHONE
using ICSharpCode.SharpZipLib.GZip;
using System.IO;
#endif
#if !SILVERLIGHT
using System.IO.Compression;
using System.IO;
#endif
namespace Stacky
{
#if SILVERLIGHT
public class UrlClient : IUrlClient
#else
public class UrlClientAsync : IUrlClientAsync
#endif
{
private class RequestContext
{
public Uri Url;
public Action<HttpResponse> OnSuccess;
public Action<ApiException> OnError;
}
public void MakeRequest(Uri url, Action<HttpResponse> onSuccess, Action<ApiException> onError)
{
var client = new HttpClient();
//client.Headers[HttpRequestHeader.UserAgent] = "Stacky";
#if !SILVERLIGHT
client.Headers[HttpRequestHeader.AcceptEncoding] = "gzip";
client.Encoding = Encoding.UTF8;
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
client.DownloadDataAsync(url, new RequestContext{Url = url, OnSuccess = onSuccess, OnError = onError});
#else
#if WINDOWSPHONE
client.OpenReadAsync(url, new RequestContext { Url = url, OnSuccess = onSuccess, OnError = onError });
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
#else
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(url, new RequestContext{Url = url, OnSuccess = onSuccess, OnError = onError});
#endif
#endif
}
#if !SILVERLIGHT
public void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
RequestContext context = e.UserState as RequestContext;
WebClient client = sender as WebClient;
if (context != null)
{
var httpResponse = new HttpResponse
{
Body = "",
Url = context.Url
};
if (e.Error != null)
{
httpResponse.Error = e.Error;
var webError = e.Error as WebException;
if (webError != null)
{
if (webError.Status == WebExceptionStatus.ProtocolError && webError.Response != null)
{
var response = (HttpWebResponse)webError.Response;
if (response.StatusCode != HttpStatusCode.NotFound)
{
using (var responseStream = response.GetResponseStream())
{
httpResponse.Body = DecodeResponseStream(responseStream);
ErrorResponse errorResponse = SerializationHelper.DeserializeJson<ErrorResponse>(httpResponse.Body);
if (context.OnError != null)
context.OnError(new ApiException(errorResponse.Error, e.Error, httpResponse.Url));
return;
}
}
}
if (context.OnError != null)
context.OnError(new ApiException(e.Error));
return;
}
}
//response.ParseRateLimit(client.ResponseHeaders);
using (var memoryStream = new MemoryStream(e.Result))
{
httpResponse.Body = DecodeResponseStream(memoryStream);
}
context.OnSuccess(httpResponse);
}
}
private string DecodeResponseStream(Stream stream)
{
using (var gzipStream = new GZipStream(stream, CompressionMode.Decompress))
{
var decompressed = new List<byte>();
int i;
while ((i = gzipStream.ReadByte()) != -1)
decompressed.Add((byte)i);
return Encoding.UTF8.GetString(decompressed.ToArray());
}
}
#endif
#if WINDOWSPHONE
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
// method changed by Stuart - just for error handling
RequestContext context = e.UserState as RequestContext;
WebClient client = sender as WebClient;
try
{
string data;
using (var gzip = new GZipInputStream(e.Result))
using (var reader = new StreamReader(gzip))
{
data = reader.ReadToEnd();
}
if (context != null)
{
var httpResponse = new HttpResponse
{
Url = context.Url
};
if (e.Error != null)
{
httpResponse.Error = e.Error;
var webError = e.Error as WebException;
if (context.OnError != null)
context.OnError(new ApiException(e.Error, httpResponse.Url));
return;
}
httpResponse.Body = data;
context.OnSuccess(httpResponse);
}
}
catch (Exception exc)
{
if (context != null && context.OnError != null)
context.OnError(new ApiException(exc));
}
}
#endif
public void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// method changed by Stuart - just for error handling
RequestContext context = e.UserState as RequestContext;
WebClient client = sender as WebClient;
try
{
if (context != null)
{
var httpResponse = new HttpResponse
{
Url = context.Url
};
if (e.Error != null)
{
httpResponse.Error = e.Error;
var webError = e.Error as WebException;
if (context.OnError != null)
context.OnError(new ApiException(e.Error, httpResponse.Url));
return;
}
//TODO: Figure out how to get the ResponseHeaders in Silverlight
//response.ParseRateLimit(client.ResponseHeaders);
httpResponse.Body = e.Result;
context.OnSuccess(httpResponse);
}
}
catch (Exception exc)
{
if (context != null && context.OnError != null)
context.OnError(new ApiException(exc));
}
}
}
}
|
|