<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.claritycon.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kevin Marshall&amp;#39;s Epic Work Blog for Awesome People</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/default.aspx</link><description>Kevin the Coder is a maverick. Almost like a team of mavericks. </description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>Thoughts on a Microsoft Tablet</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2010/03/15/thoughts-on-a-microsoft-tablet.aspx</link><pubDate>Tue, 16 Mar 2010 00:13:09 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:117417</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;With the iPad, e-reader and slate PC craze, I thought I’d put together some thoughts on a Microsoft tablet device that is not the Courier. Since the content is rather long I made it a word doc - &lt;a title="http://dl.dropbox.com/u/254416/blog/Microsoft%20Tablet%20and%20Print%20Content.docx" href="http://dl.dropbox.com/u/254416/blog/Microsoft%20Tablet%20and%20Print%20Content.docx"&gt;Microsoft Tablet Thoughts&lt;/a&gt;. I have separate thoughts on the Courier concept videos that have been released, but I’ll save those for another post.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=117417" width="1" height="1"&gt;</description></item><item><title>Json in .NET</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2010/02/05/json-in-net.aspx</link><pubDate>Fri, 05 Feb 2010 21:22:17 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:108535</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I use Json all the time, but I feel like it’s super annoying in .NET.&amp;#160; 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:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;[DataContract]
&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Person
{
    [DataMember]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; FirstName { get; set; }

    [DataMember]
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; LastName { get; set; }
}&lt;/pre&gt;

&lt;p&gt;then to deserialize whatever string of Json I got back.
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }&lt;/p&gt;

&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; Person DeserializeToPerson( &lt;span class="kwrd"&gt;string&lt;/span&gt; jsonString )
{
   &lt;span class="kwrd"&gt;using&lt;/span&gt;( MemoryStream ms = &lt;span class="kwrd"&gt;new&lt;/span&gt; MemoryStream( Encoding.Unicode.GetBytes( jsonString ) ) )
   {
      DataContractJsonSerializer serializer =
         &lt;span class="kwrd"&gt;new&lt;/span&gt; DataContractJsonSerializer( &lt;span class="kwrd"&gt;typeof&lt;/span&gt;( Person ) );
      &lt;span class="kwrd"&gt;return&lt;/span&gt; ( Person )serializer.ReadObject( ms );
    }
}&lt;/pre&gt;

&lt;p&gt;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)&lt;/p&gt;

&lt;p&gt;What I’d like is something closer to Python.&lt;/p&gt;

&lt;pre class="csharpcode"&gt;import simplejson &lt;span class="kwrd"&gt;as&lt;/span&gt; json
person = json.loads(jsonString)
print person.FirstName&lt;/pre&gt;

&lt;p&gt;That is pretty easy. &lt;/p&gt;

&lt;p&gt;With .NET there are some options like:&lt;/p&gt;

&lt;p&gt;System.Json&lt;/p&gt;

&lt;pre class="csharpcode"&gt;var data = JsonObject.Load(dataStream);  
Console.Writeline(data[&lt;span class="str"&gt;&amp;quot;FirstName&amp;quot;&lt;/span&gt;])&lt;/pre&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This site has an interesting approach: &lt;a href="http://blog.petegoo.com/archive/2009/10/27/using-json.net-to-eval-json-into-a-dynamic-variable-in.aspx"&gt;http://blog.petegoo.com/archive/2009/10/27/using-json.net-to-eval-json-into-a-dynamic-variable-in.aspx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Ideally Json parsing would be something similar but handled in the framework:&lt;/p&gt;

&lt;pre class="csharpcode"&gt;dynamic person = JsonObject.Load(jsonString)
Console.Writeline(person.FirstName)&lt;/pre&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;I could totally be missing simpler solutions so feel free to chime in if I’m just an idiot and missing something obvious.&lt;/p&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=108535" width="1" height="1"&gt;</description></item><item><title>Surface Apps on Windows 7</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2010/02/04/surface-apps-on-windows-7.aspx</link><pubDate>Thu, 04 Feb 2010 15:10:47 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:108446</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;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.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=108446" width="1" height="1"&gt;</description></item><item><title>Random Ideas for Mobile Advertising</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2010/02/04/random-ideas-for-mobile-advertising.aspx</link><pubDate>Thu, 04 Feb 2010 14:24:33 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:108435</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Here are things I’ve been thinking about lately in regards to mobile advertising.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;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) &lt;/li&gt;    &lt;li&gt;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.&lt;/li&gt;    &lt;li&gt;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.&amp;#160; 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)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;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”&lt;/p&gt;  &lt;p&gt;Here is what I want in ads:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;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.&lt;/li&gt;    &lt;li&gt;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.&lt;/li&gt;    &lt;li&gt;Demographically relevant – I like that Hulu let’s me choose. I’d rather watch the Smirnof ad than the trailer for the new Sex &amp;amp; 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)&lt;/li&gt;    &lt;li&gt;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.&lt;/li&gt;    &lt;li&gt;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&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Mobile advertising seems like it could knock all these out. I’m out shopping, I check-in at the Extra Big &amp;amp; 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. &lt;/p&gt;  &lt;p&gt;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&amp;#39;s just make them not suck so much.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=108435" width="1" height="1"&gt;</description></item><item><title>Kindle App Idea #1</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2010/02/04/kindle-app-idea-1.aspx</link><pubDate>Thu, 04 Feb 2010 13:44:16 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:108433</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;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.&lt;/p&gt;  &lt;p&gt;I love my kindle and I think the demise of e-Ink in favor of&amp;#160; 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.&lt;/p&gt;  &lt;p&gt;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.&lt;/p&gt;  &lt;p&gt;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.&lt;/p&gt;  &lt;p&gt;That or it could just tweet the books I read automatically because you really can’t overshare enough on Twitter.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=108433" width="1" height="1"&gt;</description></item><item><title>Experimenting with inter-role communication on Azure for caching</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2010/02/04/experimenting-with-inter-role-communication-on-azure-for-caching.aspx</link><pubDate>Thu, 04 Feb 2010 12:25:00 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:108430</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;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.&lt;/p&gt;  &lt;p&gt;First I defined a contract for the cache messages:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.ServiceModel;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MvcWebRole1.Caching&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="rem"&gt;/// Defines the contract for the cache service.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;    [ServiceContract]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; ICacheService&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;        [OperationContract(IsOneWay = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; Insert(&lt;span class="kwrd"&gt;string&lt;/span&gt; key, &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;        [OperationContract(IsOneWay = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;        &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;string&lt;/span&gt; key);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;

.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }&lt;/p&gt;

&lt;p&gt;Next I implemented the service for that contract. &lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.ServiceModel;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Threading;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.WindowsAzure.Diagnostics;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.WindowsAzure.ServiceRuntime;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MvcWebRole1.Caching&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    &lt;span class="rem"&gt;/// Implementation of the WCF cache service.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    [ServiceBehavior(&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;        InstanceContextMode = InstanceContextMode.Single,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;        ConcurrencyMode = ConcurrencyMode.Multiple,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;&lt;span class="preproc"&gt;#if&lt;/span&gt; DEBUG&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;        IncludeExceptionDetailInFaults = &lt;span class="kwrd"&gt;true&lt;/span&gt;,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;&lt;span class="preproc"&gt;#else&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        IncludeExceptionDetailInFaults = &lt;span class="kwrd"&gt;false&lt;/span&gt;,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;&lt;span class="preproc"&gt;#endif&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt; AddressFilterMode = AddressFilterMode.Any)]&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CacheService : ICacheService&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Insert(&lt;span class="kwrd"&gt;string&lt;/span&gt; key, &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            HttpRuntime.Cache.Insert(key, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            Trace.TraceInformation(String.Format(&lt;span class="str"&gt;&amp;quot;Added: {0} to key: {1} from broadcast&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;value&lt;/span&gt;, key));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;string&lt;/span&gt; key)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;            HttpRuntime.Cache.Remove(key);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            Trace.TraceInformation(String.Format(&lt;span class="str"&gt;&amp;quot;Removed key: {0} from broadcast&amp;quot;&lt;/span&gt;, key));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }

&lt;p&gt;That handles the inserts / deletes the cached items when one instance broadcasts a cache update.&lt;/p&gt;

&lt;p&gt;The next bit of code is used to cache on one instance and then broadcast that info out to the other roles.&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Diagnostics;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.ServiceModel;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Threading;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.WindowsAzure.Diagnostics;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; Microsoft.WindowsAzure.ServiceRuntime;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MvcWebRole1.Caching&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; SynchedCache&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; BroadcastType&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;            Insert,&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;            Remove&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Insert(&lt;span class="kwrd"&gt;string&lt;/span&gt; key, &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            HttpRuntime.Cache.Insert(key, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            Trace.TraceInformation(String.Format(&lt;span class="str"&gt;&amp;quot;Added: {0} to key: {1}&amp;quot;&lt;/span&gt;, &lt;span class="kwrd"&gt;value&lt;/span&gt;, key));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            BroadcastCacheUpdate(BroadcastType.Insert, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] {key, &lt;span class="kwrd"&gt;value&lt;/span&gt;});&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Remove(&lt;span class="kwrd"&gt;string&lt;/span&gt; key)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            HttpRuntime.Cache.Remove(key);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            Trace.TraceInformation(String.Format(&lt;span class="str"&gt;&amp;quot;Removed key: {0}&amp;quot;&lt;/span&gt;, key));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;            BroadcastCacheUpdate(BroadcastType.Remove, &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] { key });&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; Get(&lt;span class="kwrd"&gt;string&lt;/span&gt; key)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; HttpRuntime.Cache.Get(key);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; BroadcastCacheUpdate(BroadcastType type, &lt;span class="kwrd"&gt;params&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt;[] args)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;        {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;            &lt;span class="rem"&gt;// iterate over all instances of the internal endpoint except the current role - no need to notify itself&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  42:  &lt;/span&gt;            var current = RoleEnvironment.CurrentRoleInstance;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;            var endPoints = current.Role.Instances.Where(instance =&amp;gt; instance != current)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;                            .Select(instance =&amp;gt; instance.InstanceEndpoints[&lt;span class="str"&gt;&amp;quot;InternalHttpIn&amp;quot;&lt;/span&gt;]);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;            &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var ep &lt;span class="kwrd"&gt;in&lt;/span&gt; endPoints)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;            {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;                EndpointAddress address =&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;new&lt;/span&gt; EndpointAddress(String.Format(&lt;span class="str"&gt;&amp;quot;http://{0}/InternalHttpIn&amp;quot;&lt;/span&gt;, ep.IPEndpoint));&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;                ICacheService client = WebRole.Factory.CreateChannel(address);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  52:  &lt;/span&gt;                &lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  53:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  54:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;string&lt;/span&gt; key = args[0].ToString();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  55:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  56:  &lt;/span&gt;                    &lt;span class="kwrd"&gt;switch&lt;/span&gt; (type)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  57:  &lt;/span&gt;                    {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  58:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; BroadcastType.Insert:&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  59:  &lt;/span&gt;                            client.Insert(key, args[1]);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  60:  &lt;/span&gt;                            &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  61:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  62:  &lt;/span&gt;                        &lt;span class="kwrd"&gt;case&lt;/span&gt; BroadcastType.Remove:&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  63:  &lt;/span&gt;                            client.Remove(key);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  64:  &lt;/span&gt;                            &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  65:  &lt;/span&gt;                    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  66:  &lt;/span&gt;&amp;#160;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  67:  &lt;/span&gt;                    ((ICommunicationObject)client).Close();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  68:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  69:  &lt;/span&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (TimeoutException timeoutException)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  70:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  71:  &lt;/span&gt;                    Trace.TraceError(&lt;span class="str"&gt;&amp;quot;Unable to notify web role instance &amp;#39;{0}&amp;#39;. The service operation timed out. {1}&amp;quot;&lt;/span&gt;, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  72:  &lt;/span&gt;                        ep.RoleInstance.Id, timeoutException.Message);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  73:  &lt;/span&gt;                    ((ICommunicationObject)client).Abort();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  74:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  75:  &lt;/span&gt;                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (CommunicationException communicationException)&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  76:  &lt;/span&gt;                {&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  77:  &lt;/span&gt;                    Trace.TraceError(&lt;span class="str"&gt;&amp;quot;Unable to notify web role instance &amp;#39;{0}&amp;#39;. There was a communication problem. {1} - {2}&amp;quot;&lt;/span&gt;, &lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  78:  &lt;/span&gt;                        ep.RoleInstance.Id, communicationException.Message, communicationException.StackTrace);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  79:  &lt;/span&gt;                    ((ICommunicationObject)client).Abort();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  80:  &lt;/span&gt;                }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  81:  &lt;/span&gt;            }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  82:  &lt;/span&gt;        }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  83:  &lt;/span&gt;    }&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  84:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;


.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Finally in your page you can perform operations on the cache like so. &lt;/p&gt;

&lt;pre class="csharpcode"&gt;SynchedCache.Insert(key, DateTime.Now.ToString());.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, 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; }
&lt;/pre&gt;

&lt;p&gt;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.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=108430" width="1" height="1"&gt;</description></item><item><title>fb7 update</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/12/17/fb7-update.aspx</link><pubDate>Fri, 18 Dec 2009 04:54:06 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:99754</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Sorry for the slow response for everyone that messaged me. I didn’t think anyone would actually twitter/facebook message/email me about the app so I wasn’t&amp;#160; really ready to release for general usage. Then I respond to some people to let them try it, doesn’t work and then they leave negative reviews on Facebook. Awesome, thanks. Anyway, there is a new version here - &lt;a title="http://www.facebook.com/apps/application.php?id=130989934307" href="http://www.facebook.com/apps/application.php?id=130989934307"&gt;http://www.facebook.com/apps/application.php?id=130989934307&lt;/a&gt;&amp;#160; If you installed a previous one, just uninstall it.&amp;#160; Please read the README in the zip file. &lt;/p&gt;  &lt;p&gt;If this doesn’t work for people, I’m giving up. I only built this app to enter into the code7contest and I lost to an app that arguably uses no Win7 features, an old demo app from some competitor and&amp;#160; something called “Win7 in my truck” Truly a devastating blow to my motivation to ever touch this code again. &lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=99754" width="1" height="1"&gt;</description></item><item><title>TwtMyCard Upgrade: Now Featuring More Oomph</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/10/06/twtmycard-upgrade-now-featuring-more-oomph.aspx</link><pubDate>Wed, 07 Oct 2009 01:13:47 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:92087</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&lt;a href="http://www.twtmycard.com"&gt;TwtMyCard&lt;/a&gt; was down after some brief problems handling the new geo-location features in Twitter. This is what I get for using someone else’s Twitter library :) &lt;/p&gt;  &lt;p&gt;While it was down I added some caching and other performance improvements.&amp;#160; It’s at least 50% faster to send business cards. Maybe even 51%.&lt;/p&gt;  &lt;p&gt;I also added the &lt;a href="http://www.codeplex.com/Oomph"&gt;oomph plug-in&lt;/a&gt; to the app based on a suggestion from &lt;a href="http://rhizohm.net/irhetoric/"&gt;Karsten Januszewski&lt;/a&gt;. If you had IE with oomph installed previously, you saw a little icon in the upper left to bring out a microformat overlay. Now TwtMyCard has the oomph plug-in embedded so all browsers can get the same microformat goodness.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/TwtMyCardUpgradeNowFeaturingMoreOomph_1004D/image.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/TwtMyCardUpgradeNowFeaturingMoreOomph_1004D/image_thumb.png" width="436" height="337" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you have features you’d like to see added, use the feedback tab on the site. This weekend we may make some upgrades to support &lt;a href="http://hueniverse.com/2009/08/introducing-webfinger/"&gt;web finger&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=92087" width="1" height="1"&gt;</description></item><item><title>Facebook Developer Toolkit 3.0 – ASP.NET MVC Sample</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/10/06/facebook-developer-toolkit-3-0-asp-net-mvc-sample.aspx</link><pubDate>Tue, 06 Oct 2009 19:15:06 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:92001</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;It’s almost time for the long awaited release of the &lt;a href="http://facebooktoolkit.codeplex.com/"&gt;Facebook Developer Toolkit 3.0&lt;/a&gt;, the most awesomest release of the toolkit to date. The new version has great support for ASP.NET, ASP.NET MVC, Silverlight, WinForms, WPF and basically any place you can run .NET. &lt;a href="http://blogs.claritycon.com/blogs/ryan_powers/default.aspx"&gt;Ryan Powers&lt;/a&gt; and I worked on adding MVC support last week. (actually Ryan did all the coding, I just advised). We are going to build out more samples because that seems to have been a slight problem in previous versions.&lt;/p&gt;  &lt;p&gt;So getting started with a Facebook ASP.NET MVC FBML canvas application.&lt;/p&gt;  &lt;p&gt;First create a new app in Facebook. For a simple example you only need to go to the canvas section and set the “Canvas Page URL” and “Canvas Callback URL” and “Render Method” to FBML.&amp;#160; I named my app “FdtMvcSample”. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FacebookDeveloperToolkit3.0.NETMVCSample_A371/image.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FacebookDeveloperToolkit3.0.NETMVCSample_A371/image_thumb.png" width="465" height="304" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Save your Application Secret and API Key from the Basic section somewhere. You’ll need to put those in your web.config later. Now you can setup a new MVC project in Visual Studio. We’ll call it “FdtMvcSample”. &lt;/p&gt;  &lt;p&gt;In your web.config add in your secret and API key:&lt;/p&gt;  &lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;height:100px;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &amp;lt;appSettings&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt;     &amp;lt;add key=&lt;span style="color:#006080;"&gt;&amp;quot;Secret&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;=&lt;span style="color:#006080;"&gt;&amp;quot;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&amp;quot;&lt;/span&gt;/&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;     &amp;lt;add key=&lt;span style="color:#006080;"&gt;&amp;quot;ApiKey&amp;quot;&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;=&lt;span style="color:#006080;"&gt;&amp;quot;bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb&amp;quot;&lt;/span&gt;/&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt; &amp;lt;/appSettings&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;For development of Fbml canvas apps it’s easiest to use IIS and put your machine in the DMZ or port forward. I use gotdns.com for dynamic DNS and set my callback Url to be my dynamic DNS name / IIS virtual directory name.&lt;/p&gt;

&lt;p&gt;You’ll need to configure your MVC project to use IIS instead of the local dev server so Facebook can call back to it. Just make sure your virtual directory name matches the callback URL directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FacebookDeveloperToolkit3.0.NETMVCSample_A371/image_3.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FacebookDeveloperToolkit3.0.NETMVCSample_A371/image_thumb_3.png" width="584" height="149" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In your MVC project you also need to add a reference to the Facebook.dll and Facebook.Web.Mvc.dll.&lt;/p&gt;

&lt;p&gt;In my sample I removed most of the template items from the project. To connect with Facebook, we’ll focus on the HomeController.cs:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:93.22%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;height:400px;max-height:400px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; [HandleError]&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; HomeController : Controller&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;const&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; REQUIRED_PERMISSIONS = &lt;span style="color:#006080;"&gt;&amp;quot;read_stream,publish_stream&amp;quot;&lt;/span&gt;;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Index()&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;         var api = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.GetApi();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;         ViewData[&lt;span style="color:#006080;"&gt;&amp;quot;userId&amp;quot;&lt;/span&gt;] = api.Session.UserId;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color:#008000;"&gt;//ApiKey &amp;amp; Secret in web.config&lt;/span&gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum15"&gt;  15:&lt;/span&gt;     [FacebookAuthorization(IsFbml = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;)]&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Friends()&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum17"&gt;  17:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum18"&gt;  18:&lt;/span&gt;         var api = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.GetApi();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum19"&gt;  19:&lt;/span&gt;         var friends = api.Friends.GetUserObjects();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum20"&gt;  20:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View(friends);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum22"&gt;  22:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum23"&gt;  23:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum24"&gt;  24:&lt;/span&gt;     [FacebookAuthorization(IsFbml = &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;, RequiredPermissions = REQUIRED_PERMISSIONS)]&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum25"&gt;  25:&lt;/span&gt;     &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; ActionResult Stream()&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum26"&gt;  26:&lt;/span&gt;     {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum27"&gt;  27:&lt;/span&gt;         var api = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.GetApi();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum28"&gt;  28:&lt;/span&gt;         var stream_data = api.Stream.Get(&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum29"&gt;  29:&lt;/span&gt;         &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum30"&gt;  30:&lt;/span&gt;         &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; View(stream_data.posts.stream_post);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum31"&gt;  31:&lt;/span&gt;     }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum32"&gt;  32:&lt;/span&gt; }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum33"&gt;  33:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;For MVC, we added attributes to control authentication.&amp;#160; You can specify if it’s Fbml or iFrame or required permissions (and API key / secret if you don’t put them in the web.config) In the above code, the Index action is our public landing page and requires no authentication. The Friends action requires authentication to get the user’s friends’ names and the Stream action requires read_stream and publish_stream permission. The attribute runs before you action and redirects to the Facebook app authorization screen if needed and then redirects back to the action. One thing to note, adding permissions like that requires us to check which permissions are already granted and redirect to the prompt permission screen. Since that requires a call to Facebook each time the action is called, it would be best to get all the permissions granted on some initial landing page. Plus the user can get that out of the way upfront. If you need page specific permissions, then it would be best to use the Fbml fb:prompt-permission in your view before those actions are called.&amp;#160; This method is fine also, but just be aware of the impact.&lt;/p&gt;

&lt;p&gt;On the controller we added an extension method to retrieve the Api object for making making Facebook calls based on the users current Facebook session. (You can optionally pass in the key/secret if they are not in the web.config)&lt;/p&gt;

&lt;p&gt;In this simple example, I’m just passing the list of friends as the model to bind to the view.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &amp;lt;%@ Page Title=&lt;span style="color:#006080;"&gt;&amp;quot;&amp;quot;&lt;/span&gt; Language=&lt;span style="color:#006080;"&gt;&amp;quot;C#&amp;quot;&lt;/span&gt; MasterPageFile=&lt;span style="color:#006080;"&gt;&amp;quot;~/Views/Shared/Site.Master&amp;quot;&lt;/span&gt; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt;     Inherits=&lt;span style="color:#006080;"&gt;&amp;quot;System.Web.Mvc.ViewPage&amp;lt;IList&amp;lt;user&amp;gt;&amp;gt;&amp;quot;&lt;/span&gt; %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;&amp;#160; &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt; &amp;lt;asp:Content ID=&lt;span style="color:#006080;"&gt;&amp;quot;Content1&amp;quot;&lt;/span&gt; ContentPlaceHolderID=&lt;span style="color:#006080;"&gt;&amp;quot;MainContent&amp;quot;&lt;/span&gt; runat=&lt;span style="color:#006080;"&gt;&amp;quot;server&amp;quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;     &amp;lt;h2&amp;gt;Friends&amp;lt;/h2&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;     &amp;lt;ul&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;     &amp;lt;% &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (user u &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; Model)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;        { %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;         &amp;lt;li&amp;gt;&amp;lt;%= u.name %&amp;gt;&amp;lt;/li&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;     &amp;lt;% }%&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;     &amp;lt;/ul&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt; &amp;lt;/asp:Content&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;and in the master page I have some simple Fbml with a helper for generating the tabs.&lt;/p&gt;

&lt;div id="codeSnippetWrapper"&gt;
  &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;
    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &amp;lt;%@ Master Language=&lt;span style="color:#006080;"&gt;&amp;quot;C#&amp;quot;&lt;/span&gt; Inherits=&lt;span style="color:#006080;"&gt;&amp;quot;System.Web.Mvc.ViewMasterPage&amp;quot;&lt;/span&gt; %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; &amp;lt;%@ Import Namespace=&lt;span style="color:#006080;"&gt;&amp;quot;FdtMvcSample.Helpers&amp;quot;&lt;/span&gt; %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt; &amp;lt;div id=&lt;span style="color:#006080;"&gt;&amp;quot;header&amp;quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt; &amp;lt;fb:tabs&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;   &amp;lt;%= Fbml.TabItem(&lt;span style="color:#006080;"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;Index&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ViewContext) %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;   &amp;lt;%= Fbml.TabItem(&lt;span style="color:#006080;"&gt;&amp;quot;Friends&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;Friends&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ViewContext) %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;   &amp;lt;%= Fbml.TabItem(&lt;span style="color:#006080;"&gt;&amp;quot;Stream&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;Stream&amp;quot;&lt;/span&gt;, &lt;span style="color:#006080;"&gt;&amp;quot;Home&amp;quot;&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.ViewContext) %&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt; &amp;lt;/fb:tabs&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt; &amp;lt;/div&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt; &amp;lt;div id=&lt;span style="color:#006080;"&gt;&amp;quot;main_content&amp;quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt; &amp;lt;asp:ContentPlaceHolder ID=&lt;span style="color:#006080;"&gt;&amp;quot;MainContent&amp;quot;&lt;/span&gt; runat=&lt;span style="color:#006080;"&gt;&amp;quot;server&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt; &amp;lt;/div&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum13"&gt;  13:&lt;/span&gt; &amp;lt;div id=&lt;span style="color:#006080;"&gt;&amp;quot;footer&amp;quot;&lt;/span&gt;&amp;gt;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum14"&gt;  14:&lt;/span&gt; &amp;lt;/div&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The tab helper could most likely be more elegant. I just threw that in there to see how we’d do FBML helpers. We discussed making a full set of FBML helpers but that would be a significant effort and I’m not how much they are needed. &lt;/p&gt;

&lt;p&gt;So that’s all the code needed to build a simple Facebook ASP.NET MVC FBML canvas application. &lt;/p&gt;

&lt;p&gt;You can download the code &lt;a href="http://employees.claritycon.com/kmarshall/blog/files/facebook/FdtMvcSample.zip"&gt;here&lt;/a&gt;.&amp;#160; I put the full source of the required FDT components, but after the 3.0 release you can just use the new binaries.&lt;/p&gt;

&lt;p&gt;If you would like to see a more complex example or have questions, just post in the &lt;a href="http://facebooktoolkit.codeplex.com/Thread/List.aspx"&gt;forums&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=92001" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Facebook+Developer+Toolkit/default.aspx">Facebook Developer Toolkit</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category></item><item><title>SilverWave: Wrapper for building Google Wave Gadgets in Silverlight</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/10/05/silverwave-wrapper-for-building-google-wave-gadgets-in-silverlight.aspx</link><pubDate>Mon, 05 Oct 2009 23:45:38 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:91728</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I played around with Wave when I got access to the developer sandbox but quickly lost interest. The technology is cool, but I have no idea what the hell is going on in a Wave. Usability wise I think it’s like MySpace with a slightly less obnoxious UI. Once there are more than 5 people in a Wave and 10+ messages it’s nigh impossible to follow. With the recent launch of the non-sandbox, I thought I’d try again. Performance seems better now at least. Even in Chrome it felt sluggish and Chrome normally rips through Javascript. I think IE8 would just die on that much Javascript – IE8: “Hey, look, this is too much code for me to process and it’s going to be awhile, how about you just check out this web slice instead? Have you heard of Accelerators? I can pop up one of those for you”&lt;/p&gt;  &lt;p&gt;So Silverlight and Wave. Maybe it doesn’t make sense to put Silverlight in a Wave, but there are still some things you could do in SL better than HTML5 + JS. Plus I like the irony of having Silverlight in Google’s flagship RIA example. SilverWave is a managed wrapper around the Google Wave gadget APIs so you can code something like:&lt;/p&gt;  &lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:200px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; TestWaveAPIs()&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum3"&gt;   3:&lt;/span&gt;     txtIsInWaveContainer.Text = WaveManager.Wave.IsInWaveContainer().ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum4"&gt;   4:&lt;/span&gt;     var viewer = WaveManager.Wave.GetViewer();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum5"&gt;   5:&lt;/span&gt;     txtViewer.Text = viewer.ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum6"&gt;   6:&lt;/span&gt;     txtHost.Text = WaveManager.Wave.GetHost().ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum7"&gt;   7:&lt;/span&gt;     txtGetParticipantById.Text = WaveManager.Wave.GetParticipantById(viewer.Id).ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum8"&gt;   8:&lt;/span&gt;     txtParticipants.ItemsSource = WaveManager.Wave.GetParticipants();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum9"&gt;   9:&lt;/span&gt;     txtIsPlayback.Text = WaveManager.Wave.IsPlayback().ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum10"&gt;  10:&lt;/span&gt;     txtGetTime.Text = WaveManager.Wave.GetTime().ToLocalTime().ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:white;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum11"&gt;  11:&lt;/span&gt;     txtState.Text = WaveManager.Wave.State.ToString();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;border-right-style:none;background-color:#f4f4f4;margin:0em;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;font-size:8pt;border-left-style:none;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#606060;" id="lnum12"&gt;  12:&lt;/span&gt; }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Everything is strongly typed so you can do things like bind to a participant object. The WaveManger class handles all the HTML bridging and callbacks for events like wave state updated. It’s pretty simple and you can get the code here &lt;a href="http://code.google.com/p/silverwave/"&gt;http://code.google.com/p/silverwave/&lt;/a&gt; along with some more instructions. The cross domain stuff seems a little flakey though. Silverlight was loading fine on Saturday for me, then it seems to break. I think the problem is hosting the xap on a non-ssl domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/SilverWaveSilverlightWrapperforbuildingG_E57B/image.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/SilverWaveSilverlightWrapperforbuildingG_E57B/image_thumb.png" width="385" height="382" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;When it works, the sample on code.google.com looks like the above.&lt;/p&gt;

&lt;p&gt;I still have no ideas for an actual Silverlight gadget in a Wave because I have no idea what I’d use Wave for or what a good gadget in Wave would do.&amp;#160; This was just to tide me over until I can further Microsoftize Wave with a wave bot in Azure. Sadly bots only work on app engine for the moment.&lt;/p&gt;

&lt;p&gt;If you want to contribute to the code let me know. As of right now I implemented all the wave methods, but there are probably some other useful things that could be added. &lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=91728" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Google+Wave/default.aspx">Google Wave</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>WhiteboardFlow: Sketchflow like Multi-touch Windows 7 whiteboard</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/25/whiteboardflow-sketchflow-like-multi-touch-windows-7-whiteboard.aspx</link><pubDate>Fri, 25 Sep 2009 17:28:59 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:89699</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;So FB7 was our fallback &lt;a href="http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/25/fb7-facebook-desktop-notifications-for-windows-7.aspx"&gt;Code7&lt;/a&gt; contest application. It’s a teaser. Our second entry is going to be epic. At Clarity we really like &lt;a href="http://www.microsoft.com/expression/products/SketchFlow_OverView.aspx"&gt;SketchFlow&lt;/a&gt;, but there are some things that would make it cooler I think. When working in a group we usually just draw on a whiteboard to map out the application flow. It’s not as easy to have a collaborative session sitting at PC and using Blend. &lt;/p&gt;  &lt;p&gt;Our plan for the second entry is to build a large multi-touch display to put up like a whiteboard. Using your fingers like markers you can draw UI elements like windows, buttons, text, etc. The app will then recognize certain gestures. For example, you draw a really large rectangle and the app assumes you want a window. It converts that to a window. If you draw a smaller rectangle inside of the window, it’ll convert it to a control where you can hold two fingers on it to bring up a fly out menu and convert to a textbox or button. Small rectangles are converted to checkboxes and small circles, radio buttons.&lt;/p&gt;  &lt;p&gt;Here is the first prototype of the gesture recognition for controls.&lt;/p&gt; &lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/FIYKn6hLAl4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/FIYKn6hLAl4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In future versions we’re adding a marker drawn style, text recognition to convert labels/titles to hand drawn font, flow recognition (draw an arrow from a button to another window to link the two), network support for remote multi-user action, manipulation to resize controls and then try to work out a way to get this into SketchFlow. The basic idea is that it’s a simple, collaborative first step before touching up in SketchFlow. I’ll post some more prototypes next week as we finish it up for the contest.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=89699" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Multi-touch/default.aspx">Multi-touch</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Code7/default.aspx">Code7</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/SketchFlow/default.aspx">SketchFlow</category></item><item><title>FB7: Facebook Desktop Notifications for Windows 7</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/25/fb7-facebook-desktop-notifications-for-windows-7.aspx</link><pubDate>Fri, 25 Sep 2009 07:27:42 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:89663</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I was recently using the &lt;a href="http://www.facebook.com/apps/application.php?id=219303305471&amp;amp;v=info"&gt;Facebook Desktop Notifications&lt;/a&gt; app for OSX. Pretty cool &amp;amp; useful app. The shortcut layout reminded me of the Win7 jump lists and I wanted to build something for the &lt;a href="https://www.code7contest.com/Default.aspx"&gt;Code 7 contest&lt;/a&gt;. Since I was also doing some work on the &lt;a href="http://www.codeplex.com/FacebookToolkit"&gt;Facebook Developer Toolkit&lt;/a&gt; (version 3.0 is awesome), this seemed like a nice app to build. Here is what I have so far:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Jump list shortcuts to Facebook pages and new messages / notifications&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The jump list provides quick access to your latest messages, notifications and general Facebook pages.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb.png" width="222" height="404" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Progress indicator when polling Facebook and unread message/notification count overlay&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;It was nice to bust out my old school GDI drawing skills to render the little number on the overlay icon.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_3.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb_3.png" width="153" height="86" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Toast when new messages / notifications arrive&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The toast message fades in and out for about 3 seconds when something new arrives. FB7 polls Facebook every 5 mins for new items. If you only have one new item it will just display the subject or title or snippet.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_4.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb_4.png" width="295" height="142" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Global keyboard shortcut to update status&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Defaults to ctrl+alt+space, but you can change it to anything. The window pops up with a little blur animation.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_5.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb_5.png" width="350" height="204" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can also attach videos or photos via drag and drop or by clicking to browse your Win7 libraries.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_6.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb_6.png" width="288" height="324" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Settings screen&lt;/strong&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;You can toggle to Facebook Lite mode so all jump lists shortcuts link to the equivalent Facebook Lite page.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_7.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb_7.png" width="309" height="277" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Custom thumbnail to show current profile photo &amp;amp; status&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_8.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/FB7FacebookDesktopNotificationsforWindow_12612/image_thumb_8.png" width="291" height="236" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Here is a video of the application in action.&lt;/p&gt; &lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/Sb2aKT6NPRI&amp;amp;hl=en&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/Sb2aKT6NPRI&amp;amp;hl=en&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x2b405b&amp;amp;color2=0x6b8ab6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;It probably would have made more sense to make an application that runs in the tray, but I wanted to experiment with some of the new Win 7 shell integration features. I’m fairly sure I violated every UI guideline in the Win 7 shell integration guide and also most of Facebook’s terms by using their icons / logos. Also, it’s just a notification app, you can’t view your news feed from inside the app – the idea was just to port the OSX Desktop Notification app to Win 7. &lt;/p&gt;  &lt;p&gt;Win7 has definitely grown on me. As a developer I wasn’t particularly excited about some of the shell integration points, but I think you can add some pretty nice features to your app with them. As an end user, Win7 is definitely a big improvement on Vista. Feels faster, has some nice UI tweaks and is overall really stable.&lt;/p&gt;  &lt;p&gt;If you are interested in trying out the application to help test, email me at kmarshall at claritycon.com or send me a message on Twitter (@&lt;a href="http://twitter.com/ksmarshall"&gt;ksmarshall&lt;/a&gt;) or on &lt;a href="http://www.facebook.com/imkevin"&gt;Facebook&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=89663" width="1" height="1"&gt;</description><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Facebook+Developer+Toolkit/default.aspx">Facebook Developer Toolkit</category><category domain="http://blogs.claritycon.com/blogs/kevin_marshall/archive/tags/Multi-touch/default.aspx">Multi-touch</category></item><item><title>Building Cloud Applications: Windows Azure vs. Google App Engine</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/09/building-cloud-applications-windows-azure-vs-google-app-engine.aspx</link><pubDate>Wed, 09 Sep 2009 18:49:40 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:88755</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I’ve used Windows Azure to host a few apps and Google App Engine to host one small app. Clearly this qualifies me to make a definitive post comparing&amp;#160; the two. I’m leaving Amazon out of my cloud app comparison because a) Azure and App Engine seem like more direct competitors and b) I have almost zero practical knowledge of Amazon’s offerings – It’s all theoretical. &lt;/p&gt;  &lt;p&gt;In general, I’m excited about cloud computing and I like the options that are out there. For small departmental LOB apps it’s nice to have a quick place to deploy to without requiring new server environments. For something like a Facebook app that might need enormous scale quickly, Azure or GAE makes this really easy.&amp;#160; I think Microsoft did a great job of creating a product to ease people from stand alone windows servers to a cloud environment with hosted services, azure and the ability to mix on and off premise pieces of an application. &lt;/p&gt;  &lt;p&gt;Here are some reasons to use Google App Engine (GAE) and advantages of the platform compared to Azure&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Want to write code in Java, Python/Django or any language that runs on the JVM &lt;/li&gt;    &lt;li&gt;Need integrated mail functionality      &lt;ul&gt;       &lt;li&gt;Azure requires your own SMTP server outside of the cloud environment &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Need integrated XMPP messaging      &lt;ul&gt;       &lt;li&gt;Again, Azure would need an external server. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Need scheduled processing jobs      &lt;ul&gt;       &lt;li&gt;You can be creative and write something with queues and/or worker roles or perhaps a service running elsewhere to ping your web server on a schedule to run a job. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Need distributed caching via memcahe      &lt;ul&gt;       &lt;li&gt;There has been some talk of adding Velocity to Azure which would be comparable to memcache. Otherwise, if you only have one web instance you can use ASP.NET caching. If you have multiple web instances, then you need a way to invalidate the other server’s cache. Inter-role communication is coming soon which would make this possible. In the mean time you could use .NET service bus to communicate between web role instances (in theory it seems like this would work) &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Want mostly free hosting for small applications – GAE has a &lt;a href="http://code.google.com/appengine/kb/billing.html#freequota" target="_blank"&gt;free quota&lt;/a&gt;       &lt;ul&gt;       &lt;li&gt;Azure is free up to a limit in the CTP, but once live nothing is &lt;a href="http://www.microsoft.com/azure/pricing.mspx" target="_blank"&gt;free&lt;/a&gt;. I’d really like to see Microsoft keep some free version for developers to experiment with or include CTP-like free quotas to BizSpark members. Developers like to tinker and release small apps. If App Engine is free, they are going to chose that and will probably be less likely to chose Azure once comfortable with GAE. It seems like a good approach to provide some level of free support until an app becomes large enough where a developer can afford to pay (or it’s too costly to provide them free service) &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;GAE has a ridiculously fast deployment time. One click in GAE launcher or a console command and the application deploys in less than a minute      &lt;ul&gt;       &lt;li&gt;Azure deployment is just brutally slow. Make a sandwich, grab a good book – it’s going to be awhile. This is especially an issue when you consider the next bullet point. Every time you deploy to Azure it’s provisioning a new virtual machine unlike GAE which is just copying files. I’m sure there are good reasons why this needs to be done, but I really wish it had some quick deploy / file copy option. There is nothing more gut wrenching then waiting 30 mins to finish deploying and you forgot to to change one line of code. Now you are stuck waiting another 30-45 mins to delete the current instance and redeploy. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;If it runs locally in GAE, chances are very high it will run the same in GAE once deployed      &lt;ul&gt;       &lt;li&gt;Some things I do that work fine locally in Azure don’t work in the cloud. 99% of the time it’s my fault so I’m not blaming Azure, but it seems to happen to me somewhat regularly. Unfortunately I don’t have specific examples, but I’ll Twitter them as they come up. This wouldn’t really be an issue for me if I could quickly view logs and redeploy on Azure. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;GAE has excellent utilities for CRUD operations on your data store      &lt;ul&gt;       &lt;li&gt;Once you deploy to the cloud in Azure you can’t easily view/delete/edit/add entities to the storage systems. I wrote my own utility which I’ll post soon to do that and there are some others out there with various levels of functionality. It’s still kind of a pain though and the ability to do this would help debugging. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;GAE is fast to change code. For most code changes you can just change the line and refresh the browser.      &lt;ul&gt;       &lt;li&gt;In Azure this can be a real pain. First it’s managed code so you need to compile. Second, debugging Azure deploys itself to the local dev fabric. If you make a change to one line of CSS or JS or HTML in Visual Studio, then you have to stop debugging, change the line and re-run which takes a min. or two. When you are making small changes like a line of Javascript this is super tedious. It almost made me cry. I had to make a 2nd web app in my project, move the js/css into there and change the links to reference those in the web role. That way I could make changes without having to stop my local development server. This can’t be right. It’s awful. Clearly I’m an idiot and am doing something wrong. I really don’t understand how people are building complex UIs in a web app if this is the case. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;GAE lets you view logs in real-time      &lt;ul&gt;       &lt;li&gt;Viewing logs in GAE can be done through the apps dashboard. In Azure I need to go to the portal, click to copy the logs to the Blob store which takes some time. Then I have to compile the Drive Mount powershell script, configure with my credentials, run it, mount the drive, browse to the log dir on the blob store, copy them locally and view. Granted once you have the script compiled and the drive mounted you only need to click copy on the portal and copy them via the command line and view. Still it’s slow and cumbersome. For a CTP it’s mildly acceptable, but Microsoft really needs to add some sort of online log viewer if I’m going to be paying for this. The only way to troubleshoot what’s wrong when you deploy to the cloud is via the logs and Azure makes this somewhat painful. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Simple &lt;a href="http://code.google.com/appengine/docs/python/datastore/creatinggettinganddeletingdata.html" target="_blank"&gt;API&lt;/a&gt; for accessing GAE data store       &lt;ul&gt;       &lt;li&gt;Part of this is just comparing python to C#, but it’s a lot fewer lines of code to define a model and do any CRUD operations on it in GAE &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Some useful data store functionality      &lt;ul&gt;       &lt;li&gt;GAE supports list properties and referencing other entities. In Azure you could just serialize a list or convert to JSON to store multiple values, but not as convenient. The references property also makes transitioning from a relational store to a flat table storage easier. Azure it’s a little more of a pain to get referenced entities and it’s all manual. &lt;/li&gt;        &lt;li&gt;Secondly you don’t have to worry about creating unique row keys in GAE. In Azure each entity needs to specify a row key and partition key. They also have to be named RowKey and ParitionKey which seems odd when you can specify the attribute: [DataServiceKey(&amp;quot;PartitionKey&amp;quot;, &amp;quot;RowKey&amp;quot;)] Then I need to add some comments and remember my row key is really my username or something. &lt;/li&gt;        &lt;li&gt;Indexes. In GAE you can add indexes to some columns with some restriction. For now Azure doesn’t support indexes on any columns besides the key&lt;/li&gt;        &lt;li&gt;GAE supports transactions which is helpful when changing multiple dependent entities &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;No hassle config – you basically have an app that scales without worrying about partitioning data or adding instances.      &lt;ul&gt;       &lt;li&gt;In GAE the app automatically scales. In Azure you need to change the config to add new web or worker role instances. This requires more monitoring and it’s also harder to write worker roles that balance effectively especially since in code you can’t tell how many are running. You also have to think more about partitioning your data, but I suppose that might let you you do more performance tuning. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Development environment on Linux/OSX/Windows      &lt;ul&gt;       &lt;li&gt;Azure development requires Windows. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Here are some reasons to use Windows Azure and advantages of the platform compared to GAE:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Want to write code in PHP or .NET (C#, F#, VB.NET).      &lt;ul&gt;       &lt;li&gt;It’s interesting how between the two they support most languages but there isn’t much overlap unless you try to do something crazy like run PHP on the JVM or IronPython on Azure. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Want interactive debugging while developing locally. Some people log extensively, but I like to live by the breakpoint.      &lt;ul&gt;       &lt;li&gt;Actually this is probably possible in Eclipse for GAE, but I haven’t tried that out. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Need background processing. In Azure you can have a worker role running 24/7.      &lt;ul&gt;       &lt;li&gt;In GAE you need to specify a cron job to run on a schedule. The cron job needs to ping a url which executes a task, but that task is limited by the request timeout. Basically you have 30 seconds to finish processing while Azure can run for hours on a single task. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Need flexible queue storage. In Azure, queues work like I’d expect a queue to work. I put data in, something gets it out. You can specify time to live and the visibility time when some process grabs a message off the queue      &lt;ul&gt;       &lt;li&gt;In GAE the queues work a little differently. It’s nice that you enqueue data with the function to call, but you are still limited by the 30 second time limit to execute that work. The support is also still experimental &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;More robust blob storage. In Azure there are great methods are dividing up large files into blocks and retrying failed blocks. This makes uploading large blobs easier.      &lt;ul&gt;       &lt;li&gt;GAE blobs are stored in the regular data store and are limited to 1MB. Azure supports 50GB blobs. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Staging environment. While deployment to staging is slow in Azure, it only takes a second to switch from staging to deployment. This is great for cutting over new builds.      &lt;ul&gt;       &lt;li&gt;In GAE you’d have to manually create a 2nd staging site and manage that process. You could probably write some scripts to do all this, but it’s built in and easy in Azure &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;Relational and Table Storage      &lt;ul&gt;       &lt;li&gt;If the thought of using a non-relational store makes you cower in fear then Microsoft also provides SQL Azure – the same relational db running locally available in new cloud friendly form. Personally I prefer one giant table, but the option is nice. &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;.NET service bus integration. If you have Active directory you can somewhat easily integrate authentication between your apps on Azure. Although most of the .NET service bus infrastructure is REST-based so you could probably use some of those features in GAE with a little bit of work. You could also do things like host your data store locally in SQL server behind your firewall, but host the web front-end in Azure. This lets you gradually migrate to full on cloud apps or keep sensitive data in house or reuse some existing non-cloud services. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Between the two I think you have good options depending on the type of apps to build. The development time on GAE feels faster to me because of deployment, log viewing, and probably just less code in Python vs. C# The cost of GAE makes it a little cheaper to launch new applications.&amp;#160; In some cases background processing or relational storage are a must and Azure is a better choice. Or if you need to leverage some onsite data or services, then Azure is great. If you are porting an existing app then your choice is most likely made by which language the current app is written. &lt;/p&gt;  &lt;p&gt;While I really do like Azure, the previously mentioned development time issues combined with my Visual Studio not being able to make CSS/JS/HTML changes on the fly make me hesitant to use Azure for casual projects. I probably spent around 30 hrs to code all of TwtMyCard on Azure. In App Engine I maybe could have saved a few hours because of writing a little less code in Django/Python and the GAE data store. But on top of the 30 hrs in Azure I easily wasted 10-15 hrs with deployment, tracking down issues in the cloud, getting the logs and fixing HTML/CSS/JS. &lt;/p&gt;  &lt;p&gt;If Azure added web viewable logs, fixed the VS issue, supported Velocity, supported indexes and added inter-role communication, I’d be so happy.&lt;/p&gt;  &lt;p&gt;Regardless of hosting choice, I love not having to mess around with web server or database configuration to deploy an application that scales reasonably well (in theory – still waiting for Silverlight Draw or TwtMyCard to reach 1 million users to verify). &lt;/p&gt;  &lt;p&gt;In the future I’ll update this post as I use them both more or people tell me I’m wrong about some things or the products evolve.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=88755" width="1" height="1"&gt;</description></item><item><title>Silverlight Drawing via Twitter and Google App Engine</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/09/silverlight-drawing-via-twitter-and-google-app-engine.aspx</link><pubDate>Wed, 09 Sep 2009 07:02:31 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:88746</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I am currently in my Twitter app development phase. I will not rest until all possible uses for Twitter are exhausted. If I can’t monitor the contents of my fridge via Twitter, I will consider this year a failure. So after &lt;a href="http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/09/twtmycard-exchanging-business-cards-via-twitter.aspx" target="_blank"&gt;TwtMyCard&lt;/a&gt; with Azure I thought I’d try out App Engine. For a long time I really wanted to build &lt;a href="http://layertennis.com/" target="_blank"&gt;layer tennis&lt;/a&gt; with Silverlight canvases. I think I’ve mentioned this idea to &lt;a href="http://adamkinney.com/" target="_blank"&gt;Adam Kinney&lt;/a&gt; at every event I’ve seen him at since Silverlight was launched. Since it’s been a few years without progress, I clearly need to take some baby steps. So the first milestone in Silverlight layer tennis is dynamically parsing and adding Xaml. Not super hard, but I wanted something simple to build on App Engine and Google data storage in a few hours. You can check out the app at &lt;a href="http://silverlightdraw.appspot.com/"&gt;http://silverlightdraw.appspot.com/&lt;/a&gt; To use, you just have to tweet a line of xaml to @sldraw.&amp;#160; To maximize your 140 chars you can alias Xaml. e.g.&lt;/p&gt;  &lt;p&gt;&amp;lt;#e Fill=&amp;quot;Yellow&amp;quot; #h=&amp;quot;100&amp;quot; #w=&amp;quot;200&amp;quot; #st=&amp;quot;2&amp;quot; #s=&amp;quot;Black&amp;quot;&amp;gt; is the same as   &lt;br /&gt;&amp;lt;Ellipse Fill=&amp;quot;Yellow&amp;quot; Height=&amp;quot;100&amp;quot; Width=&amp;quot;200&amp;quot; StrokeThickness=&amp;quot;2&amp;quot; Stroke=&amp;quot;Black&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;You can also click on any of the Xaml tweets in the the sidebar to spotlight that layer or click download to get the current Xaml on the canvas.&lt;/p&gt;  &lt;p&gt;As for the using Silverlight on App Engine, it’s pretty easy to communicate via json. App Engine can return any data as json through &lt;a href="http://simplejson.googlecode.com/svn/tags/simplejson-2.0.9/docs/index.html" target="_blank"&gt;simplejson&lt;/a&gt; and you can consume json in Silverlight via the &lt;a href="http://msdn.microsoft.com/en-us/library/system.json.jsonobject(VS.95).aspx" target="_blank"&gt;JSONObject&lt;/a&gt;. The only thing special you need to do in the app.yaml for App Engine is to add a handler for Silverlight:&lt;/p&gt;  &lt;p&gt;handlers:   &lt;br /&gt;- url: /content/bin/SLDraw.xap    &lt;br /&gt;&amp;#160; static_files: content/bin/SLDraw.xap    &lt;br /&gt;&amp;#160; upload: content/bin/SLDraw.xap    &lt;br /&gt;&amp;#160; mime_type: application/x-silverlight-app&lt;/p&gt;  &lt;p&gt;On App Engine there is a cron job to query Twitter every minute for new Xaml tweets so feel free to tweet some xaml and see the results in near real-time. &lt;/p&gt;  &lt;p&gt;If you’d like to see the code, you can download it &lt;a href="http://dl.getdropbox.com/u/254416/blog/sldraw.zip" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=88746" width="1" height="1"&gt;</description></item><item><title>TwtMyCard : Exchanging Business Cards via Twitter</title><link>http://blogs.claritycon.com/blogs/kevin_marshall/archive/2009/09/09/twtmycard-exchanging-business-cards-via-twitter.aspx</link><pubDate>Wed, 09 Sep 2009 05:41:41 GMT</pubDate><guid isPermaLink="false">da947a97-509e-40e6-bbb5-1443ad47bf4e:88744</guid><dc:creator>kmarshall</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&lt;a href="http://twitter.com/anandiyer" target="_blank"&gt;Anand Iyer&lt;/a&gt; told me about an idea he had for an application to exchange business cards over Twitter called TwtMyCard.&amp;#160; I wanted to experiment a bit with ASP.NET MVC, Windows Azure and Twitter bots so I offered to help build the first version. Plus I thought it would make a nice demo application for some of the work we do at Clarity since we can’t always show off the applications we build for clients. And so &lt;a href="http://www.twtmycard.com/" target="_blank"&gt;TwtMyCard&lt;/a&gt; was born. Anand already wrote a nice &lt;a href="http://www.artificialignorance.net/blog/twtmycard/exchange-business-cards-on-twitter-twtmycard/" target="_blank"&gt;post&lt;/a&gt; describing the functionality and benefits. &lt;/p&gt;  &lt;p&gt;Here are some of the reasons I like the idea for the application:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Unlike Facebook, it’s easy to export out your contacts – No walled garden here, it’s your data where you want it&lt;/li&gt;    &lt;li&gt;You can quickly add your profile by uploading your vCard from Outlook and avoid the pain of entering the same profile information into a new site&lt;/li&gt;    &lt;li&gt;Lots of people already network via Twitter so this seems like a natural extension&lt;/li&gt;    &lt;li&gt;You don’t have to follow each other on Twitter or create some relationship on another social network - If you just want to exchange contact info, you can do that with TwtMyCard&lt;/li&gt;    &lt;li&gt;Better for the environment – Unless your business card is &lt;a href="http://www.youtube.com/watch?v=4YBxeDN4tbk" target="_blank"&gt;die-cut, foil-stamped and embossed&lt;/a&gt; , it’s probably going to just get thrown out at some point&lt;/li&gt;    &lt;li&gt;Since you can send a tweet via SMS, you can use TwtMyCard from any mobile phone. Although if you are using a Twitter client you should check out &lt;a href="http://gadfly.claritycon.com/" target="_blank"&gt;Gadfly&lt;/a&gt; (gratuitous cross-promotional plug).&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Here are a few other notes on the functionality:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You don’t need to create a login for TwtMyCard. You login to Twitter via &lt;a href="http://oauth.net/" target="_blank"&gt;OAuth&lt;/a&gt; and it passes a token to TwtMyCard to authenticate you. This way we don’t collect your Twitter credentials and you have one less password to remember.&lt;/li&gt;    &lt;li&gt;Your business card is marked private by default meaning that you have to send it someone before they can view it unless you mark your profile public. The cards are sent via the TwtMyCard account so it will show up in the recipient’s feed as a mention. Through the TwtMyCard site you can also send cards from your own account or a direct message.&lt;/li&gt;    &lt;li&gt;You can quickly import your profile by uploading a vCard. You can also export anyone’s contact info as a vCard or by exporting to Google contacts. (Export to Live contacts coming soon)&lt;/li&gt;    &lt;li&gt;Everyone’s saved card uses the &lt;a href="http://microformats.org/wiki/hcard" target="_blank"&gt;hCard&lt;/a&gt; microformat. If you have a microformat plug-in for your browser like &lt;a href="http://visitmix.com/lab/oomph" target="_blank"&gt;Oomph&lt;/a&gt; for Internet Explorer or Operator for FireFox then you get some bonus functionality. Below is a screenshot of the awesome looking Oomph plug-in. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://employees.claritycon.com/kmarshall/blog/img/TwtMyCardLaunch_1388E/image.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;margin:0px 0px 0px 40px;display:inline;border-top:0px;border-right:0px;" title="image" border="0" alt="image" src="http://employees.claritycon.com/kmarshall/blog/img/TwtMyCardLaunch_1388E/image_thumb.png" width="600" height="436" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If you like TwtMyCard or have any ideas you’d like to see implemented, let us &lt;a href="http://twtmycard.uservoice.com/pages/24839-general" target="_blank"&gt;know&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In future blog posts I’ll talk a little more about the code for TwtMyCard and some of my thoughts on Azure and ASP.NET MVC. Overall the experience of using MVC on Azure was pleasant minus some issues I had with Azure. Also JQuery, Blueprint CSS, TweetSharp and the Famfamfam icons sped up the development effort considerably. Thanks to all the developers / designers who built those. Not that it’s a super complicated application, but it’s great when you can mix and match some proprietary code and some open source code in a few nights to create a (hopefully) scalable web app. And big thanks to Anand for the idea and help launching the site.&lt;/p&gt;&lt;img src="http://blogs.claritycon.com/aggbug.aspx?PostID=88744" width="1" height="1"&gt;</description></item></channel></rss>