Windows Live Writer Amazon Starter Plugin

Getting started with Window Live Writer Plugins

Writing a plugin for Windows Live Writer is actually fairly easy. The biggest problem you’re going to come across is thinking about what to actually add.

There are currently a number of plugins available on the Windows Live Gallery that you can download and add. ScottIsAFool, a fellow Windows Live MVP has contributed a lot to these. My thanks also go to him for developing a nice little Visual Studio plugin that gives lays out the basic framework for Live Writer plugins.

Live Writer plugins basically fall into a number of categories but the one in this simple example to get you all started is probably the easiest one to start coding with and is based on the CreateContent API.

Windows Live Plugins work in essentially the same way for each type of plugin that you create.  You have a main cs (or vb) class file that instantiates any windows forms that you want to use, gather the information then plonk that information into Windows Live Writer.

The basic example we’ll start coding is a book review template. To make things slightly easier, we use Amazon web services to look certain information about the book and also to get a picture of the front cover of the book.

So the first thing you’ve got to do is to create yourself an account on amazon in order to access their web services. There is a link on the left hand menu for under Services for developers.  When you create your amazon account, you’ll be given an Access Key, a 20 character string of characters. You’ll need this for this example.

So first off you need to create a new Windows Application Project in Visual Studio. Name it and set the location of the project then click OK.

Now rename Program.cs (the default) to plugin.cs (this isn’t actually necessary but it helps when you come back to looking at this code after a while.

Right click on References and add a reference to “WindowsLive.Writer.Api”. This can be found in the Windows Live Writer SDK which is available for download from http://dev.live.com.

Back to plugin.cs. Here is the code at the top of our plugin.cs example :-

using System;

using System.Collections.Generic;

using System.Text;

using WindowsLive.Writer.Api;

using System.Windows.Forms;

namespace LiveWriterTestPlugin

{

  [WriterPlugin("b0fa2544-dc04-48c1-9c90-e422bff1debc", "AmazonLWPlugin",

      Description = "Use Amazon WS to retrieve book information",

      HasEditableOptions = false,

      Name = "Amazon Test Plugin",

      PublisherUrl = "http://mywebsite.com")]

  [InsertableContentSource("Amazon Test Plugin")]

You will notice the using WindowLive.Writer.Api statement.
Below this is the WriterPlugin attribute. The first part of this is a GUID, this should be unique for each plugin. In Visual Studio you can easily create a new GUID from the Tools menu. The next parameter is the Plugin name (name of the main plugin class) followed by it’s description. As we’re keeping this example simple, the next parameter, HasEditableOptions, we’ll set to false, next you give your plugin a published name and finally a URL. The url does not need to be an actual URL. Think of it more in terms on an XML namespace URI.

The next Visual Studio Attribute tells the system that you are creating an insertable content source. What this means is that you’re plugin will be writing directly into the editable “work” area of Windows Live Writer. Now that is really the hard part done with.

public class AmazonLWPlugin : ContentSource

  {

// If you change the name after class, please change it here too

public AmazonLWPlugin()

    { }

public override DialogResult CreateContent(IWin32Window dialogOwner, ref string newContent)

    {

using (SearchAmazon search = new SearchAmazon())

      {

DialogResult res = search.ShowDialog();

if (res == DialogResult.OK)

        {

string book = search.BookSelected;

StringBuilder str = new StringBuilder();

insert your markup code here. Remember to escape quotation marks

          newContent += str.ToString();

        }

else

        {

          newContent = “<h3>No Results</h3>”;

        }

return res;

      }

    }

  }

}

This is the rest of the Plugin.cs class file. As you can see we simple create a public class file that inherits from ContentSource. We have an empty initializer and the main part is the override of the CreateContent method.

You’ll notice from the signature of CreateContent that it expects a DialogResult. All that this means is that any forms you create have to be in the form of dialogs. This is accomplished simply by adding OK and cancel buttons to the form and selecting the appropriate buttons in the AcceptButton and CancelButton properties.

The next statement basically displays the dialog box (a form I’ve called SearchAmazon).
After that I’m checking to see that the “OK” button was pressed and if it was then create some HTML that we will be passing back to Live Writer and outputing the result. That’s really all there is to this.

OK so next we need to create the SearchAmazon form but first we need to add a Web Reference to the Amazon service. So right click  on References in the Solution Explorer and add a web reference to http://soap.amazon.com/onca/soap?Service=AWSECommerceService and call it AmazonWS.

Next Rename your form to SearchAmazon. The SearchAmazon dialog we will create is simply a textbox for you to input your search string, a button that kicks off the search through the amazon web service and a listbox that will output the results.  I’ve also added a number of public properties so that we can read some values back from the Plugin.cs main code file.

So here is the code for the SearchAmazon dialog :-

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

namespace LiveWriterTestPlugin

{

public partial class SearchAmazon : Form

  {

private string bookSelected = “None Selected”;

private AmazonWS.Item[] items;

private string m_isbn = string.Empty;

private string[] m_Author;

private string m_url = string.Empty;

private string m_bookimg = string.Empty;

private string m_title = string.Empty;

private string m_price = string.Empty;

public string ISBN

    {

get

      {

return m_isbn;

      }

    }

public string[] Author

    {

get

      {

return m_Author;

      }

    }

public string URL

    {

get

      {

return m_url;

      }

    }

public string BookImg

    {

get

      {

return m_bookimg;

      }

    }

public string Title

    {

get

      {

return m_title;

      }

    }

public string Price

    {

get

      {

return m_price;

      }

    }

public SearchAmazon()

    {

      InitializeComponent();

    }

public string BookSelected

    {

get

      {

return bookSelected;

      }

    }

private void btnSubmit_Click(object sender, EventArgs e)

    {

      AmazonWS.AWSECommerceService ws = new AmazonWS.AWSECommerceService();

      AmazonWS.ItemSearchRequest request = new AmazonWS.ItemSearchRequest();

      request.SearchIndex = “Books”;

      request.Power = “title:” + txtSearch.Text;

      request.ResponseGroup = new string[] { “Medium” };

      request.Sort = “salesrank”;

      AmazonWS.ItemSearchRequest[] requests = new AmazonWS.ItemSearchRequest[] { request };

      AmazonWS.ItemSearch itemSearch = new AmazonWS.ItemSearch();

      itemSearch.AWSAccessKeyId = “Your Access Key Here“;

      itemSearch.Request = requests;

try

      {

        AmazonWS.ItemSearchResponse response = ws.ItemSearch(itemSearch);

        AmazonWS.Items info = response.Items[0];

        items = info.Item;

for (int i = 0; i < items.Length; i++)

        {

          AmazonWS.Item item = items[i];

          lstAmazonResults.Items.Add(item.ItemAttributes.Title);

        }

      }

catch

      {

//do nothing

      }

    }

private void lstAmazonResults_SelectedIndexChanged(object sender, EventArgs e)

    {

      bookSelected = lstAmazonResults.SelectedItem.ToString();

foreach (AmazonWS.Item itm in items)

      {

if (itm.ItemAttributes.Title == bookSelected)

        {

          m_Author = itm.ItemAttributes.Author;

if (itm.LargeImage != null)

          {

            m_bookimg = itm.LargeImage.URL;

          }

else if (itm.MediumImage != null)

          {

            m_bookimg = itm.MediumImage.URL;

          }

else

          {

            m_bookimg = string.Empty;

          }

          m_price = itm.ItemAttributes.ListPrice.FormattedPrice;

          m_isbn = itm.ItemAttributes.ISBN;

          m_title = itm.ItemAttributes.Title;

          m_url = itm.DetailPageURL;

        }

      }

    }

  }

}

So first off we setup the public properties that we will reference from Plugin.cs file. The AmazonWS.Item[] items statement is a collection of items that the web service will return.

Next is the btnSubmit method. This is tied to the search button. Here we create an instance of the AWSECommerceService and create an search request. The search we will be doing will be on Books so we assign the SearchIndex to books. The Power statement basically allows you to narrow down your search, so here we are saying only give us items where the search query is in the title of the book.
The response group determines how many and which types of results we want back from the web service. I’ve specified “Medium” here as I also want the query to return URLs of images that we will use, then we give it a search order of by sales rank. This is optional.

You can create numerous request objects to pass into the amazon web service but for this example we will only deal with the one defined above. The next line of code simply loads our request into a collection of requests that the web service expects.

Next we define our Search. This is where the Access Key you got when you registered with the amazon service comes in. Simply replace your own Access Key in the code where I’ve marked it (“Your Access Key Here“).

Finally we call the amazon service, iterate through the items that the service returns and simply load the title of the book into the listbox of the form.

The final method on this page hooks into the listbox’s SelectedIndexChanged event. Here I’m simply loading the public properties with the appropriate values based on the item the user has selected.

And that, in just a couple of classes and not much code at all is your first Windows Live Writer plugin. See how easy that was. You will find the code for this example attached below for you to look at and play with. Have fun and remember to post your Live Writer plugins to the Windows Live Gallery for others to make use of.

As as added bonus [:|] I’ve just run across a very well written and excellent example of a complex Live Writer plugin by fellow MVP Rick Strahl and he’s been nice enough to include a download of the source. The plugin allows you to directly capture images from SnagIt (An excellent tool and highly recommended) into Live Writer. You can find the plugin and the source here.