Introducing Netizen – a Windows Azure + Windows Phone 7 Application

January 29, 2011



Netizen ( is a Windows Phone 7 application (available in the marketplace for free) that brings the voting record of your congressional representative to your finger tips, directly from your mobile phone. Simply select the Member of Congress you want to follow and "flick through" their voting record. Information about each member’s voting record is stored in Windows Azure Storage and is updated daily.

But don’t just follow how your representative is voting in congress, make your voice heard. By clicking on the "Like It" button on the mobile application, you can influence your friends and neighbors about the bill through the power of social networking. For each bill, Netizen automatically provisions a Facebook page[1] dedicated to your member of congress. This page acts almost as a virtual ballot for a bill as well as a community hub where fellow constituents can gather to express their support. Pasted below are some screenshots from the application:

Not using a mobile device? No problem! Simply point your browser to the addresses listed below: To get a list of representatives for the state of Virginia, use this address:

To view the recent votes cast by the representative from Virginia 11th district, use this address:

To view the Facebook page for the Bill H.R.4853 and Virginia 8th District, use this address:


Screenshot #1 – Select state


Screenshot #2 – Select Representative


Screenshot #3 – “Flick through” the most recent roll call votes


Screenshot #4 –  “Virtual ballot” – Dynamically generated Facebook page,


Technical Details

Netizen combines the power of Windows Phone 7 & Windows Azure. Here is how the application works

WP7 App

Windows Phone 7 app is designed to have a small footprint. As a result, the bulk of the functionality is located inside the Azure hosted service. Here are some of key highlights:

1) The main screen (display of votes) is based on Pivot Control. Pivot Control provides a quick way to manage views. Each view (PivotItem) displays the details associated with a vote. Pivot control makes it really convenient for switching between different vote views. The Pivot control employs lazy loading to conserve resources. In addition, in order to limit the resources used, we only display the ten most recent votes.

2) Some addition performance related items include:

· Invoking garbage collection explicitly after the rebinding the pivot control.

· Storing the state in the isolated storage in order to make application resumption quicker.

· Doing all the data transformation on the server, again in order to reduce the processing foot-print on WP7.

· Keeping a close watch on the overall size of the XAP file – the current version is under 150K.

The following link provides great performance related tips:

3) Since it is important to support a disconnected mode of operation, we always store the most recent data obtained from the Azure service into isolated storage. Another possibility is use of Sync Framework 4.0.

4) We experimented with embedding the browser control for web-based logins. It is possible for the web page to callback into the Silverlight code.

5) All the Netizen Azure service methods are based on REST. This made it quite easy to use the WebClient class to access them. A better alternative would have been the use reactive extensions as it would have made the code a bit cleaner.

6) One gotcha that we ran into was based on our decision to use SyndicationFeed as the data format. This was based on our desire to allow users to access the voting records
via their favorite feed readers (in addition to the WP7 app). In order to process the returned SyndicationFeed type, we had to explicitly add a reference to System.ServiceModel.Syndication. Here is the relevant code:

   1: XmlReader reader = XmlReader.Create(new StringReader(xmlContent));

   2: SyndicationFeed sFeed = SyndicationFeed.Load(reader);

   3:                    var entries = from en in sFeed.Items.Take(MaxNumberOfItemsPerFeed)

   4:                                  select en;

   5:                    foreach (var en in entries)

   6:                    {

   7:                        var x = en;

   8:                        SyndicationContent sc = x.Content;

   9:                        XmlSyndicationContent xsc;

  10:                       if (x.Content.Type == "text/xml" || x.Content.Type == "xml")

  11:                       {

  12:                           xsc = (XmlSyndicationContent)x.Content;

  13:                           VoteDetails vds = xsc.ReadContent<VoteDetails>();

  14:                           Votes.Add(vds);

  15:                       }

  16:                 }


Where the class VoteDetails is defined as shown below:

   1: [DataContract(Namespace = "")]

   2:         public class VoteDetails

   3:         {

   4:             [DataMember]

   5:             public string BillID { get; set; }

   6:             [DataMember]

   7:             public string Date { get; set; }

   8:             [DataMember]

   9:             public string Democratic_AYEs { get; set; }

  10:             [DataMember]

  11:             public string Democratic_NAYs { get; set; }

  12:             [DataMember]

  13:             public string Description { get; set; }

  14:             [DataMember]

  15:             public string Question { get; set; }

  16:             [DataMember]

  17:             public string Republican_AYEs { get; set; }

  18:             [DataMember]

  19:             public string Republican_NAYs { get; set; }

  20:             [DataMember]

  21:             public string Result { get; set; }

  22:             [DataMember]

  23:             public string Roll { get; set; }

  24:             [DataMember]

  25:             public string Vote { get; set; }

  26:         }

Azure Service

As stated earlier, the bulk of processing resides within the Azure based service.

This includes the following:

· A WCF/ REST service hosted on Windows Azure (x-small instance) that exposes the voting record as an RSS/ATOM feed. Here is what the WCF contract looks like.

   1: namespace Netizen.Contract

   2: {

   3:     [ServiceContract]

   4:     [ServiceKnownType(typeof(Atom10FeedFormatter))]

   5:     [ServiceKnownType(typeof(Rss20FeedFormatter))]

   6:     public interface INetizenService

   7:     {


   9:         [OperationContract]

  10:         [WebGet(UriTemplate = "rep/{zip}-{zipFour}")]

  11:         string GetRepresentative(string zip, string zipFour);


  13:         [OperationContract]

  14:         [WebGet(UriTemplate = "reps/{state}/{feedType}")]

  15:         SyndicationFeedFormatter GetRepresentatives(string state, 

  16: ng feedType);



  19:         [OperationContract]

  20:         [WebGet(UriTemplate = "vote/{repID}/{feedType}")]

  21:         SyndicationFeedFormatter GetVotes(string repID, string feedType);


  23:         [OperationContract]

  24:         [WebInvoke(UriTemplate =

  25: bscribe/{state}/{district}/{notificationUri}")]

  26:         void SetSubscription(string state, string district, 

  27: ng notificationUri);


  29:     }

  30: }


All the data is stored in Azure tables. A batch program is used to obtain the congressional voting record from Office of the Clerk of the U.S. House of Representatives and stored in Azure Tables. Data is appropriately transformed to make sure that Azure Table queries are efficient.

· Since the batch job runs once a day, it did not make sense to have dedicated worker role just loading data. Instead, we rely on a concept of “dynamic worker” within the web role job. We launch a console based data loader executable using the concept of startup tasks.

2. A MVC2 based web application hosted on Windows Azure (co-located within the same worker) Is used to dynamically generate Open Graph API  pages (that are deemed as Facebook Pages).

[1] A page hosted on our site that includes Open Graph tags, making it equivalent to a Facebook Page

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: