Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert .net 4.5 Async/Await example back to 4.0

What would the equivalent asp.net mvc 4.0 code look like?

using System.Net;
using System.Net.Http;
using System.Web.Mvc;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Web.Controllers
{
    public class HomeController : Controller
    {
        private HttpClient httpClient = new HttpClient();
        private static dynamic shots;

        public async Task<ActionResult> Index()
        {
            if (shots == null)
            {
                try
                {
                    var responseMessage = 
                       await httpClient.GetAsync
                            ("http://api.dribbble.com/shots/everyone?per_page=30");
                    responseMessage.EnsureSuccessStatusCode();

                    var value = await responseMessage.Content.ReadAsStringAsync();
                    shots = await JsonConvert.DeserializeObjectAsync<dynamic>(value);
                }
                catch (WebException)
                {
                }
            }
            return View(shots);
        }
    }
}
like image 295
superlogical Avatar asked Jun 12 '12 10:06

superlogical


3 Answers

NOTE: This is only for the Async/Await part.

The easiest way would be to use the Async CTP. It has a Go live license which means you can use it in production code. You will have to make some modifications in cases where the Async CTP doesn't provide async equivalents.

You can use Async CTP on Azure as the only thing required is an extra DLL. There is a similar SO question here Async CTP and Windows Azure Support

I've been using Async CTP in production for over a year without problems. I'd definitely recommend this. Upgrading to .NET 4.5 is rather easy, essentially requiring only some class name changes (TaskEx to Task) and a few signature changes.

If you can use Visual Studio 2012 RC you can also use the Async Targeting pack which will allow you to use your async code in .NET 4 with fewer changes than if you use the Async CTP.

Finally, the brute-force solution is to use the TaskIterator from the ParallelExtensionsExtras samples to emulate what async/await does. You will have to convert all asynchronous invocations to tasks, or methods that return a task, and then iterate over the list of those tasks. It's a lot more code but it's the only solution if you don't want to use CTP code, even if it has a Go Live license.

The ParallelExtensionsExtras include asynchronous tasks for the WebClient which may be useful if you decide to switch from HttpClient to WebClient.

like image 169
Panagiotis Kanavos Avatar answered Nov 14 '22 07:11

Panagiotis Kanavos


As someone exploring how to get all of this working in .NET 4.0 as well, I haven't found the given answers on this thread and others complete enough to immediately get up and running. So the following is a more comprehensive answer of what to simply do:

======= STEP #1) INSTALL Microsoft ASP.NET Web API Client Libraries (RC) 4.0.20505.0 =======

http://nuget.org/packages/Microsoft.AspNet.WebApi.Client

PM> Install-Package Microsoft.AspNet.WebApi.Client

INSTALLS: System.Net.Http.dll, System.Net.Http.Formatting.dll, System.Net.Http.WebRequest.dll, Newtonsoft.Json.dll

======= STEP #2) Microsoft .NET Framework 4 HTTP Client Libraries 2.0.20505.0 =======

http://nuget.org/packages/Microsoft.Net.Http.

PM> Install-Package Microsoft.Net.Http.

If you followed step #1 already, NuGet should have actually already grabbed this dependency: System.Net.Http.dll. System.Net.Http. is what provides HttpClient, HttpRequestMessage and HttpResponseMessage.

At this point, you will be getting errors when using async/await (though these keywords still show up as keywords) saying things like:

Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

Thus:

======= STEP #3) Async Targeting Pack for Visual Studio =======

http://www.microsoft.com/en-us/download/details.aspx?id=29576

PM> Install-Package Microsoft.CompilerServices.AsyncTargetingPack

('...Visual Studio 11' name needs updated on NuGet, both are version 1.0.0)

Installs 1 dll: Microsoft.CompilerServices.AsyncTargetingPack.Net4.dll

"The "Async Targeting Pack for Visual Studio 2012" enables projects targeting .NET Framework 4.0 or Silverlight 5 to use the Async language feature in C# 5 ... " http://www.microsoft.com/en-us/download/details.aspx?id=29576

Among other things, adds TaskEx (a .NET 4.0 version that fills in many new Task features. TaskEx is only for the 4.0 version... so .NET 4.5: "Task.Run" is in 4.0: "TaskEx.Run", many other things are like this with this library)

Suddenly, await and async and the whole works starts working like a charm! If you reflect in, one of the most important things about this is the class (declared without a namespace): AsyncCompatLibExtensions. A static class containing extension methods onto especially: 1) Stream. E.g. ReadAsync. So now stream.ReadAsync suddenly appears! (it actually cleanly wraps stream's BeginRead/BeginWrite, if you want to know), 2) WebClient. E.g. webClient.DownloadStringTaskAsync, and more.

like image 5
Nicholas Petersen Avatar answered Nov 14 '22 08:11

Nicholas Petersen


WARNING There is no error checking!

Well I feel like I learned something today, have a read of this article http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx to learn a better way to handle this :)

using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Mvc;
using Newtonsoft.Json;
namespace DribbbleR.Web.Controllers
{
    public class HomeController : Controller
    {
        private static dynamic shots;
        private HttpClient client = new HttpClient();
        private string url = "http://api.dribbble.com/shots/everyone?per_page=30";

        public Task<dynamic> Index()
        {    if (shots == null)
             shots = Task.Factory.StartNew
                   (() => return DownloadContent();).Unwrap();    
             return shots;
        }
        public Task<dynamic> DownloadContent()
        {    var responseTask = client.GetAsync(url);
             var readTask = responseTask.ContinueWith
                 (t =>
                     {   t.Result.EnsureSuccessStatusCode();
                         return t.Result.Content.ReadAsStringAsync();
                      }
                  ).Unwrap();
            var deserializeTask = readTask.ContinueWith
                  (t => return JsonConvert.DeserializeObjectAsync<dynamic>(t.Result);)
            .Unwrap();
            var viewTask = deserializeTask.ContinueWith
                  (t =>  return this.View(t.Result););
            return viewTask;
        }
    }
}
like image 3
superlogical Avatar answered Nov 14 '22 08:11

superlogical