• Accessing Amazon S3 with Silverlight

    I ran into an interesting situation last week…the desire to access some of my Amazon S3 services from within a Silverlight application.

    Amazon Simple Storage Solution (S3) is a pay service provided Amazon for object storage ‘in the cloud.’  Although there is no UI tool provided by Amazon to navigate your account in S3, a SOAP and REST API are available for developers to integrate S3 information into their applications or other uses.  You can view more information about Amazon S3 on their site.

    What is S3?

    Since S3 is a pretty flexible service, it can be used for many different things including storing “objects” like serialized representations of a type or something.  A lot of applications these days are using cloud storage to store their application objects like this.  For me, I use it as a file server in the cloud.  Mostly it is there to host my images on this site as well as downloads and such.  Because there is no user interface I collaborated with Aaron to make the S3 Browser for Live Writer so that I could access my files for when I need them in posting content.

    Accessing content from S3 also has different meanings, even with regard to Silverlight.  For example, if you wanted to simply set an Image source to a hosted image on S3, you could easily do that using the URL provided by S3 to the object.  Since Silverlight allows media assets to be sourced from anywhere, this is not a problem.

    The Problem

    The problem comes when you want to download content in otherways, such as maybe a file stored there, a serialized object, or access their services in a Silverlight application.  Why is this a problem?  Well because S3 does not expose any cross-domain policy files in their implementation.  RIA platforms like Silverlight require a policy file from the providing service to exist in order to make cross-domain calls from the platform. 

    You can read more about Silverlight’s cross-domain policy information here:

     

    So how can we accomplish this?

    The S3 Service APIs

    Amazon exposes two service APIs: SOAP and REST.  Because of the requirements around using their REST service and providing an Authorization header, we are unable to use that in Silverlight at this time since Authorization is a restricted header we cannot modify at this time.  So we can use their SOAP service.  This is fine for Silverlight because Amazon provides a WSDL for us to generate a proxy with.  The defined endpoint in the WSDL for the service is https://s3.amazonaws.com/soap.  This is important so remember this.  Let’s move on.

    Buckets to the rescue!

    S3 uses a concept they call buckets to store information in containers.  I’m not going to into a lot of detail explaining this concept so if you want to learn more, read their documentation.  Basically a bucket is global unique to the service (not to your account)…so there can only exist one “timheuer” bucket across the service, name them accordingly :-).  All data you push to S3 must be in a bucket.  When you create a bucket, you can also access content in that bucket using a domain shortcut system.  For example when you create a bucket called “timheuer” and put a file in there called foo.txt, it has the URI of http://timheuer.s3.amazonaws.com/foo.txt.  Notice the alias that is happening here.  We can now use this method to solve some of our issues.  How?  Well the “/soap” key will be available at any bucket endpoint!

    Because of this aliasing, we can use this mechanism to ‘trick’ the endpoint of our service to respond to the policy file request…so let’s review how we’ll do this.

    Step 1: Create the bucket

    There are different ways you could do this.  You could simply put a bucket called “foo” and use that, or you can completely alias a domain name.  I’m choosing to completely alias a domain name.  Here’s how I did it.  First I created a bucket called timheueraws.timheuer.com – yes that full name.  That’s a valid bucket name and you’ll see why I did the full one in a moment.

    Step 2: Alias the domain

    If you have control over your DNS, this is easy, if you don’t, you may want to use the simple bucket aliasing.  But I went into my DNS (I use dnsmadeeasy.com btw, and it rocks, you should use it too).  I added a CNAME record to my domain (timheuer.com):

       1: CNAME    timheueraws    timheueraws.timheuer.com.s3.amazonaws.com.    86400    

    What does this mean?  Well any request to timheueraws.timheuer.com will essentially be made at timheueraws.timheuer.com.s3.amazonaws.com.  The last parameter is the TTL (time-to-live).

    Step 3: Create the clientaccesspolicy.xml file

    Create the policy file and upload it to your bucket you created in step 1.  Be sure to set the access control list to allow ‘Everyone’ read permissions on it or you’ll have a problem even getting to it.

    Creating the Silverlight application

    Create a new Silverlight application using Visual Studio 2008.  You can get all the tools you need by visiting the Getting Started section of the Silverlight community site.  Once created let’s point out the key aspects of the application.

    Create the Amazon service reference

    In your Silverlight application, add a service reference.  The easiest way to do this by right-clicking on the Silverlight project in VS2008 and choosing Add Service Reference.  Then in the address area, specify the Amazon S3 WSDL location:

    This will create the necessary proxy class code for us as well as a ServiceReferences.clientconfig file.

    Write your Amazon code

    Now for this simple purposes, let’s just list out all the buckets for our account.  There is an API method called “ListAllMyBuckets” that we’ll use.  Now Amazon requires a Signature element with every API call – it is essentially the authentication scheme.  The Signature is a hash of the request plus your Amazon secret key (something you should never share).  This can be confusing to some, so with the perusing of various code libraries on the Amazon doc areas, I came up with a simplified S3Helper to be able to do this Signature generation for us.

       1: public class S3Helper
       2: {
       3:     private const string AWS_ISO_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffZ";
       4:     private const string AWS_ACTION = "AmazonS3";
       5:  
       6:     public static DateTime GetDatestamp()
       7:     {
       8:         DateTime dteCurrentDateTime;
       9:         DateTime dteFriendlyDateTime;
      10:         dteCurrentDateTime = DateTime.Now;
      11:         dteFriendlyDateTime = new DateTime(dteCurrentDateTime.Year,
      12:             dteCurrentDateTime.Month, dteCurrentDateTime.Day,
      13:             dteCurrentDateTime.Hour, dteCurrentDateTime.Minute,
      14:             dteCurrentDateTime.Second,
      15:             dteCurrentDateTime.Millisecond, DateTimeKind.Local);
      16:         return dteFriendlyDateTime;
      17:     }
      18:  
      19:     public static string GetIsoTimestamp(DateTime timeStamp)
      20:     {
      21:         string sISOtimeStamp;
      22:         sISOtimeStamp = timeStamp.ToUniversalTime().ToString(AWS_ISO_FORMAT, System.Globalization.CultureInfo.InvariantCulture);
      23:         return sISOtimeStamp;
      24:     }
      25:  
      26:     public static string GenerateSignature(string secret, string S3Operation, DateTime timeStamp)
      27:     {
      28:         Encoding ae = new UTF8Encoding();
      29:         HMACSHA1 signature = new HMACSHA1(ae.GetBytes(secret));
      30:         string rawSignature = AWS_ACTION + S3Operation + GetIsoTimestamp(timeStamp);
      31:         string encodedSignature = Convert.ToBase64String(signature.ComputeHash(ae.GetBytes(rawSignature.ToCharArray())));
      32:  
      33:         return encodedSignature;
      34:     }
      35: }

    This will abstract that goop for us.

    Let’s assume we have a ListBox in our Page.xaml file that we’re going to populate with our bucket names.  Mine looks like this:

       1: <ListBox x:Name="BucketList">
       2:     <ListBox.ItemTemplate>
       3:         <DataTemplate>
       4:             <TextBlock Text="{Binding Name}" />
       5:         </DataTemplate>
       6:     </ListBox.ItemTemplate>
       7: </ListBox>

    So let’s just add a simple method to our Loaded event handler calling our ListAllMyBuckets method.  Remember, everything in Silverlight with regard to services is asynchronous, so we’re actually going to call ListAllMyBucketsAsync from our generated code.  We’ll need a completed event handler where we will put our binding code.  Here’s my complete code for both of these:

       1: void Page_Loaded(object sender, RoutedEventArgs e)
       2: {
       3:     DateTime timeStamp = S3Helper.GetDatestamp();
       4:  
       5:     s3 = new AWS.AmazonS3Client();
       6:  
       7:     s3.ListAllMyBucketsCompleted += new EventHandler<AWS.ListAllMyBucketsCompletedEventArgs>(s3_ListAllMyBucketsCompleted);
       8:     s3.ListAllMyBucketsAsync(AWS_AWS_ID, timeStamp, S3Helper.GenerateSignature(AWS_SECRET_KEY, "ListAllMyBuckets", timeStamp));
       9: }
      10:  
      11: void s3_ListAllMyBucketsCompleted(object sender, AWS.ListAllMyBucketsCompletedEventArgs e)
      12: {
      13:     if (e.Error == null)
      14:     {
      15:         AWS.ListAllMyBucketsResult res = e.Result;
      16:         AWS.ListAllMyBucketsEntry[] buckets = res.Buckets;
      17:         BucketList.ItemsSource = buckets;
      18:     }
      19: }

    The AWS_AWS_ID and AWS_SECRET_KEY are constants in my application that represent my access key and secret for my S3 account.  You’ll notice that in this snippet above the “s3” object isn’t typed – that is because I have a global that defines it (you can see it all in the code download).

    So now if we run this application, we should expect to see our bucket list populated in our ListBox, right?  Wrong.  We get a few exceptions.  First, we get an error because we can’t find the cross-domain policy file.  Ah yes, remember we’re still using the Amazon SOAP endpoint.  We need to change that.

    Changing the Amazon endpoint

    You may notice that the SOAP endpoint for S3 is an https:// scheme.  We won’t be able to use that using this method because of our aliasing and the fact that the SSL certificate wouldn’t match our alias.  So we need to change our endpoint.  There are two ways we can do this.

    We can change this in code and alter our code by creating a new BasicHttpBinding and EndpointAddress and passing them into the constructor of new AWS.AmazonS3Client().  But that would be putting our configuration in code.  Remember that when we added the service reference we were provided with a ServiceReferences.clientconfig file.  Open that up and check it out.  It provides all the configuration information for the endpoint.  Now we could just change a few things.  I decided to create a new <binding> node for my use rather than alter the others.  I called it “CustomAWS” and copied from the existing one that was there.  Now because the default endpoint for S3 is a secure transport and we cannot use that, we have to change the <security> node to mode=”None” so that we can use our custom endpoint URI.

    The second thing we do is in the <client> node change the address attribute and the bindingConfiguration attribute (to match new new config we just created).  Mine now looks like this in entirety:

       1: <configuration>
       2:     <system.serviceModel>
       3:         <bindings>
       4:             <basicHttpBinding>
       5:                 <binding name="AmazonS3SoapBinding" maxBufferSize="65536" maxReceivedMessageSize="65536">
       6:                     <security mode="Transport" />
       7:                 </binding>
       8:                 <binding name="AmazonS3SoapBinding1" maxBufferSize="65536" maxReceivedMessageSize="65536">
       9:                     <security mode="None" />
      10:                 </binding>
      11:               <binding name="CustomAWS" maxBufferSize="65536" maxReceivedMessageSize="65536">
      12:                 <security mode="None" />
      13:               </binding>
      14:             </basicHttpBinding>
      15:         </bindings>
      16:         <client>
      17:             <endpoint address="http://timheueraws.timheuer.com/soap" binding="basicHttpBinding"
      18:                 bindingConfiguration="CustomAWS" contract="Amz.AWS.AmazonS3"
      19:                 name="AmazonS3" />
      20:         </client>
      21:     </system.serviceModel>
      22: </configuration>

    Now when we run the application it will work and if we sniff the traffic we’ll see that the first request is to our clientaccesspolicy.xml file that enables us to continue with the /soap requests:

    Now we can see a list of our buckets and after wiring up some other code so that when we click on the bucket, we’ll see a list of all the objects, bound to a DataGrid (details blurred for privacy) :

    Summary

    Sweet, we’re done!  We’ve now been able to provide our own clientaccesspolicy.xml file in a place where it didn’t exist before and be able to call the service.  We can now use other methods perhaps to create a new bucket, put objects in buckets, etc.

    So in order to do this, we’ve:

      • Created an alias to an bucket in our S3 account
      • Uploaded a clientaccesspolicy.xml file to that bucket
      • Changed the endpoint configuration in our service reference
      • Called the services!

    I’ve included all the files for the above solution in the download file.  You’ll have to provide your own access key/secret of course as well as specify the endpoint address in the ServiceReferences.clientconfig file.

    Hope this helps!


    This work is licensed under a Creative Commons Attribution By license.
  • Updating Silverlight.js and Firefox 3

    I’m hoping this post will help explain a few things with regard to Silverlight detection scripts that some sites may be using.  This is related to the silverlight.js Javascript file that was deployed with a lot of Silverlight 1.0 applications/sites and is also available as a part of the Silverlight 2 SDK tools.

    What the heck is this Silverlight.js you speak of?

    Simply put, Silverlight.js is a helper file which enables Web sites to create advanced Silverlight installation and instantiation experiences.  It was a resource file that was initially shipped along side several templates and helper projects to aid in the detection of browsers and platforms and instantiate a new Silverlight application on a web page.  This actually was a method similar to other frameworks that used Javascript to instantiate plugin content to provide for a better user experience in some deployment instances.  When delivering rich internet applications, it is important to provide your users with the most positive experience in installing any plugins they may require.  You can read more about my thoughts about that here in Providing a great Silverlight deployment experience.

    Although not generally used for Silverlight 2 deployment now in favor of simply using the <object> tag explicitly, it is still a resource available to site developers should they choose to use it.  It provides some simple functions like checking if Silverlight is installed, and a method to create the HTML output content for when it is (object) and when it is not (HTML content).

    So why is it being updated, is something totally wrong?

    Not really.  We received feedback on some areas of the file and some scenarios where an enhanced version of certain aspects should be modified.  As an example, after the plugin was installed (by a user who previously did not have Silverlight), the browser had to be refreshed (and in some cases restarted) prior to the Silverlight plugin being able to be used.  This was one area of feedback that we heard and while some script methods surfaced as work arounds, ultimately they ended up being incorporated into this newer Silverlight.js file.

    Some of the enhancements provided in this update are:

      • Auto-refresh behavior where available, providing WaitForInstallation and onSilverlightInstalled hooks for developers to use.
      • Reduced clicks in the default installation badge
      • Inproved UI for default badge image (i.e., looks better on all sites)

    Although they may seem minor, they help in enabling site owners deliver great deployment experiences.

    Great, so where can I get this update?

    The updated Silverlight.js file has been available for a while in the Silverlight 2 SDK materials.  However, you have had to download the full Silverlight 2 SDK just to get to the one file you may need.

    NOTE: If you have already done this, the file is located in C:\Program Files\Microsoft SDKs\Silverlight\v2.0\Tools path.

    Today, we actually made it available on its own without having to download the full Silverlight 2 SDK (but you should really check out Silverlight 2…it’s really great).  Leveraging the MSDN Code Gallery, the Silverlight.js file is now available for download as a stand-alone file at the Silverlight.js Code Gallery project site.  A link to the API documentation and any breaking changes from the previous version are also available there.  What is further great is that it is being released under the Microsoft Public License (Ms-Pl), which means it is available for you to freely modify to your own needs.

    I got the file, how and what should I be updating with this new file?

    Now that you have the updated file, what do you do with it.  Well, that depends :-).  The simplest answer here is to replace your old Silverlight.js file with this new one.  IMPORTANT: Review the breaking changes documentation to ensure you aren’t using things that may break.  If you never knew you were even using the Silverlight.js file you should generally be safe with a simple replace.  Your old file will likely be sitting in your web application and named Silverlight.js…just copy this file over that one (I’d recommend backing up your old one just in case).

    There may be other areas where you want to update the file so that you don’t have to update the file to begin with.  Now, please note this is a suggestion from me and likely ‘unsupported’ but I feel pretty safe about updating these templates.   Here are some suggestions:

    Visual Studio 2005 Project Templates

    If you are using VS2005, you probably downloaded the Silverlight 1.0 SDK which installed some VS2005 project templates for your creating Silverlight 1.0 applications.  Look for the template file in C:\users\(username}\Documents\Visual Studio 2005\Projects\Templates\ProjectTemplates\Silverlight\SilverlightJSApplication.zip.  This is the path on Vista, but the user path is slightly different on Windows XP (c:\documents and settings…etc.).  If you open that archive you’ll see the Silverlight.js file there.  Now, please note this is a suggestion from me and likely ‘unsupported’ but I feel pretty safe about updating this template.  Simply use your favorite archive tool to open the template file and replace the Silverlight.js file with the new one.  Now when you choose File…New…Silverlight Javascript Application in Visual Studio 2005 you’ll have the updated Silverlight.js file already!

    Visual Studio 2008 Project Templates

    NOTE: These actually shouldn't need updating if you are using the latest Silverlight 2 Beta 2 SDK tools...the templates already have the update in them.

    If you are using VS2008 you are likely using Silverlight 2 development (which the project templates do not use Silverlight.js), but there actually is a Silverlight Script Web project type for still working on 1.0 projects.  The location of that template is C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\Web\{language}\1033 where language is both CSharp and VisualBasic (there is a template for both).  Within this folder is an archive file called SilverlightScriptWeb.zip which is the template file.  If you open that archive you’ll see the Silverlight.js file there.  Simply use your favorite archive tool to open the template file and replace the Silverlight.js file with the new one.  Now when you choose File…New Web Site…Silverlight Script Web in Visual Studio 2008 you’ll have the updated Silverlight.js file already!

    Expression Encoder Output Templates

    All of the Expression Encoder media output templates use this file.  This process is a bit more time because there are more templates than just two.  Navigate to C:\Program Files\Microsoft Expression\Encoder 2\Templates\en to see the templates.  If you have Encoder 1 installed the path will be different slightly in C:\Program Files\Microsoft Expression and might be called Media Encoder depending on what version you have (but you really should get Encoder 2, it rocks).  In each of those template folder you’ll see the Silverlight.js file there.  Again, I’d recommend backing this up ‘just in case’ before making any changes.  Since none of these are in an archive folder, you can copy/paste the file into each of the template folders.  If you have Powershell installed you can navigate to the run this command (nod to ScottHa for the help):

       1: dir . silverlight.js -recurse |% { copy c:\foo $_.FullName  }

    obviously replacing {c:\foo} with the location of where you downloaded the updated Silverlight.js file.  One note here is that the Encoder templates included an obfuscated/compressed version of Silverlight.js.  The new one is not compressed/obfuscated and you should test your templates to ensure everything works.

    Does this fix any Firefox 3 issues?

    It’s important to note that Firefox 3 is not currently a supported browser for Silverlight.  At the time of release of Silverlight 1.0, Firefox 3 was not a released product.  And right now Silverlight 2 is still in beta as well.  We intent on making Firefox 3 a supported browser when Silverlight 2 releases this year.

    That said the updated file will likely fix one problem with Firefox 3 visiting sites that use Silverlight.js.  Using the old file, visitors using Firefox 3 would see an image asking them to install Silverlight even though they already had it installed.  We’ve made some updates to the isInstalled method to cover the Firefox 3 scenario so this won’t happen.

    You can see an example I put up on my server by visiting the same Silverlight application using the old script or the new script.  The only difference between these two is a cut/paste of Silverlight.js.

    OLD:

    NEW (replacing only silverlight.js):

    Attention site owners:  If you are seeing information from your users or haven’t tested your Silverlight applications in Firefox 3, please do so and update to the latest Silverlight.js file if you are using the old one.  Visitors, if you see sites that are displaying the ‘install Silverlight’ badge and you have Silverlight installed, you can try to contact them and refer them to this post…or leave a comment here as well.  Yes, I know some Microsoft sites need this update as well, we’re working on getting the site owners to update as well!

    I saw a link about Silverlight.supportedUserAgent.js as well, what is that?

    This file is an optional add-on for Silverlight.js. It adds Silverlight.supportedUserAgent function which determines if the user's browser is supported by Silverlight.  This is not included in the base because supportedUserAgent is highly dependent upon the current Web browser implementations.  Because browsers evolve, this file would need to be updated more frequently than Silverlight.js.  If you need this functionality, you’ll want to check back often to get any updates.  The supportedUserAgent file has a Code Gallery project site as well.

    I hope this helps clear up some confusion and provide some pointers where you might want to update.  If you have any questions, leave a comment and I’ll do my best to answer!


    This work is licensed under a Creative Commons Attribution By license.
  • Pogue’s Hypocrisy

    I’m a fan of David Pogue.  I like his podcast as he covers some cool gadgets and service in a bit of a no-nonsense way.  I saw his site today and saw his ‘pledge’ followed by my eye glancing at what I consider ads.  Evidently David doesn’t consider self promotion of goods and sale words like ‘half-price’ or product placement words advertising.


    This work is licensed under a Creative Commons Attribution By license.
  • Line Rider rides on Silverlight 2

    BoschOne of probably the coolest casual ‘games’ I’ve ever seen is Line Rider.  It’s a fun game, but really gets exciting when you have an artist behind it.  Basically it’s a blank canvas for you to draw a route for the main character to hop on his sled and ride.  Sound lame?  Not when you see what some have come up with.  For example, here’s a very popular ‘ride’ on YouTube.

    Well, the Line Rider team has recently modified their beta version and implemented in Silverlight 2!  They’ve also added some social networking integration using Live Messenger and the ability to send your rides to your contacts, etc.  The team was a group of developers and designers from the Line Rider team from InXile Entertainment as well as the crew from Cynergy Systems.  The Line Rider game was also used in a creative McDonald’s television campaign as well – McDonald’s gettin’ all involved with the interwebs…cool.

    In addition to the Silverlight version, InXile has announced console versions for XBOX 360, Wii, and PS3.  I think that will definitely a must get console game for myself and for the kids.  This Silverlight version really demonstrates some great things in Silverlight 2 and shows that the platform is a great one for casual games and how creative you can be with what version 2 has to offer.

    Congratulations to the Line Rider teams!


    This work is licensed under a Creative Commons Attribution By license.
  • Silverlight community controls contest

    I suspect we’ll be seeing more of these efforts for Silverlight and I love it.  In fact, INETA will be sponsoring the 2008 INETA Silverlight Challenge soon, so you should sign up for more information about that as well.  But until then…

    But until then, check out what some of the community MVPs and leaders are doing on their own!  They’ve started the Silverlight Control Builder Contest ‘08.  Two main organizers (Page Brooks and Dave Campbell) have put some time and thought into how they can get the community excited about developing solutions for the community and alas this idea came out of that!  These two have done some research, sought guidance, solicited some sponsors and did this on their own.  They built the contest site which is very detailed providing all the rules, prizes, and an FAQ.  Please be sure to read the rules.  One key thing is that this contest is open to US residents (over 18) only.  Please note that Pete/Dave answer why in their FAQ and please also realize this is completely a community-driven effort from these two guys.  I applaud them for their efforts and can tell you that they indeed researched the effort to make it an internationally available contest, but simply didn’t have the resources to do so…but hey, there is nothing preventing you in your local community from using this same idea :-).

    Additionally, there are some additional tidbits in the rules, so read them carefully…I picked out some highlights only:

      • Silverlight 2 Beta 2 or higher
      • Control must have a default and 1 additional template
      • No use of third-party controls
      • Source code must be open
      • Entries cannot be commercial/shareware

    The prizes are pretty great as well, including a 1-year MSDN Premium subscription provided by the organizers of the contest!

    So get your mind working and submit your entry by 11 AUG 2008.  Since only 1 entry allowed per contestant, make sure you put some good thought into it!


    This work is licensed under a Creative Commons Attribution By license.
  • I <3 Zappos!

    Zappos – a company that seemingly ‘gets it’ with regard to customer service, doing the right thing, and providing the best products at the best prices.  They have not paid/asked me for this comment.  When I find a company willing to provide the best service and put the customer first, I’m so impressed.

    I just ordered a new pair of shoes this afternoon (about 11:00 GMT –7).  I just received this email (emphasis mine) in my inbox (13:50 GMT –7):

    Although you originally ordered Standard (4 to 5 business days) shipping and handling, we have given your order special priority processing in our warehouse and are upgrading the shipping and delivery time frame for your order.  Your order will ship out Monday, June 30th 2008 and be given a special priority shipping status so that you can receive your order even faster than we originally promised!

    Please note that this is being done at no additional cost to you.  It is simply our way of saying thank you for being our customer.

    Now that is how to treat your customers.  I wrote a quick post earlier this year about how I felt they were innovating in advertising as well.  Seems to be a very creative company…and they are watching on Twitter as well!  I see that their catalog has expanded well beyond shoes and that is the only thing that worries me.  I hope that their commitment to excellence and return policies will apply when you buy that digital camera from them.  I’m not convinced that their expanding catalog is the best business move, but I’m not behind their doors.

    Until then, can’t wait for my shoes (oh and btw, if they are the wrong ones or don’t fit, they pay for return shipping too).  Thanks Zappos!


    This work is licensed under a Creative Commons Attribution By license.
  • Learning ASP.NET MVC?

    Stephen WaltherAre you poking around with the latest ASP.NET MVC (Model-View-Controller) bits?  If so, hopefully you are already aware of the resources available to you and the fact that Phil Haack is one of the program manager’s leading those efforts, and Scott Hanselman has been providing the community with some resources to jump start your learning.

    Well, another member has just joined the ranks on the team I work for.  Stephen Walther, pictured here in his best book-cover pose ;-), has joined the team.  He actually joined earlier this month, but I’m just now getting around to welcoming him to our team and checking out the stuff he’s been doing.  He’s been on a great clip lately and I’ve been reading his latest 11 tips on ASP.NET MVC on his blog.  I’m really glad to have him on our team as I think we’ve got some great resources for ASP.NET, AJAX, MVC, Silverlight and Windows Client.

    If you are messing around with the ASP.NET MVC framework, check out his site and subscribe.  We’ll be seeing a lot more of Stephen soon and I’m sure your ideas will be welcome to him as well!


    This work is licensed under a Creative Commons Attribution By license.
  • Android, iPhone and Windows oh my!

    I suspect Apple will have a good day on 11 July.  I’m pretty sue Apple could release the iGumWrapper and people will camp out 2 days before to be the first to purchase a gum wrapper made out of napkin and far less superior in functionality than what exists today.  It’s the lure of Apple, the marketing engine behind them and the fact that despite that napkin material, it would likely be so beautiful and make you forget some things that you’ve depended on for so long.

    But I digress :-).  In all seriousness, Apple excels at the hype and the experience (yes, two distinctions that shouldn’t always be confused as one).  With the release of the iPhone 3G, they’ll sell a lot I’m imagining and it will cause other mobile manufacturers concern…or it should.  The iPhone is being marketed as ‘half the price’ but others have already pointed out that that asterisk on the advertisements is a large asterisk…and in fact the ultimate cost to the consumer is actually higher (including service plans, etc.) than the current model.  But who cares…I’ve seen the cost analyst and it is negligible.  Misleading advertising?  Maybe.  Some have even pointed out that other than the 3G there isn’t much core upgrade to the device.  No camera upgrade, no IM, no Bluetooth support for cars, no cut/paste, no MMS messaging.  Some have even pointed out that despite GPS support there will be no guided turn-by-turn navigation provided.

    Regarding Navigation: Some have said that 3rd parties will use the SDK to solve that problem.  Ah, but read the terms of the SDK…no applications can provide navigational guidance using the SDK.  Why?  If you are aware of US carriers in telecom, you may notice that devices equipped with GPS all have an icon for directions – provided by TeleNav – provided as a monthly service fee of approximately USD $10 per month.  I think this is one area where the carriers won against apple in negotiations…to protect their own agreements and cross-revenue opportunities on services.

    One thing that has bothered most developer geeks about the SDK is the lack of background processing.  Apple’s keynote has pulled a little of the 'these aren’t the droids you're looking for’ magic by stating battery life, blah blah blah.  Hey guess what…Blackberry does this just fine and has great battery life.  Is this an area of “we couldn’t get it done” for Apple?  How many think this will change?  I do.  If there is any plans for iChat to be on the device, it would have to be.  Rely on an middle messaging server to deliver what is effectively an SMS command and then prompt me to launch the app again?  Seriously?!  Is this another way of retaining the carrier’s service costs for messaging fees?

    Have you ever noticed that Visual Voicemail is actually delivered as an SMS command to the phone with information on what that voice mail contains?

    Another sore spot for developers was the lack of Flash on the device.  There has been some bickering from Adobe/Apple on this, but it still isn’t there.  Adobe has said in their last company call their execs have noted they have it working via SDK but would hope the software would eventually be a part of the iPhone software.  A similar request has been made to me by developers of ‘when will Silverlight be on the iPhone’?  Hey guess what, no plugins are allowed on the iPhone – let’s wait for Apple to change that first, then let’s talk…you can’t complain when the platform doesn’t allow it first!

    And then comes Android.  When I first saw the video demonstration of this I was impressed.  It incorporates a lot of what modern devices have as well as what people like in the iPhone from a usability standpoint.  Oh, and it will be free and open source.  Some of the Open Handset Alliance have already announced devices with Android that might be available as soon as the end of this year!

    Will Android be successful in mainstream?  That is a big question.  Why would I ask that?  Tim, it’s Google, they do everything right, how could you be so stupid?  But consider this.  What makes Apple so successful in their software implementations?  Their ad campaigns shed some light on this when they jab Windows.  They control everything…the entire channel from hardware design to implementation.  There are no other (legal) hardware providers creating iPods, iPhones or MacBooks.  What does this have to do with Android?  Well Android is an open source project that will directly affect consumers.  Most of the time I think we see open source projects that are hiding behind consumer services.  Take, for example, any web server running their site on Linux.  Sure that affects consumers visiting the site, but not directly…the HTML/rendering is what affects me…not the implications of the hardware.

    Android will be literally in peoples’ hands.  There have been others that have done this successfully…like Sansa running Mono on their MP3 devices.  But how is this different?  Google isn’t providing the handset.  Will Android feel the same pains of the distribution channel that Windows does?  That being that you are providing an OS and don’t control the hardware that it resides on?  Android will be picked up by handset manufacturers and modified and tweaked and installed on various chipsets and handsets with differing peripherals that may not always comply to the specs or to what Android may expect.  Will that give Android a bad name when someone wants to put it on a device that is ‘minimum requirements’ (I hate minimum requirements---ever try anything on a min req machine…it never is a good experience)?  That remains to be seen.  Perhaps Google may have to do what they said they never would: the Google phone – to ensure that Android has one place where it can be guaranteed.

    And when it does come out, will it beat iPhone even though it shares some similarities?  I’m not convinced.  Apple (and iPhone) have a culture behind it.  iPhone itself has become somewhat of a mnemonic.  If you have an iPhone, when you tell someone that you just took a picture, do you say “I took it with my phone” or do you say “I took it with my iPhone”?  I hear this all the time…I <fill-in-the-function> with my iPhone.  I never walk around saying “I took this with my Blackjack.”  This is an advantage Apple has over the market…the brand strength.  I took it with my Android.  Still doesn’t sound right.  Even the newest devices like the Samsung Instinct, HTC Diamond, etc. will not gain that level of brand recognition.

    Where does all this leave developers?  Let’s see:

      • Apple – closed platform; closed hardware; Objective-C/Cocoa dev platform (OSX only for best tools); controlled distribution channel for apps;
      • Android – open platform; Java dev platform; tools everywhere; available for any hardware
      • Windows Mobile – open/closed platform; C++/.NET dev platform; tools everywhere (best tools on Windows); available for any licensed hardware vendor

    What a minute, Windows Mobile an ‘open’ platform?!  Tim, you lie.  Well, I’m not sure the marketing teams would agree with my statement, but consider the facts.  Windows Mobile provides an operating system to device manufacturers to leverage.  We actually provide what we call “platform builder” and those who license Windows Mobile can customize and pick and choose what “Windows Mobile'” means to them.  Is it completely open to alter the base code of WinMo?  No.  But if you have ever picked up a phone that had WinMo from T-Mobile and one from AT&T and one from Verizon, you’ll see that it is not the exact replication across the board.  Those carriers have done some of their own customizations and added/altered some of the applications that exist.

    Basically developers will have a choice…not a consistent choice by any means because each choice has a specific skill set.  I don’t know Java well enough that Android will be my choice, for example.  But if it is compelling enough, will that cause me to want to learn?  Who knows…

    So what’s with my rant.  Who knows…just had some thoughts on mobile that I wanted to get out.  Carry on.

    Related Blog Posts:


    This work is licensed under a Creative Commons Attribution By license.
  • FeedReader web part 3.0.0.2

    For those of you who use my RSS FeedReader Web Part for SharePoint, it has been updated into an ‘official’ release for the project.  Version 3.0.0.2 is now the latest release.  It incorporates all the changes from our team’s contributor, Ryan – thanks Ryan!!!  You can read the checkin on the Codeplex site or review this previous post for Ryan’s checkin notes.

    As always, the source code is included on the site, licensed under the Ms-Pl.

    There has been some emails/work items/debate over the installer.  The installation is two parts:

      • Installation of binaries
      • Deployment to SharePoint servers

    It has been much debated with me in private emails about that the MSI installer should automatically deploy to the server.  Initially this is how feedreader did it.  And I was flooded with email complaints.  Why?  Well, turns out people don’t always install to the same locations, have SharePoint in the same locations, want to deploy only certain web parts to certain SharePoint site collections, etc., etc. – I could go on.  The bottom line is that every configuration was different enough that it didn’t make sense to me to put effort into the installer to either a) guess or b) ask configuration questions.

    SharePoint already provides a tool to do this: stsadm.exe.  The readme (yes, there is a readme file) provides instructions for deploying the web part to your specific configurations.  I also received notes that the sample script should be more explicit.  Again, people haven’t always been installing the binaries to the same location so if I was explicit, I’d be wrong in some instances.  I can’t please everyone :-)

    The first step (after running the MSI which installs the binaries to your machine) is to run the stsadm tool to add the web part solution:

    stsadm -o addsolution -filename %YOUR_INSTALL_DIR%\SharePoint.WebParts.Rss.wsp

    Note the %YOUR_INSTALL_DIR% is not a literal you should be typing.  This refers to where you installed the binaries.  If you didn’t change any settings it would be this:

    stsadm -o addsolution -filename "C:\Program Files\Tim Heuer\RSS feedreader Web Part\SharePoint.WebParts.Rss.wsp"

    Notice that if you have spaces in your path you must put them in quotes.

    If you have problems/suggestions log them as a bug/work item on the Codeplex site please.  If you have an idea and would like to contribute, the source is available!

    The web part package you may have noticed is not packaged in a WSP file for easier deployment to Windows SharePoint Services v3 and in fact, that is a new requirement (WSS v3) for this update.


    This work is licensed under a Creative Commons Attribution By license.
  • Appreciate your blessings…

    Yes, this is one of those posts where you reflect on ‘life’ and how precious it is.  Today was a weird day for me because of two things that caused me pause.  Allow me a little history…

    Just over 5 years ago now I received a call that my father was in the hospital as a result of a massive heart attack and was unconscious.  Those are things you never want to hear…ever.  Needless to say it was going to get worse.  In fact my father was in immediate need of a heart transplant to live.  In the interim, they would equip him with an artificial heart.  Sounds logical right?  Unfortunately, ‘artificial hear’ in my father’s situation (due to his body size, chest cavity, etc.) translated to a massive piece of equipment.  Literally my father was hooked up to a pressure device that was on wheels and was about the size of a machine washer.  He had these HUGE tubes connected into his chest and external pumps that served as ventricles.  EVERYTHING was external to his body – yes you could see blood pumping in and out…it was disgusting and amazing at the same time.

    After about 7 months of this and a false start on a heart transplant we got the call that a heart was coming and it was local (a donated heart has about a 4hr ideal life span to transplantation).  Hours of surgery later my father had a new heart.  It was a long road to recovery but he is alive today with a donor heart.  My family is eternally grateful for this gift.  My children would have not known their grandfather otherwise (my wife was 9months pregnant when this was all happening).

    Fast-forward 5 years later.  Today we received a letter from a woman we’d never met.  It was the mother of the donor heart.  My own heart sank as she wrote this letter on father’s day.  She wrote how she had hoped we were able to benefit as she has felt this long for some time.  We had suspected the identity of the donor heart immediately as on the day my father received his, there was a terrible murder in a neighboring city of a young man.  To this day we suspected it was his heart.  Today we received confirmation of such.  To protect his identity I am not revealing details but that isn’t the point anyway.  My father lives today as a result of one man’s unfortunately loss of life and his remarkable decision to be an organ donor.  This letter from the family is a reminder of what a remarkable miracle happened to my father. 

    The second thing tod