The Wayback Machine - https://web.archive.org/web/20130502033807/http://www.codeguru.com:80/csharp/.net/net_asp/mvc/working-with-asynchronous-operations-in-asp.net-mvc.htm

Working with Asynchronous Operations in ASP.NET MVC

Introduction

Whenever you call action methods in an ASP.NET MVC application, by default they are executed in synchronous fashion. In order to improve the overall performance and responsiveness of your application you may wish to execute the code asynchronously. You may execute code asynchronously from two distinct places - server-side and client-side. This article discusses both of these scenarios and shows how to create asynchronous controllers and use SessionState attribute.

What are Asynchronous Operations?

Before you write any code that runs asynchronously, it would be nice to quickly brief what asynchronous operations are and the benefit of such operations. Suppose that you have a piece of code as shown below :

public void ParentMethod()
{
    ChildMethod1();
    ChildMethod2();
    ChildMethod3();
}

The ParentMethod() is a method that you are supposed to call from the rest of your application. The ParentMethod() in turn calls three child methods viz. ChildMethod1(), ChildMethod2() and ChildMethod3(). Also assume that all the child methods are remote methods. Under synchronous execution (default as far as server-side code in ASP.NET is concerned) the three child methods will execute serially i.e. one after the other. Thus ChildMethod1() will execute first, will return the control back to the parent method and only then will ChildMethod2()be executed. If the child methods are taking say 5, 10 and 15 seconds to complete, the effective time taken for executing all of them will be 5 + 10 + 15 i.e. 30 seconds.

Under the asynchronous scheme of code execution, the child methods are called in parallel i.e. ChildMethod2() will start its execution without waiting for ChildMethod1() to complete. So, if the three methods are taking 5, 10 and 15 seconds to complete, the effective time taken will not be 30 seconds as in the former case but 15 seconds (the time taken for the longest running method).

Of course, there are other factors that affect the execution of asynchronous code but the above example highlights the main difference between synchronous and asynchronous operations.

As far as ASP.NET MVC is concerned there are two distinct places where asynchronous operations can be invoked:

  • Server-side
  • Client-side

In the former case you will use asynchronous controllers and in the latter case you will go for session-less controllers on the server along with AJAX code at the client-side.

Creating Asynchronous Controllers

Whenever you add a controller to your ASP.NET MVC application, you will see a class declaration like this:

public class HomeController : Controller
{
...
}

By default, the newly added controller class is inherited from Controller base class. If you wish to code asynchronous action methods you should inherit the controller class from AsyncController class instead.

public class HomeController : AsyncController
{
...
}

When you inherit your controller from AsyncController base class, an instance of AsyncManager class is made available to your code. The AsyncManager class allows you to flag asynchronous operations and also helps you to store pieces of data that are passed to the method handling asynchronous operation completion. Use of AsyncManager will be clear when you develop an example in later sections.

Creating Asynchronous Action Methods

The asynchronous controller declared, as shown in the preceding section, can contain asynchronous action methods. ASP.NET MVC follows certain patterns for creating asynchronous methods. For every action that you wish to execute in asynchronous fashion there will be two methods - one that initiates the operation and other that completes the operation. For example, say you wish to create Index() action in asynchronous fashion. So, your code will resemble that shown below :

public void IndexAsync()
{
...
}
 
public ActionResult IndexCompleted(...)
{
...
}

As you can see the first method takes the form XXXXAsync() and the second method takes the form XXXXCompleted(). The second method can have a list of parameters depending on what you put inside AsyncManager.

Let's say you are developing an application that fetches RSS news feeds from different sources (say Google, MSN, Yahoo etc.) and then aggregates them to produce a single feed. So your skeleton methods will look like this:

public class HomeController : AsyncController
{
    private void GetGoogleNews()
    {
    }
 
    private void GetMSNNews()
    {
    }
 
    public void IndexAsync()
    {
    }
 
    public ActionResult IndexCompleted()
    {
    }
}

The IndexAsync() method needs to call GetGoogleNews() and GetMSNNews() helper methods in asynchronous fashion. So, the complete code of IndexAsync() method looks like this:

public void IndexAsync()
{
    AsyncManager.OutstandingOperations.Increment(2);
    Task.Factory.StartNew(() => GetGoogleNews()); 
    Task.Factory.StartNew(() => GetMSNNews()); 
}

As you can see, before calling GetGoogleNews() and GetMSNNews() methods you use AsyncManager instance to flag the number of pending operations. The OutstandingOperations.Increment() method allows you to specify the number of outstanding operations. Notice how the code uses Task class to call the methods asynchronously. The outstanding operation count needs to be decremented once the individual operations are done with. This can be done inside the GetGoogleNews() and GetMSNNews() methods as shown below:

private void GetGoogleNews()
{
    XmlReader reader = XmlReader.Create("http://news.google.co.in/news?pz=1&cf=all&ned=in&hl=en&output=rss");
    Rss20FeedFormatter formatter = new Rss20FeedFormatter();
    formatter.ReadFrom(reader);
    reader.Close();
    AsyncManager.Parameters.Add("GoogleNews", formatter.Feed.Items);
    AsyncManager.OutstandingOperations.Decrement();
}
 
private void GetMSNNews()
{
    XmlReader reader = XmlReader.Create("http://msn.com/rss/news.aspx");
    Rss20FeedFormatter formatter = new Rss20FeedFormatter();
    formatter.ReadFrom(reader);
    reader.Close();
    AsyncManager.Parameters.Add("MSNNews", formatter.Feed.Items);
    AsyncManager.OutstandingOperations.Decrement();
}

As you can see, both of the methods essentially make use of classes from System.ServiceModel.Syndication namespace to fetch RSS feed items from a specified source. Notice the code marked in bold letters. It uses the Parameters collection of AsyncManager object to store application specific pieces of data. In this case you store feed items with key names GoogleNews and MSNNews respectively. These parameters will be passed to the completion method. The code then calls the OutstandingOperations.Decrement() method so as to decrement the pending operation count.

When all the outstanding operations are completed, the async completion method is called and all the parameters are passed to it. In our example, the async completion method looks like this:

public ActionResult IndexCompleted(IEnumerable<SyndicationItem> GoogleNews, IEnumerable<SyndicationItem> MSNNews)
{
    List<SyndicationItem> allItems = new List<SyndicationItem>();
    allItems.AddRange(GoogleNews);
    allItems.AddRange(MSNNews);
    allItems.Sort(CompareDates);
    ViewBag.FeedItems = allItems;
    return View();
}

As you can see, the IndexCompleted() method accepts two parameters of type IEnumerable<SyndicationItem>. It then aggregates all the news feed items and passes them to Index view via ViewBag (FeedItems property).

Consuming Asynchronous Action Methods

Consuming asynchronous action methods is no different than synchronous ones. You will still refer the action method as Index in your URLs and Views. For example, consider the Index view that renders the aggregated news feed items in an HTML table.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%@ Import Namespace="System.ServiceModel.Syndication" %>
 
<!DOCTYPE html>
 
<html>
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    <table border="1" cellpadding="6" cellspacing="0">
    <tr><th>Latest News from Google and MSN</th></tr>
    <%foreach (SyndicationItem item in ViewBag.FeedItems)
      {%>
      <tr><td><a href="<%= item.Links[0].Uri %>"><%= item.Title.Text %></a></td></tr>
    <%}%>
    </table>
    </div>
</body>
</html>

To run this view, you will still use Index as the action name in the URL and not IndexAsync. So, your URL will be:

Use Index as the action name in the URL
Figure 1:Use Index as the action name in the URL

Session-less Controllers and Client-Side Asynchronous Calls

In the preceding example you invoked methods asynchronously at the server end. Many modern web applications make use of AJAX to call server methods asynchronously from the client-side. For example, jQuery makes use of $.ajax() to make remote calls in asynchronous fashion. If you are making a single remote call using $.ajax() nothing special needs to be done. However, if you wish to make multiple $.ajax() calls to server at one go then you need to be aware of the session state behavior of ASP.NET MVC. By default, ASP.NET session is available to all the controller methods and you can read / write data to the Session storage. However, ASP.NET needs to ensure that at a time only one call from a client is accessing the session. In many cases you don't need session state at all but due to this default behavior multiple $.ajax() calls cannot work in an efficient manner. In such cases it is recommended to turn off the session state altogether. This way ASP.NET need not bother about access to session store and multiple client-side AJAX calls can perform efficiently.

To disable session state for controller actions you use [SessionState] attribute. The following controller class shows how this attribute is used.

[SessionState(SessionStateBehavior.Disabled)]
public class RssController : Controller
{
...
}

Notice how SessionState attribute sets session state behavior to Disabled. Also notice that the controller class (RssController) is not inherited from AsyncController because you will be invoking asynchronous operations from the client-side.

The remaining methods of RssController class are similar to what you already developed for HomeController with a few modifications.

[HttpPost]
public JsonResult GetGoogleNews()
{
    XmlReader reader = XmlReader.Create("http://news.google.co.in/news?pz=1&cf=all&ned=in&hl=en&output=rss");
    Rss20FeedFormatter formatter = new Rss20FeedFormatter();
    formatter.ReadFrom(reader);
    reader.Close();
    return Json(formatter.Feed.Items);
}
 
[HttpPost]
public JsonResult GetMSNNews()
{
    XmlReader reader = XmlReader.Create("http://msn.com/rss/news.aspx");
    Rss20FeedFormatter formatter = new Rss20FeedFormatter();
    formatter.ReadFrom(reader);
    return Json(formatter.Feed.Items);
}

As you can see the methods return JsonResult because jQuery code will be handling the returned data. Also notice the use of Json() method to serialize feed items in JSON format.

Invoking Action Methods from Client-Side

To invoke the above action methods from the client-side, you will make use of $.ajax(). The following jQuery code from the Index view of RssController shows how.

$(document).ready(function () {
    $.ajax({
        url: '/Rss/GetGoogleNews',
        type: 'POST',
        dataType: 'json',
        success : ShowGoogleNews
    });
 
    $.ajax({
        url: '/Rss/GetMSNNews',
        type: 'POST',
        dataType: 'json',
        success: ShowMSNNews
    });
})
 
function ShowGoogleNews(results) {
    $("#googleDiv").append("<table border='1' cellpadding='6' cellspacing='0'></table>");
    $("#googleDiv table").append("<tr><th>Google News</th></tr>");
    for (var i = 0; i < results.length; i++) {
        $("#googleDiv table").append("<tr><td><a href='" + results[i].Links[0].Uri + "'>" +results[i].Title.Text + "</a></td></tr>");
    }
}
 
function ShowMSNNews(results) {
$("#msnDiv").append("<table border='1' cellpadding='6' cellspacing='0'></table>");
$("#msnDiv table").append("<tr><th>MSN News</th></tr>");
for (var i = 0; i < results.length; i++) {
    $("#msnDiv table").append("<tr><td><a href='" + results[i].Links[0].Uri + "'>" + results[i].Title.Text + "</a></td></tr>");
}
}

As you can see, the $.ajax() calls invoke GetGoogleNews() and GetMSNNews() action methods from the RssController in asynchronous fashion. Upon successful completion of the $.ajax() calls ShowGoogleNews() and ShowMSNNews() client-side functions will be called. These functions essentially display the news feed items in an HTML table.

That's it! You can run the Index view and see how the feed items are rendered.

Summary

Asynchronous operations are helpful to improve the overall performance and responsiveness of your web application. As far as ASP.NET MVC is concerned you can program asynchronous operations from two distinct places - server-side and client-side. Programming server-side asynchronous operations involve inheriting your controller class from the AsyncController base class and then create action methods of the form XXXXAsync() and XXXXCompleted() where XXXX is the name of the action method. The AsyncManager object allows you to flag outstanding operations and to store data as key-value pairs. The parameters stored in AsyncManager are passed to the async completion method. The client-side asynchronous operation are invoked using jQuery $.ajax() calls. To serve multiple AJAX calls efficiently, you can go for session-less controllers. Session-less controllers make use of [SessionState] attribute to disable the session state.

Download the code for this article.

Related Articles

IT Offers

Comments

  • wholesale beanies

    Posted by xxds9tt on 04/01/2013 05:12am

    [url=http://snapbackhatwholesale.webs.com]wholesale snapbacks[/url] wholesale snapbacks l mbku [url=http://goodsnapbackhatscheap.webs.com]cheap snapbacks free shipping[/url] cheap snapbacks free shipping u bbcz[url=http://cheaphatsmall.webs.com]snapbacks for cheap[/url] snapbacks for cheap l qowu[url=http://bestbaseballcap.webs.com]wholesale baseball caps[/url] wholesale baseball caps g rsfe[url=http://cheaphatsmall.webs.com]cheap snapbacks[/url] cheap snapbacks v wmyf[url=http://snapbackswholesalezone.webs.com]snapback wholesale[/url] snapback wholesale l ezvd [url=http://cheaphatsmall.webs.com]snapback hats cheap[/url] snapback hats cheap c bynl [url=http://cheapsnapbackshat.webs.com]cheap hats online[/url] cheap hats online q nhjx[url=http://bestbaseballcap.webs.com]wholesale snapback caps[/url] wholesale snapback caps n jsop[url=http://cheaphatsmall.webs.com]cheap snapbacks[/url] cheap snapbacks h gucj[url=http://snapbackswholesalezone.webs.com]fitted hats wholesale[/url] fitted hats wholesale c xrhn[url=http://snapbackswholesalezone.webs.com]snapback wholesale[/url] snapback wholesale v dram [url=http://bestbaseballcap.webs.com]wholesale snapback caps[/url] wholesale snapback caps m wcbp [url=http://cheapsnapbackshat.webs.com]cheap snapbacks hats[/url] cheap snapbacks hats v fknp[url=http://cheapsnapbackshat.webs.com]cheap snapbacks online[/url] cheap snapbacks online o dywn[url=http://cheaphatsmall.webs.com]cheap hats[/url] cheap hats i rjza[url=http://cheapsnapbacksforsalezone.webs.com]cheap snapbacks free shipping[/url] cheap snapbacks free shipping n thdz[url=http://cheapsnapbackshat.webs.com]cheap snapbacks online[/url] cheap snapbacks online f bjdj

    Reply
  • Sexy Lingerie sale

    Posted by Fishnetgn1105 on 03/29/2013 10:35am

    http://babydollnightgowns.webs.com - babydoll nightwearDark blue conveys wisdom, trust and seriousness 2 is the busiest, most demanding time of our year http://womenssexyclothes.webs.com - sexy adult costumesMy Florida friend tunes in to his different operations at different times every day, and takes a few notes on what he seeslingerie?has been derived from the French word http://sexycostumesboutique.webs.com - Sexy CostumesSo beware of choosing the color for someone with different cultureBabydoll sets work well for any body type http://cheapspicylingerie.webs.com - cheap sexy lingerieBabydolls, slips, chemises, and gowns may also include a robe The amount of skin being covered as well as the body parts being accented and held to feature are the biggest determination of the lingerie http://cheapsexylingerie.webs.com - Cheap Discount Lingeries undergarments, sometimes, including the breasts?Lovers?Lane

    Reply
  • Sexy Chemise

    Posted by Fishnetei1077 on 03/29/2013 09:46am

    http://G-string.webs.com - sexy g-stringsThis company grew for 35 years and had continuously offered a wide array of products such as sexy costumes, fetish wear, plus size costumes, sexy lingerie and even menIf you happen to be really hunting for lingerie to spice up your love life, be sure to visit Frederick's of Hollywood (accessible online) http://Lingeriesv.webs.com - Camouflage LingerieThe top brings out the finest shape of your body One more interesting moment - on main picture maybe the model will be in black color but this company also offers this style in other color http://sexylingeriecostumese.webs.com - Lingerie CostumesTip 6 – Think about how the lingerie is going to feel against her skin when she is wearing it It has over 5,000 dreamgirl lingerie retailers that offers their products to the public http://sexylingerieshops.webs.com - Candy Lace lingerielingerie?has been derived from the French word On this day, you can be whoever you want http://sexylingeriecostumese.webs.com - Sexy LingerieThat is why the various cuts and slits on the fashionable skirts bring a taller appearance for the wearer even when showing off striking legs Second, the office parties

    Reply
  • cheap lingerie

    Posted by Fishnettc1056 on 03/29/2013 09:39am

    http://sexycostumesboutique.webs.com - Nurse Costumess boxers, and they have it The dreamgirl lingerie international catalogue offers a list of dreamgirl lingerie retailers http://sexylingeriecostumes.webs.com - sexy adult costumesToday's modern corset is made from softer and suppler materials such as silk, satin and lace, (as well as leather) to name a few Lingeries basically shape the body of women http://spicylingeries.webs.com - womens lingerieAvailable in soft and flowing materials and colorful designs, babydoll chemises are an ideal complement to any wardrobeThe cut, pattern or design is another factor for determining hot lingerie http://sexycostumesboutique.webs.com - Nurse CostumesWhich kind of lingerie you should get your love depends a lot on her self esteemwhy don't you just ask her her size! When shopping for lingerie, keep in mind that a gift of lingerie should stimulate both you and your partner http://sexycostumesus.webs.com - womens sexy clothesMy Florida friend tunes in to his different operations at different times every day, and takes a few notes on what he seeslingerie?has been derived from the French word

    Reply
  • sheer babydolls

    Posted by Fishnetpb1011 on 03/29/2013 09:25am

    http://discounteroticlingerie.webs.com - Sexy Lingerie storeThis is a great way to earn money and also drive additional customers to your own auctions One reason for offering the wholesale on lingerie is definitely promotion of the lingerie store http://cheapspicylingerie.webs.com - Cheap Babydoll Lingerie?My Florida friend tunes in to his different operations at different times every day, and takes a few notes on what he seeslingerie?has been derived from the French word http://cheapspicylingerie.webs.com - Cheap Discount LingerieDressing like a mermaid is sure to seize the notice of that specific someone you been admiring lately, and make you the envy of all the other girls Petite women should opt to baby dolls with simple design while larger women can choose styles with details that will attract attention to small body parts http://G-string.webs.com - Lingerie TeddiesThey too are typically made of silk or satinThere are two groups of people who like lingerie http://SexyChemise.webs.com - Sexy ChemiseTherefore, it is wise to choose white or black apparel as a gift Amongst its product inclusions are summerwear, clubwear, Halloween lane, fetish wear, men

    Reply
  • cheap sexy lingerie

    Posted by Fishnetgz1041 on 03/29/2013 09:00am

    http://sexycostumesboutique.webs.com - Sexy Rear Admiral CostumeIt should be elastic around the bust and it should be able to stretch while ensuring that it remains firm There are also some kinds in silk and lace with good and seductive designs that are good to be used in special occasions like honeymoons for one http://sexylingeriecostumese.webs.com - Nurse Lingerie4 Hosiery or pantyhose can also provide you a slimmer look for it enhances curves and lessens some problem areas in your body http://babydollnightgowns.webs.com - babydoll nightwearWhile lingerie is generally pretty forgiving size wise, (a lot of lingerie is marked one size fits all) you should know at a minimum if she's a small, medium or large Therefore, red is also suitable for males, such as red tie, red mp3 player http://G-string.webs.com - Sexy ChemiseBy signing up as an affiliate, you will be directing customers to purchase items in exchange for a commission On one of the calls he just casually mentioned that four months after installing the systems, he has not had a workmans compensation claim in two months, something that was very common before the cameras were installed http://spicylingeries.webs.com - womens lingerieBy opening an eBay store, you will be able to list more auctions at a lesser priceBlack denotes seriousness, bold and conservative

    Reply
  • Sexy Chemise

    Posted by Fishnetky1080 on 03/29/2013 07:46am

    http://sexycostumesus.webs.com - cop costumeThin women will look good in anything, but especially teddies, corsets, and babydolls Invite your co-workers, family and friends to join you http://Lingeriesv.webs.com - black LingerieAre you mysterious sexy? Cute sexy? Seductive sexy? Sporty sexy? Knowing what style of sexy you are will help you choose a costume that best matches your underlying sensuality and will help you feel more comfortable in fulfilling your fantasy role However, you need to remember not to buy over-decorated baby dolls for they always look trashy rather than seductive http://sexylingeriecostumese.webs.com - French Maid LingerieThey have lingerie from bustiers, corsets and babydolls The best thing is that all these dresses are available both online and offline at affordable prices for the customers http://discounteroticlingerie.webs.com - womens lingerieFulfill Your FantasiesHalloween provides us with an excellent opportunity to fulfill our fantasies It is generally sold with a matching thong http://Lingeriesv.webs.com - Animal Print LingerieYou can shop for lingerie together or make a surprise gift for a special occasion or just to surprise them At the beginning of December, move to Christmas as well as holidays of other faiths and cultures

    Reply
  • cheap snapbacks free shipping

    Posted by xxds5bt on 03/29/2013 02:55am

    [url=http://snapbackhatwholesale.webs.com]wholesale snapbacks[/url] wholesale snapbacks y yuor [url=http://goodsnapbackhatscheap.webs.com]cheap snapbacks[/url] cheap snapbacks z zzpg[url=http://goodsnapbackhatscheap.webs.com]cheap snapbacks[/url] cheap snapbacks u wnaa[url=http://cheaphatsmall.webs.com]snapbacks for cheap[/url] snapbacks for cheap s jiza[url=http://goodsnapbackhatscheap.webs.com]cheap snapbacks free shipping[/url] cheap snapbacks free shipping e dnzs[url=http://bestbaseballcap.webs.com]wholesale snapback caps[/url] wholesale snapback caps h jawr [url=http://cheaphatsmall.webs.com]snapbacks for cheap[/url] snapbacks for cheap q oqtp [url=http://cheapsnapbackshat.webs.com]cheap snapbacks hats[/url] cheap snapbacks hats r nkev[url=http://snapbackhatwholesale.webs.com]wholesale beanies[/url] wholesale beanies a cdgf[url=http://cheaphatsmall.webs.com]cheap hats[/url] cheap hats o mrfe[url=http://snapbackhatwholesale.webs.com]wholesale snapbacks[/url] wholesale snapbacks k fhaj[url=http://cheapsnapbackshat.webs.com]cheap snapbacks hats[/url] cheap snapbacks hats v mzxp [url=http://snapbackswholesalezone.webs.com]snapbacks wholesale[/url] snapbacks wholesale e zmzx [url=http://snapbackhatwholesale.webs.com]snapback hats wholesale[/url] snapback hats wholesale z zayo[url=http://cheapsnapbacksforsalezone.webs.com]cheap snapbacks for sale[/url] cheap snapbacks for sale t sepa[url=http://wholesalefittedhat.webs.com]snapback wholesale[/url] snapback wholesale l cqdw[url=http://snapbackhatwholesale.webs.com]wholesale beanies[/url] wholesale beanies a ozzk[url=http://cheapsnapbacksforsalezone.webs.com]cheap snapbacks free shipping[/url] cheap snapbacks free shipping r yyqn

    Reply
  • cheap ray ban

    Posted by lgliliImpumpiny on 03/29/2013 01:32am

    replica oakleys [url=http://replicaguccisunglasses.webs.com]replica oakleys[/url] oakley discount discount ray ban [url=http://discountsunglasseshoo.webs.com]discount ray ban[/url] wholesale oakley sunglasses cheap sunglasses [url=http://qualityguccisunglass.webs.com]cheap sunglasses[/url] discount ray ban cheap oakley frogskins [url=http://sunglasswholesaleofgucci.webs.com]cheap oakley frogskins[/url] discount sunglasses cheap fake oakleys [url=http://bestsunglassesshop.webs.com]cheap fake oakleys[/url] cheap ray ban oakleys for cheap [url=http://sunglasswholesaleofgucci.webs.com]oakleys for cheap[/url] cheap ray ban cheap ray ban [url=http://sunglasssaleulow.webs.com]cheap ray ban[/url] wholesale sunglasses discount oakleys [url=http://discountsunglassesfinewebs.com]discount oakleys[/url] cheap ray ban

    Reply
  • ray ban sunglasses cheap

    Posted by mgliliImpumpmyp on 03/29/2013 01:10am

    cheap wayfarer sunglasses [url=http://onlineguciisunglass.webs.com]cheap wayfarer sunglasses[/url] cheap sunglasses cheap oakley frogskins [url=http://sunglasswholesaleofgucci.webs.com]cheap oakley frogskins[/url] cheap ray ban wayfarer cheap sunglasses [url=http://sunglasspomoteauthentic.webs.com]cheap sunglasses[/url] fake oakleys replica oakleys [url=http://replicaguccisunglasses.webs.com]replica oakleys[/url] cheap ray ban discount sunglasses [url=http://discountsunglassesfinewebs.com]discount sunglasses[/url] discount ray ban sunglasses wholesale [url=http://wholesalesunglassescool.webs.com]sunglasses wholesale[/url] cheap oakleys cheap ray ban [url=http://qualityguccisunglass.webs.com]cheap ray ban[/url] cheap ray ban wayfarer oakley sunglasses cheap [url=http://cheapsunglassesshop.webs.com]oakley sunglasses cheap[/url] wholesale sunglasses

    Reply

Go Deeper

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds