Kevin Marshall's Epic Work Blog for Awesome People

@ksmarshall - i <3 software
in

February 2010 - Posts

Json in .NET

I use Json all the time, but I feel like it’s super annoying in .NET.  Typically I’d call some web service that returns Json. In .NET it seems like the best thing to is to define a data contract and use the DataContractSerializer:

[DataContract]
public class Person
{
    [DataMember]
    public string FirstName { get; set; }

    [DataMember]
    public string LastName { get; set; }
}

then to deserialize whatever string of Json I got back. .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

public static Person DeserializeToPerson( string jsonString )
{
   using( MemoryStream ms = new MemoryStream( Encoding.Unicode.GetBytes( jsonString ) ) )
   {
      DataContractJsonSerializer serializer =
         new DataContractJsonSerializer( typeof( Person ) );
      return ( Person )serializer.ReadObject( ms );
    }
}

Feels like a lot of code and I need to define the data contract beforehand which seems a little unnecessary given the dynamic nature of web services and Json. Things like the the memory stream reader and getting bytes off the string are brutal. Why can’t i just pass a string to the JsonDataContractSerializer? Some things seem way more complicated in .NET than they need to be. (cref: Calling REST services in .NET)

What I’d like is something closer to Python.

import simplejson as json
person = json.loads(jsonString)
print person.FirstName

That is pretty easy.

With .NET there are some options like:

System.Json

var data = JsonObject.Load(dataStream);  
Console.Writeline(data["FirstName"])
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

This is pretty close to what I want. The problem is having to cast sub items to things like JsonArray and what not. Secondly, System.Json only works in Silverlight so i can’t use in a web project or desktop app.

Next option is one of the Json libraries like Json.Net. Not that I mind using any 3rd party DLLs, I just think parsing Json is fairly common if you are calling a rest web service and it should be in the framework, maybe I’m the only one that uses json all the time instead of XML but I’d rather use Lotus Notes everyday than parse XML and you know I hates the Lotus Notes.

This site has an interesting approach: http://blog.petegoo.com/archive/2009/10/27/using-json.net-to-eval-json-into-a-dynamic-variable-in.aspx

2 problems for me. I still need to reference Json.Net and there is that ridiculous looking code to convert to Expando object. I just don’t feel comfortable dropping that blob in my code.

Ideally Json parsing would be something similar but handled in the framework:

dynamic person = JsonObject.Load(jsonString)
Console.Writeline(person.FirstName)

That makes me happy. No pre-defining a contract and something in the framework that can take a string of Json and return back a dynamic object. There is so much stuff in the .NET framework, why can’t there be useful helpers that do common tasks like this.

I could totally be missing simpler solutions so feel free to chime in if I’m just an idiot and missing something obvious.

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
Surface Apps on Windows 7

I feel like an idiot for not realizing this sooner, but if you have the Surface touchpack for Win7, you can reference those Microsoft.Surface.Touchpack dlls in your Surface app, remove the regular Surface references and change the namespaces and voila, your Surface app runs on Win 7. How did I not know this sooner? That seems fairly awesome to me. Surface apps running on the 3m 10-touch capacitive screen are fantastic.

Random Ideas for Mobile Advertising

Here are things I’ve been thinking about lately in regards to mobile advertising.

  • Mobile advertising seems really underdeveloped. Maybe in part because it’s difficult to tailor ads to various devices and it’s easy to push the standard banner ad inventory or just punt on originality and buy Google ad words. (side note – who actually clicks on google ads? how does this make money for anyone? they seem so worthless)
  • Local advertising also seems fairly weak. What replaces local business ads in local papers once they all die out? It doesn’t seem effective for those businesses to buy google ad words. The geographic targeting seems limited and again, who clicks on those ads. There seems to be room for someone to come in and dominate advertising on the local level similar to what google did with online ads in general. Make it super easy and cheap for local businesses to display ads to people that are within a given radius of their business.
  • My ideal mobile advertising scenario is close to what Foursquare has done. I check-in at one venue and it alerts me of specials nearby.  Although it’s pretty basic in Foursquare. It seems like it could be way more targeted. I check-in at a bar and it could present offers for drink specials at the bar next door. I love the market that could develop for bidding on what gets displayed when you check-in at certain venues. (Side note – I really want to see sponsored badges on Foursquare seems like a great revenue model. Bonus points if the foursquare app handles mobile payments to track actually getting those badges. Pay for 10 lattes with the foursqaure app, get the latte lover badge)

Ad words and banner ads just seem lazy. Want to target rich people? put a banner ad on forbes. Want to target people who like to ski? buy an ad word for “ski”

Here is what I want in ads:

  • Contextual relevant – This is the whole reason facebook ads are worthless. Just because I like books by Michael Chabon, doesn’t mean I want to see an for his book. I probably already have it and most likely I was just browsing someone’s drunken party pics so I was too distracted to notice the ad anyway.
  • Engaging not just distracting – There are a lot of talented agencies out there, do something good. Make me want to experience the ad instead of just clogging up the intertubes and my screen with your 120x240 animated gif.
  • Demographically relevant – I like that Hulu let’s me choose. I’d rather watch the Smirnof ad than the trailer for the new Sex & the City movie. (Bonus points to Hulu for recognizing that if you show me a 10 second ad instead of 3 mins, I will actually pay attention because it’s not enough time for me to leave the room)
  • Geographically focused – I see ads for Sonic on TV sometimes. I want that slushy and tater tots shown. There is no Sonic in San Francisco. That makes me sad. This shouldn’t happen.
  • Value Added – Mint does this well. I don’t mind seeing credit card or bank ads because they are presented in a helpful manner and again are contextually relevant. The same ad for a “no limits platinum joie de vivre” card shown on espn.com just pisses me off and ad block is going to boot it off my screen

Mobile advertising seems like it could knock all these out. I’m out shopping, I check-in at the Extra Big & Tall show me an ad for a sale on husky fleece pants at Old Navy next door. Maybe include multiple product photos or a little video. You can even scan the ad when i purchase said husky fleece pants to complete the feedback loop. Contextually relevant – I’m shopping, Engaging – some multi-media action, Demographically relevant – I’m a big guy who like comfy pants, Geographically focused – It’s for the store next door and it adds value – I saved some money or you sold me on something I didn’t think I even needed.

Is this too much to ask for? I submit no. Stop wasting time on this pennies per billion impression non-sense. Advertisers should be able to get much higher ROI on ads and I shouldn’t have to be inundated with crap. Ads are always going to be a reality, let's just make them not suck so much.

Kindle App Idea #1

I’m thinking I’ll just start blogging the random ideas I have. Maybe they are good and i will eventually do it or maybe someone else will and I reap the benefits or maybe they suck and nothing happens. Either way, I get a +1 on my blogging stats.

I love my kindle and I think the demise of e-Ink in favor of  reading on a tablets is overrated. The Kindle app store seemed like an obvious idea. Amazon clearly needs to grow the device and lots of people are unwilling to pay $200+ for a device that “just reads books” Not that there is anything wrong with that. Plus they can charge other people for apps without actually having to think of new uses for the Kindle themselves. Well played Amazon.

So idea #1. Facebook on the Kindle. Not original right? I don’t want a Facebook client because I rarely use Facebook anymore. The one really useful thing I like about Facebook is Facebook Connect. I really just want my list of friends and their data. I want the Kindle Facebook app to prompt me for a review after I finish a book and post that to Facebook. Then I want to be able to browse books my friends liked and click to buy. I read a fair amount of books and I’m always interested in recommendations. There are bunch of social book sites out there, but I hate having to enter stuff manually. The Kindle knows when I finish a book so I’d like to just take care of it then automagically. Cross posting the review to Amazon would be nice because I value the ratings on there, but I don’t have “friends” on Amazon so there isn’t an easy way to see what they recommend.

I have no idea what the SDK allows though. It would be great if there was some OnBookCompleted event that you could attach apps to. Also it’s Java and the thought of using Java again makes Kevin the Coder cower in fear. Maybe someone can get JRuby or Jython running on there.

That or it could just tweet the books I read automatically because you really can’t overshare enough on Twitter.

Experimenting with inter-role communication on Azure for caching

It’s been awhile since I’ve used Azure. The new storage libraries are a welcome addition. As a better diagnostic framework and inter-role communication. In a previous Azure project, I wanted to use ASP.NET caching on the web role, but that breaks down if you start to run multiple instances. With inter-role communication it seems like you could use caching on the server as long as you notify the other instances of updates to the cache. I wrote a little prototype to do that. It’s fairly basic and I haven’t tested it on a real deployment or benchmarked etc. Basically this may just be a terrible way of doing things.

First I defined a contract for the cache messages:

   1:  using System.Collections.Generic;
   2:  using System.ServiceModel;
   3:   
   4:  namespace MvcWebRole1.Caching
   5:  {
   6:      /// <summary>
   7:      /// Defines the contract for the cache service.
   8:      /// </summary>
   9:      [ServiceContract]
  10:      public interface ICacheService
  11:      {
  12:          [OperationContract(IsOneWay = true)]
  13:          void Insert(string key, object value);
  14:   
  15:          [OperationContract(IsOneWay = true)]
  16:          void Remove(string key);
  17:      }
  18:  }

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Next I implemented the service for that contract.

   1:  using System;
   2:  using System.Web;
   3:  using System.Diagnostics;
   4:  using System.Linq;
   5:  using System.ServiceModel;
   6:  using System.Threading;
   7:  using Microsoft.WindowsAzure.Diagnostics;
   8:  using Microsoft.WindowsAzure.ServiceRuntime;
   9:   
  10:  namespace MvcWebRole1.Caching
  11:  {
  12:  /// <summary>
  13:      /// Implementation of the WCF cache service.
  14:      /// </summary>
  15:      [ServiceBehavior(
  16:          InstanceContextMode = InstanceContextMode.Single,
  17:          ConcurrencyMode = ConcurrencyMode.Multiple,
  18:  #if DEBUG
  19:          IncludeExceptionDetailInFaults = true,
  20:  #else
  21:          IncludeExceptionDetailInFaults = false,
  22:  #endif
  23:   AddressFilterMode = AddressFilterMode.Any)]
  24:      public class CacheService : ICacheService
  25:      {
  26:          public void Insert(string key, object value)
  27:          {
  28:              HttpRuntime.Cache.Insert(key, value);
  29:              Trace.TraceInformation(String.Format("Added: {0} to key: {1} from broadcast", value, key));
  30:          }
  31:   
  32:          public void Remove(string key)
  33:          {
  34:              HttpRuntime.Cache.Remove(key);
  35:              Trace.TraceInformation(String.Format("Removed key: {0} from broadcast", key));
  36:          }
  37:      }
  38:  }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

That handles the inserts / deletes the cached items when one instance broadcasts a cache update.

The next bit of code is used to cache on one instance and then broadcast that info out to the other roles.

   1:  using System;
   2:  using System.Diagnostics;
   3:  using System.Linq;
   4:  using System.ServiceModel;
   5:  using System.Threading;
   6:  using System.Web;
   7:  using Microsoft.WindowsAzure.Diagnostics;
   8:  using Microsoft.WindowsAzure.ServiceRuntime;
   9:   
  10:  namespace MvcWebRole1.Caching
  11:  {
  12:      public class SynchedCache
  13:      {
  14:          private enum BroadcastType
  15:          {
  16:              Insert,
  17:              Remove
  18:          }
  19:   
  20:          public static void Insert(string key, object value)
  21:          {
  22:              HttpRuntime.Cache.Insert(key, value);
  23:              Trace.TraceInformation(String.Format("Added: {0} to key: {1}", value, key));
  24:              BroadcastCacheUpdate(BroadcastType.Insert, new object[] {key, value});
  25:          }
  26:   
  27:          public static void Remove(string key)
  28:          {
  29:              HttpRuntime.Cache.Remove(key);
  30:              Trace.TraceInformation(String.Format("Removed key: {0}", key));
  31:              BroadcastCacheUpdate(BroadcastType.Remove, new object[] { key });
  32:          }
  33:   
  34:          public static object Get(string key)
  35:          {
  36:              return HttpRuntime.Cache.Get(key);
  37:          }
  38:   
  39:          private static void BroadcastCacheUpdate(BroadcastType type, params object[] args)
  40:          {
  41:              // iterate over all instances of the internal endpoint except the current role - no need to notify itself
  42:              var current = RoleEnvironment.CurrentRoleInstance;
  43:              var endPoints = current.Role.Instances.Where(instance => instance != current)
  44:                              .Select(instance => instance.InstanceEndpoints["InternalHttpIn"]);
  45:   
  46:              foreach (var ep in endPoints)
  47:              {
  48:                  EndpointAddress address =
  49:                      new EndpointAddress(String.Format("http://{0}/InternalHttpIn", ep.IPEndpoint));
  50:                  ICacheService client = WebRole.Factory.CreateChannel(address);
  51:   
  52:                  try
  53:                  {
  54:                      string key = args[0].ToString();
  55:   
  56:                      switch (type)
  57:                      {
  58:                          case BroadcastType.Insert:
  59:                              client.Insert(key, args[1]);
  60:                              break;
  61:   
  62:                          case BroadcastType.Remove:
  63:                              client.Remove(key);
  64:                              break;
  65:                      }
  66:   
  67:                      ((ICommunicationObject)client).Close();
  68:                  }
  69:                  catch (TimeoutException timeoutException)
  70:                  {
  71:                      Trace.TraceError("Unable to notify web role instance '{0}'. The service operation timed out. {1}", 
  72:                          ep.RoleInstance.Id, timeoutException.Message);
  73:                      ((ICommunicationObject)client).Abort();
  74:                  }
  75:                  catch (CommunicationException communicationException)
  76:                  {
  77:                      Trace.TraceError("Unable to notify web role instance '{0}'. There was a communication problem. {1} - {2}", 
  78:                          ep.RoleInstance.Id, communicationException.Message, communicationException.StackTrace);
  79:                      ((ICommunicationObject)client).Abort();
  80:                  }
  81:              }
  82:          }
  83:      }
  84:  }
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 

Finally in your page you can perform operations on the cache like so.

SynchedCache.Insert(key, DateTime.Now.ToString());.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }

That call will then notify all the other web roles running. Of course running AppFabric Caching on Azure would be a much better solution once available, but the inter-role communication is still nice to have for other stuff.