See intro blogpost here.
In Silverlight and WPF you are probably used to using WebClient to perform downloads. This is a simple class for doing download/upload string or retrieving a response stream from the server. However, in Windows Runtime this client doesn’t exists. Instead we have new a simple “HttpClient” to do much of what WebClient can. However it works very differently by using the new Task framework, and the more you dive into porting code to WinRT, you will see this a lot, and it will make your life porting code cumbersome. On the upside, the Tasks framework is awesome and it’ll often simplify you code a great deal! I talked a bit about this in my previous post, so please read that first, before you continue here, since this will be building on top of that.
Let’s say we have a method in WPF and Silverlight that uses WebClient to downloada and create an image. Since this is working asynchronously, we would have to either use event handlers or action delegates to return the result and/or the error. The method could look something like this:
public void GetContent(Uri uri, Action<string> complete, Action<Exception> error)
{
WebClient client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Error != null)
error(e.Error);
else {
complete(e.Result);
}
};
client.DownloadStringAsync(uri);
}
Here’s how a method like that could look in WinRT:
public async Task<string> GetContentI(Uri uri)
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var result = await client.GetAsync(uri);
return result.Content.ReadAsString();
}
Simple right? Well it' gets even simpler when we have to start consuming that method.
From SL and WPF you would consume the method something like this:
GetContent(uri, (text) => {
TextBlock tb = new TextBlock() { Source = text };
LayoutRoot.Children.Add(tb);
},
(error) => { /*TODO: handle error*/ }
);
And the same using the Task framework:
try {
TextBlock tb = new TextBlock() { Source = await GetContent(uri) };
LayoutRoot.Children.Add(tb);
catch { /*TODO: handle error */ }
You tell me what’s more elegant and readable?
My point here is that Tasks are awesome, so rather than trying to reuse your existing code in WinRT, consider rewriting your existing code to use Tasks and it will work much smoother.
There’s lets create a method for downloading a string over the network that works the same way across the board. (I’ll assume you are using the Async Task CTP for Silverlight or WPF for this).
public async Task<string> GetContent(Uri uri)
{
#if NETFX_CORE
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
var reqResult = await client.GetAsync(uri);
return reqResult.Content.ReadAsString();
#else
WebClient client = new WebClient();
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Error != null)
tcs.TrySetException(e.Error);
else
tcs.TrySetResult(e.Result);
};
client.DownloadStringAsync(uri);
return await tcs.Task;
#endif
}
Note you could also use the new .NET method “WebClient.DownloadStringTaskAsync” which would simplify the above quite a lot. I used the event based approach to demonstrate how you would handle the cases where you don’t already have a task implementation available.