Ich habe den ganzen Tag damit verbracht, Probleme mit der Amazon ECS (Ecommerce Services) API zu beheben.
Ich habe das Beispiel auf ihrer Website für das Senden von SOAP-Anfragen mit .NET 4.0 und WCF heruntergeladen
http://aws.amazon.com/code/Product-Advertising-API/3941
Ich habe nichts am Code des Beispiels geändert, außer der AccessKeyID und SecretyKeyID in der Konfigurationsdatei.
Der aufrufende Code sieht wie folgt aus:
// Instantiate Amazon ProductAdvertisingAPI client
AWSECommerceServicePortTypeClient amazonClient = new AWSECommerceServicePortTypeClient();
// prepare an ItemSearch request
ItemSearchRequest request = new ItemSearchRequest();
request.SearchIndex = "Books";
request.Title = "WCF";
request.ResponseGroup = new string[] { "Medium"};
ItemSearch itemSearch = new ItemSearch();
itemSearch.Request = new ItemSearchRequest[] { request };
request.Condition = Condition.All;
itemSearch.AssociateTag = "";
itemSearch.AWSAccessKeyId = ConfigurationManager.AppSettings["accessKeyId"];
// send the ItemSearch request
ItemSearchResponse response = amazonClient.ItemSearch(itemSearch);
if (response != null)
{
// write out the results from the ItemSearch request
foreach (var item in response.Items[0].Item)
{
Console.WriteLine(item.ItemAttributes.Title);
}
}
Console.WriteLine("done...enter any key to continue>");
Console.ReadLine();
der Aufruf von ItemSearch() liefert ein Null-Objekt. Ich habe mir das genauer angesehen und gesehen, dass in der AmazongSigningMessageInspector-Klasse die AfterReceiveReply()-Methode zeigt, dass eine ordnungsgemäße SOAP-XML-Antwort mit Ergebnissen zurückgegeben wird, so dass ich weiß, dass der Aufruf an den Dienst erfolgt und korrekt zurückgegeben wird. Aus irgendeinem Grund aber ich bin mit einem NULL ItemSearch Objekt links.
Der Code für meine Klassen ist der folgende:
class AmazonSigningBehaviorExtensionElement : BehaviorExtensionElement
{
public AmazonSigningBehaviorExtensionElement()
{
}
public override Type BehaviorType
{
get
{
return typeof(AmazonSigningEndpointBehavior);
}
}
protected override object CreateBehavior()
{
return new AmazonSigningEndpointBehavior(AccessKeyId, SecretKey);
}
[ConfigurationProperty("accessKeyId", IsRequired = true)]
public string AccessKeyId
{
get { return (string)base["accessKeyId"]; }
set { base["accessKeyId"] = value; }
}
[ConfigurationProperty("secretKey", IsRequired = true)]
public string SecretKey
{
get { return (string)base["secretKey"]; }
set { base["secretKey"] = value; }
}
}
public class AmazonSigningEndpointBehavior : IEndpointBehavior {
private string _accessKeyId = "";
private string _secretKey = "";
public AmazonSigningEndpointBehavior()
{
this._accessKeyId = ConfigurationManager.AppSettings["accessKeyId"];
this._secretKey = ConfigurationManager.AppSettings["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)
{
}
}
Ich habe dieses Problem überall gesehen, aber niemand hat irgendwo eine Lösung dafür veröffentlicht. Kann mir bitte jemand dabei helfen?