February 3 2011
Been playing with WebMatrix and have come across some crazy and beautiful code that I really liked in the FourSquare helper on CodePlex. Check this method out, which returns a graph of friends from the fourquare api
/// Returns a list of friends
/// </summary>
/// <param name="accessToken">The access token of the authenticating user.</param>
/// <param name="userId">The Id of the person for whom to pull a friend graph. if not specified, the authenticating user's list of friends will be returned.</param>
public static IList<dynamic> GetFriends(string accessToken, int userId = 0) {
var url = "https://api.foursquare.com/v2/users/{0}/friends?oauth_token={1}";
var client = new WebClient();
var jsonResult = client.DownloadString(string.Format(url, userId == 0 ? "self" : userId.ToString(), accessToken));
var result = Json.Decode(jsonResult);
return new List<dynamic>(result.response.friends.items);
}
Notice how tight this code is. And note the crazy dynamic typing that C#4 provides in combination with the Json.Decode method. If you are wondering where that JSON.Decode method came from, it is from System.Web.Helpers -- you can use this dll anywhere, doesn't have to be with WebMatrix or Razor. Here's a link to the docs on System.Web.Helpers.Json: http://msdn.microsoft.com/en-us/library/system.web.helpers.json(VS.99).aspx
Serialization and JSON have long been painful in .NET because of .NET's strong typing. This got better with the C# dynamic keyword (see this post and this post) but nothing is as elegant as the code above.
Check this example out, which returns a user's FourSquare badges:
/// <summary>
/// Returns badges for a given user.
/// </summary>
/// <param name="accessToken">The access token of the authenticating user</param>
/// <param name="userId">The Id of the user</param>
public static IList<dynamic> GetBadges(string accessToken, int userId = 0) {
var url = "https://api.foursquare.com/v2/users/{0}/badges?oauth_token={1}";
var client = new WebClient();
var jsonResult = client.DownloadString(string.Format(url, userId == 0 ? "self" : userId.ToString(), accessToken));
var result = Json.Decode(jsonResult);
var badges = new List<dynamic>();
var groups = new List<dynamic>(result.response.sets.groups);
var allBadgesGroup = groups.FirstOrDefault(g => g.type == "all");
if (allBadgesGroup != null) {
foreach(var badgeId in allBadgesGroup.items) {
badges.Add(result.response.badges[badgeId]);
}
}
return badges;
}
Notice how the two dynamic lists get created which are then manipulated with a LINQ lambda query. Nice! Having dealt so often with either manually mapping JSON to CLR objects and/or dealing with arrays nested in arrays nested in arrays, I'm absolutely loving this.