| Comments

From time to time I’ve gotten a few inquiries as to what platform my blog is, what tools do I use, etc.  After a recent trip to Redmond and visiting with the Live Writer team, I got another inquiry while talking with a customer.  I thought I’d just spit out my thoughts.

First, my platform.  Yes there are many platforms out there for blogging.  Probably the most popular are Wordpress and Blogspot.  I think those are popular because you can get up and running for free and have it hosted.  My wife and her friends mostly use Blogspot for that reason.  Only a little customization is allowed, but skilled people can get creative.  For us propeller heads though, we don’t like hosted solutions :-).  I started a long while back on the .TEXT platform.  When Scott Watermasysk had started working with Telligent and Community Server, the .TEXT project was at a bit of a stand-still for growth.  A few picked up the project source code, forked it and created Subtext, which is the platform I now use.  Subtext has a good developer ecosystem around it and led by Phil Haack, there are constant improvements being discussed on the developer list.  It has served me well since I made the move and I’ve contributed features/fixes myself to make it better for me to use!  I’ve tinkered with Graffiti CMS, but for now, Subtext is my comfort zone and has given me no reason to leave.  There are a few things in the overall engine that are a bit dated, but heck the team is all volunteers and open source, so I’m not holding that against anyone.

As for tools, I’ve come to love Windows Live Writer.  Honestly, if you are a blogger and don’t use Writer, I have to ask why.  Seriously…even if you are the casual blogger.  I’ve heard my wife’s friends complain about formatting pictures in Blogspot…then they see Writer and love it!  When I first started blogging I would use the web site and my blog engine.  But quite honestly that is limiting to very basic posting information.  It doesn’t make authoring easy.  I initially started using BlogJet in the early days.  Honestly, it’s a good tool and I happily paid for it.  Probably my only reason for switching to Live Writer was because of the programming model.  As a developer I wanted to be able to customize it and take advantage of other customizations from others.  I remember getting word that Live Writer was available internally.  I took a look at it. 

The moment I downloaded it and installed it I knew we were going to be on to something.  But there were glaring holes.  That being said, I was a responsible beta user and gave feedback…very blunt feedback.  I remember within a week being invited on a phone call with the team to help them understand my feedback.  It was GREAT!  I told them that as-is they shouldn’t release…there were too many holes and releasing without a few key features would be detrimental to future releases.  Quickly I was introduced to some APIs and we talked through certain scenarios.  A few we agreed at the time couldn’t be core, and I volunteered some time to look at building some plugins with their help.  That was the birth of a few of my tools (Tag4Writer and Flickr4Writer).  Tag4Writer was a stop-gap until the Tags feature could get into the next release (which the functionality has and much better).  Flickr4Writer was a great learning experience in client development as well as working with a great team.  I’ve constantly stayed close to the feedback loop with the team to make it a better product.  To date, there is no better authoring product for me than Live Writer.

That being said, here’s my complete tools for blogging:

  • Subtext – my blog engine
  • Windows Live Writer (WLW) – authoring tool
  • Flickr4Writer – a plugin for WLW that enables browsing and insertion of pictures from Flickr and also has BlogThis support
  • S3Browser - a plugin that enables insertion/upload of bits to Amazon S3 storage.  I wrote this along with tremendous help from Aaron Lerch.  This enables me to keep my images/files stored on a reliable network and reduce overall bandwidth usage.
  • Leo Vildosa’s Code Snippet plugin – another plugin for WLW which enables me to insert formatted code snippets.  I know people have their favorites (and there are a lot of them) – this one is mine.
  • Dynamic Templates – a WLW plugin from one of the developers of Writer that enables you to provide your own “macros” within the plugin, helpful in a lot of cases
  • Creative Commons footer – a WLW plugin to append a Creative Commons note to every post without having to think about it.
  • Twitter Notify plugin: a WLW plugin to automatically update Twitter after posting
  • Templates: every blog should be as unique as you can make it.  Some of us are more skilled in design than others.  I’m not one of them.  I get my inspiration from others.  Wordpress has the best ecosystem of templates…learn from them.  There are a few sites that advertise templates like wpSnap.com and others.  Also look at SmashingMagazine.com always, they have some great stuff they find/provide with liberal licensing.

As you can see, my tools completely revolve around Live Writer.  There is only one instance where I can’t use it to do what I need: Enclosures – and I’ve been providing the team feedback around this feature to hopefully get it into their next release. 

For Mac Users: No, there isn’t a version of Writer for Mac :-(.  I’ve heard a lot of people on Mac say they keep a Windows virtual image around just for using Live Writer…wow.  There are some other tools (ecto and Mars Edit) but I haven’t used them extensively to know if they are good or not.  I know they don’t provide the suite of tools that I use so I don’t even bother exploring for now.

I’ve made a lot of investment in making Writer+Subtext an easy authoring setup for me and it has paid off in productivity savings.  Hopefully you have a set of tools on your own as well that keep you productive!

| Comments

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).

UPDATE: For security reasons you should actually stick with using only a bucket name and not a CNAME'd bucket.  This will enable you to use the SSL certificate from Amazon and make secure calls.  For example a bucket names "foo" could use https://foo.s3.amazonaws.com/soap as the endpoint.  This is highly adviseable.

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!  Please read Part 2 of this post.

| Comments

Hot off the press, a new drop of Windows Live Writer was just released.  Get it here.  This is one of my favorite tools from Microsoft and the update brings a few new changes.

First, I’m happy to report that Flickr4Writer and S3Browser still work fine and require no adjustments.  The other thing announced today from the Writer team is an updated SDK.  This new SDK includes a new type of plugin which enable plug-in activity for pre- and post-publish events.  Some of you following me on Twitter may have noticed something every so often that said “blogging: blah blah” and a link to the post.  This is done automatically for me from Writer using a plug-in.  It actually is one of the ones included in the updated SDK (along with another example for adding a Digg badget to your post).

Recently there’s been some discussion of people re-aggregating/posting blog content to other sites.  Even though I had a Creative Commons license on my blog’s footer, etc, it wasn’t in my content so when someone re-posted my stuff automatically, it wasn’t visible.  Using the new Writer SDK, I created a quick little plug-in that would add a notation about the Creative Commons license I was using to every post.  Again, automatically now and I don’t have to write anything.  I’m making this one available for free/test and you can get it here.  These plug-ins are accessed in the same way through the Tools…Options menu in Writer.  Here’s the configuration for mine:

If you click the Preview tab (a new feature in Writer preview – tabs instead of menu options to switch between Edit, Preview, Source), it will show you what it will look like as well.  These types of plugins can also be enabled per weblog so if you have more than one weblog defined for Writer, you can choose which one you want these post- and pre-publish event plug-ins to be turned on for. 

For some existing plugins out there, this is a more natural fit.  When I heard about this new model, I joined up with Alexander Groß who wrote the Now Playing plug-in which is awesome and flexible (he’s also involved in a great Graffiti template for user groups).  But it seemed a more natural fit to use this model of automatically appending the information instead of having the user remember to click the button to insert the information.  I’ve submitted my changes to Alexander and hope they make it into his next build of Now Playing.  It looks the same in config and here it is in preview mode in Writer:

I love the new Writer with the subtle changes it has made and the additional plug-in model.  Get your update today!