Jinesh Varia, Amazon Web Services
For illustration purposes, the text in italics represents the thought process of a developer (in this case, me) who is building an application (in this case, S3Whois).
Every business starts with a cool idea. Either you already have one or you have a problem that needs a solution. You start small, but think big. Just ask a few simple questions to test your idea:
Believe in yourself and your idea, and always validate your idea with �been-there-done-that� folks.
I came up with a simple idea. I thought it would be cool to show a small tooltip box when you move your over any e-mail address that appears on any web page while you are surfing. We can be very creative about what to show in the tooltip. To start off, I thought I will simply display all the �business card� information of the individual with a small photo. Something like this:

I thought the idea is cool because it gives e-mail a face and helps me associate an e-mail address with an actual identity/person.
How would the overall system work? Always use the whiteboard when you need to dump your brain. There will be lots of �idea threads� spawning which will, in turn, spawn more �idea threads� and not let you focus on the main idea. With the goal to get something fast, it�s important that you stay focused on your main success scenario. Whiteboards usually help transcribe your thoughts. Questions that you need to ask are:
My idea of trying to make it work for every web page on the Internet suggests that I need to develop a plug-in or toolbar for browsers. The plug-in will parse each page the user visits and replace all the mailto: href links with injected javascript code. This will render a small div layer (size of business card) when the mouseover event is fired.
The t ooltip will then query a web server and data store using the e-mail as an input parameter, then fetch me data associated with the e-mail. Initially, the data can be an image (photo) and some additional information like name, e-mail address, interests, and zip code.
How would I get the data in the first place? I would need a web form that users can use to insert data into the data store.
Initially, my whiteboard diagram looked like:

My main pieces of the puzzle were:
How will the system look and feel?
Overall, I felt I needed the following:
With the overall requirements of:
So you have a cool idea. And you also have a good feel of how the overall system will work and how the different parts will interact with each other. Now, we want to delve a little deeper and ask the following questions:
Its important to get there fast and hence its important that you have the right equipment/gear to get there. Either people decide to choose something they are already familiar with or they take this opportunity to learn a new product or technology.
I chose to do the latter. Taking the above pieces, and with an aim to develop something fast (in one weekend), I thought of the following:
To address #1 above, I thought it would be cool to use something like GreaseMonkey and install a small user script (probably might already be developed by some genius developer and just waiting for me to get noticed � think positive) in the script repository. By this, users (my customers) just have to install one cool little script that will do all the magic. One Caveat: Greasemonkey just works with firefox but there are also similar engines like greasemonkIE and turnabout that works for IE too. Other Alternatives were: developing a BHO/ActiveX IE plug-in or firefox plug-in.
To address #2, I decided to use VS.NET 2005 that comes with a built-in IIS server. I thought it would be a cool opportunity for me to learn the new product from Microsoft.
To address #3, I thought the fastest and easiest way to develop will be to consume an already existing web service. Instead of creating databases and writing the same-old CRUD database SQL logic, I will simply use some sort of web service that will store all the profiles of my customers.
Hence, I decided to use the new Amazon S3 web service for three main reasons:
Sweet, isn�t it?

I installed Greasemonkey plug-in for firefox, and modified a user script that was available from their user script repository (credits to Walter Zorn for providing his cool JavaScript tooltip). I already had VS2005.NET and IIS configured and ready.
I went to http://aws.amazon.com, created an account, and got Access Key ID and Secret Access Key. I also signed up for Amazon S3 by clicking on the �Sign up for Web service� button on http://aws.amazon.com/s3 and providing my credit card details
It is strongly recommended to dive into the code. It�s similar to approach that we take when we learn how to swim. Jump! You will flip-flop-splish-splash and strive to survive for few minutes, however, after some time, you will feel all your phobia has transformed into confidence. Likewise, you will realize how easy it is to integrate amazon s3 in your application only if you take the plunge into the code. Questions that you should ask here are :
I created a new web site in VS.NET 2005 and add existing files that I downloaded off the Resource Center in the code sample sections. I had all the code that I need to create my first Happy-path use case. My Solution Explorer looked something like this:

I created a new file called getprofile.aspx and inserted the following code:
<asp:Panel ID="profilePanel" runat="server">
<table>
<tr>
<td rowspan="4">
<form action="" runat="server">
<asp:Image ID="s3WhoisImage" runat="server" Height="150px" Width="100px"/> </form>
</td>
<td>
<table>
<tr> <td>
<asp:Label ID="s3WhoisName" runat="server" Text="Label"></asp:Label></td>
</tr>
<tr><td>
<asp:Label ID="s3WhoisEmail" runat="server" Text="Label"></asp:Label></td>
</tr>
<tr><td>
<asp:Label ID="s3WhoisInterests" runat="server" Text="Label"></asp:Label></td>
</tr>
</table>
</td>
</tr>
</table>
</asp:Panel>
To back this HTML, I had the following in my code (getprofile.aspx.cs):
//amazon aws credentials : you can get these from creating one at http://aws.amazon.com
//I am reading from web.config
string accessKey = system.Configuration.ConfigurationManager.AppSettings.Get("AccessKey");
string secretKey = System.Configuration.ConfigurationManager.AppSettings.Get("SecretKey");
//use your bucketname from web.config
bucketName = System.Configuration.ConfigurationManager.AppSettings.Get("bucketname");
//using REST get the URL of the image. Let the browser make the fetch call
//tricky to do this in SOAP as ASP.NET does not have ImageControl that takes in byte Array/bitmap
//QueryStringAuthGenerator simply generates the URL that we can use to make the REST call
QueryStringAuthGenerator generator = new QueryStringAuthGenerator(accessKey, secretKey, true);
generator.ExpiresIn = 60 * 1000;
string url = generator.get(bucketName, s3WhoisId, null);
s3WhoisImage.ImageUrl = url;
// *******************************************************
// REST example to get metadata of S3 object
// *******************************************************
RESTConnection restS3 = new RESTConnection(accessKey, secretKey);
GetResponse resp = restS3.getHead(bucketName, s3WhoisId, null);
SortedList metadata = resp.Object.Metadata;
//populating the html fields from the metadata
s3WhoisEmail.Text = (string)metadata["s3WhoisEmail".ToLower()];
s3WhoisName.Text = (string)metadata["s3WhoisName".ToLower()];
s3WhoisInterests.Text = (string)metadata["s3WhoisInterests".ToLower()];
I found that I could also do the same thing using SOAP:
// *******************************************************
// SOAP example to get metadata of S3 object
// *******************************************************
SOAPConnection s3 = new SOAPConnection(accessKey, secretKey);
GetObjectResult objResult = s3.get(bucketName, s3WhoisId, true);
s3WhoisEmail.Text = GetMetadataValue(objResult.Metadata, "s3WhoisEmail");
s3WhoisName.Text = GetMetadataValue(objResult.Metadata, "s3WhoisName");
s3WhoisInterests.Text = GetMetadataValue(objResult.Metadata, "s3WhoisInterests");
GetProfile.aspx looked something like this:

OK. So now I learned the way go �GET� an object from S3 using SOAP and REST. I needed to find out how can I �PUT� an object in Amazon S3. The PUT object was slightly tricky as I found out that there are multiple design choices:
As you can see, Amazon S3 gave me the flexibility to choose what�s best for me. #1 seems to be most viable option in my case as I could get the object and all its metadata in one single request and thereby it reduces the number of requests. Plus it�s more scalable as I just have to add a line of code or two to add a new metadata object.
This is what my putprofile.aspx looks like:

My Codebehind putprofile.aspx.cs:
public partial class PutProfile : System.Web.UI.Page
{
private string bucketName = "";
private SOAPConnection s3;
private RESTConnection restS3;
protected void Page_Load(object sender, EventArgs e)
{
//amazon aws credentials : you can get these from creating one at http://aws.amazon.com
string accessKey =System.Configuration.ConfigurationManager.AppSettings.Get("AccessKey");
string secretKey =System.Configuration.ConfigurationManager.AppSettings.Get("SecretKey");
//use your bucketname
bucketName = System.Configuration.ConfigurationManager.AppSettings.Get("bucketname");
//we will demostrate both SOAP and REST. so lets instantiate the connection
s3 = new SOAPConnection(accessKey, secretKey);
restS3 = new RESTConnection(accessKey, secretKey, true);
string id = Request.QueryString["id"];
if (id != "" && id != null)
{
s3WhoisId.Enabled = false;
s3WhoisId.Text = id;
}
else
s3WhoisId.Enabled = true;
}
protected void cmdSend_Click(object sender, EventArgs e)
{
// Check to see if image file was uploaded
if (filMyFile.PostedFile != null)
{
// Get a reference to PostedFile object
HttpPostedFile myFile = filMyFile.PostedFile;
// Get size of uploaded file
int nFileLen = myFile.ContentLength;
// make sure the size of the file is > 0}
if (nFileLen > 0)
{
// Allocate a buffer for reading of the file
byte[] myData = new byte[nFileLen];
// Read uploaded file from the Stream
myFile.InputStream.Read(myData, 0, nFileLen);
// Create a name for the file to store
string strFilename = Path.GetFileName(myFile.FileName);
// *******************************************************
// using REST to put a file in S3
// *******************************************************
SortedList metadata = new SortedList();
metadata.Add("s3WhoisName", s3WhoisName.Text);
metadata.Add("s3WhoisEmail", s3WhoisEmail.Text);
metadata.Add("s3WhoisInterests", s3WhoisInterests.Text);
SortedList headers = new SortedList();
headers.Add("Content-Type", "image/jpeg");
//prepare the object
S3Object obj = new S3Object(myData, metadata);
//make the call
Response res = restS3.put(bucketName, s3WhoisId.Text, obj, null);
//check the response message
if (res.Status == System.Net.HttpStatusCode.OK)
message.Text = "Profile Stored";
}
}
}
I also found that I could do the same using SOAP:
// *******************************************************
// using SOAP to put a file in S3
// *******************************************************
PutObjectResult objS3PutObjectResult;
MetadataEntry objMetaDataEntry;
MetadataEntry[] aobjMetaDataEntries = new MetadataEntry[3];
// adding some metadata entries to the object data
objMetaDataEntry = new MetadataEntry();
objMetaDataEntry.Name = "s3WhoisName";
objMetaDataEntry.Value = s3WhoisName.Text;
aobjMetaDataEntries[0] = objMetaDataEntry;
objMetaDataEntry = new MetadataEntry();
objMetaDataEntry.Name = "s3WhoisEmail";
objMetaDataEntry.Value = s3WhoisEmail.Text;
aobjMetaDataEntries[1] = objMetaDataEntry;
objMetaDataEntry = new MetadataEntry();
objMetaDataEntry.Name = "s3WhoisInterests";
objMetaDataEntry.Value = s3WhoisInterests.Text;
aobjMetaDataEntries[2] = objMetaDataEntry;
// make the remote call
objS3PutObjectResult = s3.put(bucketName, s3WhoisId.Text, myData, aobjMetaDataEntries, null);
if (objS3PutObjectResult != null)
message.Text = "Profile Stored";
This is how it looks in the end:

In Summary, this application utilizes the following things:
GetProfile.aspx gets the stored image/profile and its metadata from S3 using a unique identifier. The unique identifier is stored as �key� of S3 object in S3. PutProfile.aspx is a ASP.NET web form that take the information like image, name, email address from a web page and stores the information in the form of object in S3. All images are stored as �objects� in the �S3whois� bucket and additional information is stored as metadata of that object. The Greasemonkey script parses the HTML page and injects the mouseover JavaScript code wherever mailto: links are encountered. MouserOver displays the getprofile.aspx page.
There are always edge cases/exceptions in any application. Some Tips that might be helpful:
As soon as my �Happy Path� was working, I hosted my app on my local Web server, so that other people could start using it and provide me with more feedback. I documented the main success scenario and created a one page �user manual�.
It is important to share your application with others. Let the world know about you. Let the world blog about you.
I did a number of things to market and publicize my app:
Continuously keep track of features so that you can add and improve. One of the ways that has proven successful is to maintain a wiki page where others can add content (features/comments) about your application.
I chose to create an excel sheet that helps me track/sort the status of each new feature that I add. I continuously maintain and update that excel worksheet whenever any new interesting feature crops up.
| You must Sign In to use this message board. | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||