NB. Please note that this code block now adds 3 new classes – I believe these are provided by Amazon in an code example somewhere.. they are called AmazonHeader, AmazonSigningMessageInspector, and AmazonSigningEndpointBehaviour. They basically add the correct signatures to the web service requests so that they comply with Amazon’s strict security policy which was enforced recently. I didn’t write these.
namespace AmazonService.Proxy
{
public static class AmazonGateway
{
private const string privateKey = "MYPRIVATEKEY (Secret key)";
private const string publicKey = "MYPUBLICKEY (AWSAccessKey)";
public static List<System.Drawing.Image> SearchAlbumArt(string movieKeywords)
{
string filteredKeywords = string.Empty;
foreach (char c in movieKeywords)
{
if (char.IsLetterOrDigit(c))
{
filteredKeywords += c;
}
else
{
filteredKeywords += " ";
}
}
filteredKeywords = filteredKeywords.Trim();
ItemSearchRequest itemRequest = new ItemSearchRequest();
itemRequest.Keywords = filteredKeywords;
itemRequest.SearchIndex = "DVD"; // dvd’s only
itemRequest.ResponseGroup = new string[] { "Images" }; // images only
ItemSearch request = new ItemSearch();
request.AWSAccessKeyId = publicKey;
request.Request = new ItemSearchRequest[] { itemRequest };
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.MaxReceivedMessageSize = int.MaxValue;
AWSECommerceServicePortTypeClient client = new AWSECommerceServicePortTypeClient(
binding,
new EndpointAddress("https://webservices.amazon.com/onca/soap?Service=AWSECommerceService"));
// add authentication to the ECS client
client.ChannelFactory.Endpoint.Behaviors.Add(new AmazonSigningEndpointBehavior(publicKey, privateKey));
ItemSearchResponse response = client.ItemSearch(request);
// Determine if book was found
bool itemFound = ((response.Items[0].Item != null)
&& (response.Items[0].Item.Length > 0));
if (itemFound)
{
List<System.Drawing.Image> images = new List<System.Drawing.Image>();
foreach (Item currItem in response.Items[0].Item)
{
try
{
images.Add(ConvertByteArrayToImage(
GetBytesFromUrl(currItem.LargeImage.URL)));
}
catch { }
}
return images;
}
else
{
return null;
}
}
public static System.Drawing.Image ConvertByteArrayToImage(byte[] byteArray)
{
try
{
if (byteArray != null)
{
MemoryStream ms = new MemoryStream(byteArray, 0,
byteArray.Length);
ms.Write(byteArray, 0, byteArray.Length);
return System.Drawing.Image.FromStream(ms, true);
}
return null;
}
catch { }
return null;
}
static public byte[] GetBytesFromUrl(string url)
{
byte[] b;
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
WebResponse myResp = myReq.GetResponse();
Stream stream = myResp.GetResponseStream();
//int i;
using (BinaryReader br = new BinaryReader(stream))
{
//i = (int)(stream.Length);
b = br.ReadBytes(500000);
br.Close();
}
myResp.Close();
return b;
}
}
public class AmazonSigningEndpointBehavior : IEndpointBehavior
{
private string accessKeyId = "";
private string secretKey = "";
public AmazonSigningEndpointBehavior(string accessKeyId, string secretKey) {
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime) {
clientRuntime.MessageInspectors.Add(new AmazonSigningMessageInspector(accessKeyId, secretKey));
}
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { return; }
public void Validate(ServiceEndpoint serviceEndpoint) { return; }
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) { return; }
}
public class AmazonSigningMessageInspector : IClientMessageInspector
{
private string accessKeyId = "";
private string secretKey = "";
public AmazonSigningMessageInspector(string accessKeyId, string secretKey)
{
this.accessKeyId = accessKeyId;
this.secretKey = secretKey;
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
// prepare the data to sign
string operation = Regex.Match(request.Headers.Action, "[^/]+$").ToString();
DateTime now = DateTime.UtcNow;
string timestamp = now.ToString("yyyy-MM-ddTHH:mm:ssZ");
string signMe = operation + timestamp;
byte[] bytesToSign = Encoding.UTF8.GetBytes(signMe);
// sign the data
byte[] secretKeyBytes = Encoding.UTF8.GetBytes(secretKey);
HMAC hmacSha256 = new HMACSHA256(secretKeyBytes);
byte[] hashBytes = hmacSha256.ComputeHash(bytesToSign);
string signature = Convert.ToBase64String(hashBytes);
// add the signature information to the request headers
request.Headers.Add(new AmazonHeader("AWSAccessKeyId", accessKeyId));
request.Headers.Add(new AmazonHeader("Timestamp", timestamp));
request.Headers.Add(new AmazonHeader("Signature", signature));
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState) { }
}
public class AmazonHeader : MessageHeader
{
private string name;
private string value;
public AmazonHeader(string name, string value)
{
this.name = name;
this.value = value;
}
public override string Name { get { return name; } }
public override string Namespace { get { return "http://security.amazonaws.com/doc/2007-01-01/"; } }
protected override void OnWriteHeaderContents(XmlDictionaryWriter xmlDictionaryWriter, MessageVersion messageVersion)
{
xmlDictionaryWriter.WriteString(value);
}
}
}
So, effectively what you end up with here is a static method you can call, and pass in a search keyword from any source you need to lookup cover art for. It will return a series of images which you can then display dynamically in a .NET application or just save to a designated path using the Image.Save method.