Getting Twitter Avatar Via C#

October 5 2012
Until Twitter deprecates their version 1 api, getting an avatar from Twitter anonymously serverside with C# is a snap. A little goofy since it returns a 302 so you have to set AllowAutoRedirect to false and then look in the Header location to get the URI:
private string GetTwitterAvatarUrl(string twitterHandle)
            string avatarUrl = string.Empty;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format("{0}", twitterHandle));
            request.AllowAutoRedirect = false;
            request.Method = "GET";
                WebResponse response = request.GetResponse();
                if (response.Headers["Location"] != null)
                    avatarUrl = response.Headers["Location"];
            catch (WebException) {}
            return avatarUrl;

WordPress Audio Player Now Falls Back To HTML5

August 15 2012

I realized people on iOS and other devices that don’t support Flash couldn’t use the embedded Flash player for listening to audio when using the WordPress Audio Player plugin.  I wanted to customize it so that sites would fall back to HTML5 if Flash wasn’t present. I found a post in the WordPress forums of someone who did this here.

However, his script didn’t work as it was for two reasons. First, he was Base64 encoding the url to the mp3 — not sure why. So I remmed out that code. Second, he was replacing the parent element with the <audio> tag, which was blowing away the entire post!  By replacing the element witht the id of the audio tag itself, walla!  Everything works!

You can download the modified file here and minify if you’d like.

Skinless jPlayer Implementation

August 15 2012

I recently implemented a skinless audio player using jPlayer that plays m4a files that it retrieves from the iTunes Search API.

I am using jPlayer 2.1.0 and the main gotchas I hit were problems with not having the latest version of Flash on target computers.  jPlayer requires Flash 10 or higher for fallback, which it seems to do for m4a files in Firefox.

Anyway, here’s the code if you are interested. Here’s where I instantiate the jPlayer. The only parameters I pass are the supplied parameter. I got away with the defaults for everything else.

ready: function() {
$("#jp_container .track-default").click();
supplied: "m4a, m4v"
Then, here’s how I wire up the click handler, toggling between the play and pause icons:
var current;
 $(".play").click(function(e) {
 $("#jplayer").jPlayer("setMedia", {
 m4a: $(this).attr("href")

 if (current == this) {
 $(current).append("<img style='vertical-align:middle;' 
border='0' src='/images/ic_menu_play.png'/>"
); $("#jplayer").jPlayer("pause"); current = null; return false; } $("#jplayer").jPlayer("play"); if (current != null) { $(current).empty(); $(current).append("<img style='vertical-align:middle;'
border='0' src='/images/ic_menu_play.png'/>"
); } $(this).empty(); $(this).append("<img style='vertical-align:middle;'
border='0' src='/images/ic_menu_pause.png'/>"
); current = this; return false; });
Works great!
Technorati Tags:

Having jPlayer dynamically switch between m4a and mp3

August 15 2012

According to the docs of jPlayer, you are only supposed to use either mp3 or m4a.  But in my case, I’m not sure which gets passed to the player from the database. So, I had to handle that in the script. Here’s what it looks like:

 ready: function() {
 $("#jp_container .track-default").click();

 supplied: "m4a, mp3, mv4"

When I wire up the handlers, I check the file extension before passing the URL to the setMedia method, like this:

$(".play").click(function(e) {
 var filename = $(this).attr("href");
 var ext = filename.split('.').pop();
Technorati Tags:
 if (ext == "m4a") {
 $("#jplayer").jPlayer("setMedia", {
 m4a: $(this).attr("href")
 else {
 $("#jplayer").jPlayer("setMedia", {
 mp3: $(this).attr("href")


A little hacky, but it works!

Visual Studio Achievements For VS2012

July 31 2012

The Visual Studio Achievements extension now supports VS2012. Read all about it here. And, there's a new achievement, BRAVE NEW WORLD, that you can get if you are running VS2012 on Windows 8. (Note: no one seems to have gotten the in joke about that achievement -- anyone?)

Visual Studio Achievements For Windows Azure Buzz

May 1 2012

Here’s some links to posts and stories about the 15 new Windows Azure achievements added to Visual Studio Achievements:

Visual Studio Adds Windows Azure Achievements

Azure Gamified - More Badges!
I Programmer

Visual Studio Achievements Brings Gamification to Windows Azure Development
MSFT post

Announcing Windows Azure Achievements For Visual Studio
Windows Azure Post

Cloud Cover Video

Announcing Visual Studio Achievements For Windows Azure

Using Parallel.ForEach To Aggregate Results From JSON Files Stored in Windows Azure Blob Storage

April 17 2012

I love NoSQL, except when it comes to reporting.  Then I miss those handy SQL aggregation calls. I recently had a situation where I needed to look at a whole bunch of JSON files stored in Windows Azure Blob Storage and aggregate values from within those JSON files. The exact scenario was to get a count of how many people had achieved each achievement as part of the Visual Studio Achievements project.

Turned out to be an ideal use case for using some of the parallel programming features in .NET 4.0. Rather than download and process N JSON blobs linearly, I could throw the loop in a Parallel.ForEach block and gain speed from the multi-core machine I was using. The code was pretty straightforward, especially once I discovered the System.Collections.Concurrent namespace with its handy ConcurrentDictionary.

And, most significantly, it increased performance by 400 percent!

Below is the code in it’s entirety; I’ll walk through it here:

For JSON deserialization, I’m using a library provided by the WCF team up on CodePlex which is now part of the ASP.NET Web API. It provides some nifty features for turning JSON into dynamic objects.

The first thing I do is download a JSON file that has all the achievements, which is publically available (line 25).

I then put all the achievements in a ConcurrentDictionary<string, int> which I’ll use to build my report (line 33).

Then, I get the blobs and start my Parallel.ForEach loop (line 41). Inside the Action(TSource), I walk the list of the user’s earned achievements, incrementing the count in the ConcurrentDictionary of each achievement (line 57).

Finally, once I exit the loop, I turn the dictionary into an Excel spreadsheet (line 69) – folks tend to like that format.

You’ll notice the remmed out code; that’s the old non-parallelized code if you’d like to compare.

1 using System; 2 using System.Collections.Concurrent; 3 using System.IO; 4 using System.Json; 5 using System.Net; 6 using System.Threading.Tasks; 7 using Microsoft.WindowsAzure; 8 using Microsoft.WindowsAzure.StorageClient; 9 10 namespace AchievementsReporting 11 { 12 class Program 13 { 14 15 static void Main(string[] args) 16 { 17 var cloudBlobClient = new CloudBlobClient(new Uri("", UriKind.Absolute), 18 new StorageCredentialsAccountAndKey("---", 19 "---")); 20 var container = cloudBlobClient.GetContainerReference("users"); 21 22 string masterJson = string.Empty; 23 using (var webClient = new WebClient()) 24 { 25 masterJson = 26 webClient.DownloadString(new Uri("")); 27 } 28 dynamic masterList = JsonValue.Parse(masterJson); 29 var statisticsDictionary = new ConcurrentDictionary<string, int>(); 30 //var statisticsDictionary = new Dictionary<string, int>(); 31 foreach (var achieve in masterList.Achievements) 32 { 33 statisticsDictionary.GetOrAdd(achieve.Name.ToString(), 0); 34 //statisticsDictionary.Add(achieve.Name.ToString(), 0); 35 } 36 BlobRequestOptions options = new BlobRequestOptions(); 37 options.UseFlatBlobListing = true; 38 options.BlobListingDetails = BlobListingDetails.Snapshots; 39 Console.WriteLine("Starting..."); 40 DateTime start = DateTime.Now; 41 Parallel.ForEach(container.ListBlobs(options), blobListItem => 42 //foreach (var blobListItem in container.ListBlobs(options)) 43 { 44 CloudBlob blob = 45 container.GetBlobReference( 46 blobListItem.Uri.AbsoluteUri); 47 string json = blob.DownloadText(); 48 if (!string.IsNullOrEmpty(json)) 49 { 50 dynamic achievementsDynamic = 51 JsonValue.Parse(json) as dynamic; 52 foreach ( 53 var achieve in achievementsDynamic.Achievements) 54 { 55 if (achieve.DateEarned != null) 56 { 57 statisticsDictionary[achieve.Name.ToString()] = 58 statisticsDictionary[achieve.Name.ToString()] + 1; 59 } 60 } 61 } 62 } 63 ); 64 65 using (StreamWriter writer = new StreamWriter("report.xls")) 66 { 67 foreach (var key in statisticsDictionary.Keys) 68 { 69 writer.WriteLine(key + "\t" + statisticsDictionary[key].ToString()); 70 } 71 } 72 TimeSpan diff = DateTime.Now - start; 73 Console.WriteLine("done - took: "); 74 Console.WriteLine(diff.TotalMinutes); 75 } 76 } 77 } 78

Migrating VSIX Extensions To Dev11

March 30 2012

Hit an interesting issue with porting Visual Studio VSIX extensions to Dev11. 

To get my extension to work in Dev11, I tweaked the source.extension.vsixmanifest file. While there is a GUI for editing that file, it doesn’t expose the ability to add Dev11 as a supported edition. However, you can open the source.extension.vsixmanifest up in your favorite xml editor and party on it there. In my case, I changed it as follows:

<SupportedProducts> <VisualStudio Version="10.0"> <Edition>Ultimate</Edition> <Edition>Premium</Edition> <Edition>Pro</Edition> <Edition>IntegratedShell</Edition> </VisualStudio> <VisualStudio Version="11.0"> <Edition>Ultimate</Edition> <Edition>Premium</Edition> <Edition>Pro</Edition> <Edition>IntegratedShell</Edition> </VisualStudio> </SupportedProducts>

Easy enough – the vsix installer will then install your extension for both versions. Nice!


However, I experienced some odd behavior that may catch some people.  There’s another section of the vsixmanifest called the <Content> section.  You are supposed to put an element into that section called the <VsPackage> element, with the name of the pkgdef file (which is an .ini file).  However, in VS2010, you could get away without having this element. But, in Dev11, if you don’t have this element, your extension will install but never initialize.  So make sure you have this element, either as macro, aka


Or as a hardcoded value:


Finally, be sure to test test test in Dev11, as you never know what might get ya.

StreamInsight Nuggets

March 22 2012

Here’s some choice quotes from a whitepaper on StreamInsight:

Relational database applications typically acquire data and store it to disk before it can be analyzed. We therefore call analysis with traditional relational database systems query-driven. Query-driven analysis is well-suited for historical data. … To reach the necessary performance and scale, [some] applications need to analyze the data in near real time while it is being acquired from the source. We denote these applications as event-driven applications because new event data arriving at the system triggers the necessary analysis.

I think this is a great intro to help wrap yr head around the difference between query-driven and event-driven analysis.

Microsoft StreamInsight is Microsoft’s platform to build high-throughput, low-latency event-driven analytics applications.

That’s a great one liner.

With StreamInsight, business insight is delivered at the speed at which data is produced, as opposed to the speed at which traditional reports are processed or consumed.

Nicely worded value prop.

StreamInsight’s runtime performs calculations incrementally whenever possible. This means that the processing only involves the data for the current result and the new event. Unlike in traditional databases, updating a report with aggregates or KPIs with StreamInsight does not require to re-iterate through past data once a new event comes in. Instead, StreamInsight answers continuous queries with a single pass over all the data, which is an important capability for long-running, potentially infinite, standing queries. Incremental processing is one key performance benefit of StreamInsight.

That is rad engineering methinks.

StreamInsight automatically distributes the processing across the available processor cores on the system as well. Thread management and query parallelization are performed automatically by the system.

How cool is that!

Speaking At GSummit

March 19 2012

Gonna be speaking at GSummit, a conference about gamefication, in June, down in San Francisco.  More here.