Real-World Windows 8.1 Deployment Notes from the Field

Exception management for asynchronous tasks can be a little tricky.
In the following example, I have implemented exception management. Suppose that server returns an error message using the header "Reason-Phrase"
public byte[] getFile (String url,String fileName)
{
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream stream = request.GetRequestStream())
{
/* suppose that the name of requested file is sent in the
body of POST. For REST services you can send
parameters in the body of POST, "url-encoded"
and separated by "&" */
byte[] content = Encoding.UTF8.GetBytes("name=" + WebUtility.UrlEncode(fileName));
stream.Write(content, 0, content.Length);
}
// the following call will not block
Task<WebResponse> task = request.GetResponseAsync();
// ...here you can do something while task complete...
try
{
// waiting until task complete
// note exception management for Wait()
task.Wait();
}
catch (AggregateException e)
{
throw new Exception(((WebException)e.InnerException).Response.Headers["Reason-Phrase"]);
}
using (Stream stream = task.Result.GetResponseStream())
using (MemoryStream m = new MemoryStream())
{
stream.CopyTo(m);
return m.ToArray();
}
}
}
Fun session. Thank you Mads! You're one of my favorite speakers.
Where is the video?
Thanks!
Where is the video?
In order to improve User Experience in front-end Apps, is a good practice implement the callback pattern (methods which are invoked when asynchronous operations are completed). This pattern is also a little tricky.
Here an example (suppose that server returns an error message using the header "Reason-Phrase");
public void getFileAsync(String url,String fileName,Action<byte[]> callback)
{
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream stream = request.GetRequestStream())
{
/* suppose that the name of requested file is sent in the
body of POST. For REST services you can send
parameters in the body of POST, "url-encoded"
and separated by "&" */
byte[] content = Encoding.UTF8.GetBytes("name=" + WebUtility.UrlEncode(fileName));
stream.Write(content, 0, content.Length);
}
// the following call will not block
Task<WebResponse> task = request.GetResponseAsync();
if (callback != null) task.ContinueWith((t, c) =>
{
try
{
using (Stream stream = t.Result.GetResponseStream())
using (MemoryStream m = new MemoryStream())
{
stream.CopyTo(m);
((Action<byte[]>)c)(m.ToArray());
}
}
catch (AggregateException e)
{
throw ((WebException)e.InnerException).Response != null ?
new Exception(((WebException)e.InnerException).Response.Headers["Reason-Phrase"]) :
e.InnerException;
}
}, callback);
}
Finally, you only need invoke the following method (the callback function is inlined using a lambda expression):
getFileAsync("my-url","file-name",(buffer) => {
// buffer contains the received file
});
Note that method getFileAsync() not blocks. Also, note that AggregateException is used for exception management because the anonymous function inlined within ContinueWith() executes in a different context.