【问题标题】:Pass parameter as an object[]将参数作为对象传递[]
【发布时间】:2013-04-25 17:19:46
【问题描述】:

我希望将此 API 与 c# 应用程序一起使用: http://www.affjet.com/2012/11/26/4-4-affjet-api/#more-3099

将 wsdl 添加到我的项目后,我编写了以下简单代码: (getTransactions 获取一个 object[] @params 并返回一个字符串)

Ws_ApiService service = new Ws_ApiService();
string apiKey = "*************";
var response = service.getTransactions(new object[] { apiKey });

我尝试了更多方法,但无法得到正确的响应, 我试过了:

var response = service.getTransactions(new object[] { "apiKey:****"});

和

var response = service.getTransactions(new object[] { "apiKey","******"});

这是他们的文档中执行相同操作的 php 代码:

<?php

$nameSpace = "https://secure.affjet.com/ws/api";

//Creating AffJet client for SOAP
$client = new SoapClient($nameSpace."?wsdl");

$pageNumber = 0;
//Setting up parameters
$params = array();
$params["apiKey"] = "MY_API_KEY";
//Value for parameters (optional)
//$params["networkId"] = array(1,2);
//$params["pageNumber"] = 0;
//$params["pageSize"] = 10;
//Making Request
$response = $client->getNetworks($params);
//XML to SimpleXMLElement Object
$xmlResponse = new SimpleXMLElement($response);
if ($xmlResponse->success == "true"){
    while (isset($xmlResponse->dataList->data)) {
        //Iterate the results
        foreach ($xmlResponse->dataList->data as $data){
            var_dump(xml2array($data));
        }
        //Requesting next page of data
        $pageNumber++;
        $params["pageNumber"] = $pageNumber;
        //Making Request
        $response = $client->getNetworks($params);
        //XML to SimpleXMLElement Object
        $xmlResponse = new SimpleXMLElement($response);
    }
} else {
    //Error somewhere
    echo $xmlResponse->errorMessage;
}

/**
* Transforms the object SimpleXmlElement into an array, easier to handle
*/
function xml2array($xml) {
    $arr = array();
    foreach ($xml as $element) {
        $tag = $element->getName();
        $e = get_object_vars($element);
        if (!empty($e)) {
            $arr[$tag] = $element instanceof SimpleXMLElement ? xml2array($element) : $e;
        } else {
            $arr[$tag] = trim($element);
        }
    }
    return $arr;
}


?>

这是我尝试过的回应:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:ns1="http://secure.affjet.com/ws/api"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
          SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
        <ns1:getTransactionsResponse>
        <return xsi:type="xsd:string">
            &lt;response&gt;&lt;success&gt;false&lt;/success&gt;&lt;errorMessage&gt;
            API Key not provided&lt;/errorMessage&gt;&lt;dataList&gt;
            &lt;/dataList&gt;&lt;/response&gt;
        </return>
        </ns1:getTransactionsResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

你可以看到:

API Key not provided

响应应该是这样的:

<response>
    <success>true</success>
    <errorMessage></errorMessage>
    <dataList>
        <data>
            <date>2012-11-05 15:02:41</date>//Transaction Date
            <amount>81.67</amount>
            <commission>15.86</commission>
            <status>confirmed</status>//Status, could be: declined, pending, confirmed or paid
            <clickDate></clickDate>
            <ip></ip>
            <custom_id>MyCustomId</custom_id>//Custom Id for the transactions (SID, SubId,clickRef....)
            <unique_id>2548462</unique_id>//Unique Id given from the network to this transaction
            <merchantId>1</merchantId>//Id for the Merchant on AffJet
            <networkId>1</networkId>//Id for the Network on AffJet
        </data>
    </dataList>
</response>

我只需要提供一个名为“apiKey”的参数及其值

编辑:

联系他们的支持后,他们说请求应该是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:ns1="http://secure.affjet.com/ws/api" 
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
                   xmlns:ns2="http://xml.apache.org/xml-soap" 
                   xmlns:SOAP- ENC="http://schemas.xmlsoap.org/soap/encoding/" 
            SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
        <ns1:getTransactions>
            <params xsi:type="ns2:Map">
                <item>
                    <key xsi:type="xsd:string">apiKey</key>
                    <value xsi:type="xsd:string">YOURAPIKEY</value>
                </item>
            </params>
        </ns1:getTransactions>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

有什么想法吗?

【问题讨论】:

  • 你的尝试发生了什么?返回一个字符串?弦是什么?你期望它是什么?
  • 我编辑了你要求的内容:)
  • 你能看到 service.getTransactions() 的方法 sig 是什么吗?
  • 当我尝试使用 WCFTestClient 导入 wdsl 时,添加服务时出现错误。您是如何将 wdsl 添加到您的项目中的?网页参考?
  • 我刚刚尝试了 wsdl.exe secure.affjet.com/ws/api?wsdl 并收到了很多警告和错误。试试看。我认为警告“警告:此 Web 参考不符合 WS-I Basic Profile v1.1”。可能需要进一步研究。

标签: c# web-services soap wsdl affiliate


【解决方案1】:

我对这个引人入胜的话题进行了更深入的研究,不得不说,使用相当于关联数组的东西只是 .NET SOAP 实现中的一种痛苦。关联数组表示为 IDictionary(例如 Hashtable)——但拒绝被序列化(试试看!)。

下面的代码是我能得到的最接近的代码——由于某种原因(错误?)它不能在 .NET 框架上运行,但在 Mono 上运行。

using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Text;

public class Test
{
  /*
   *  as per http://stackoverflow.com/a/1072815/2348103
   */
  public class Item
  {
    [XmlElement(Form = XmlSchemaForm.Unqualified)]
    public string key;

    [XmlElement(Form = XmlSchemaForm.Unqualified)]
    public string value;
  }

  [SoapType(TypeName = "Map", Namespace = "http://xml.apache.org/xml-soap")]
  public class Map : List<Item>
  {
  }

  public static void Main()
  {
    Map map = new Map();
    map.Add( new Item { key="foo", value="bar" } );
    map.Add( new Item { key="quux", value="barf" } );

    XmlTypeMapping mapping = 
         (new SoapReflectionImporter()).ImportTypeMapping( map.GetType() );
    XmlSerializer serializer = new XmlSerializer( mapping );
    XmlTextWriter writer = new XmlTextWriter( System.Console.Out );
    writer.Formatting = Formatting.Indented;
    writer.WriteStartElement( "root" );
    serializer.Serialize( writer, map );
    writer.WriteEndElement();
    writer.Close();
  }
}

/*
  // 
  // does not work - but see http://msdn.microsoft.com/en-us/magazine/cc164135.aspx
  // 
  public class Map : IXmlSerializable
  {
    const string NS = "http://xml.apache.org/xml-soap";
    public IDictionary dictionary;
    public Map()
    {
      dictionary = new Hashtable();
    }

    public Map(IDictionary dictionary)
    {
      this.dictionary = dictionary;
    }

    public void WriteXml(XmlWriter w)
    {
      w.WriteStartElement("Map", NS);
      foreach (object key in dictionary.Keys)
      {
        object value = dictionary[key];
        w.WriteStartElement("item", NS);
        w.WriteElementString("key", NS, key.ToString());
        w.WriteElementString("value", NS, value.ToString());
        w.WriteEndElement();
      }
      w.WriteEndElement();
    }

    public void ReadXml(XmlReader r)
    {
      r.Read(); // move past container
      r.ReadStartElement("dictionary");
      while (r.NodeType != XmlNodeType.EndElement)
      {
        r.ReadStartElement("item", NS);
        string key = r.ReadElementString("key", NS);
        string value = r.ReadElementString("value", NS);
        r.ReadEndElement();
        r.MoveToContent();
        dictionary.Add(key, value);
      }
    }
    public System.Xml.Schema.XmlSchema GetSchema() { return null; }
  }
*/

Mono 的示例输出:

<q1:Map xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="id1" d2p1:arrayType="Item[2]" xmlns:d2p1="http://schemas.xmlsoap.org/soap/encoding/" xmlns:q1="http://xml.apache.org/xml-soap">
  <Item href="#id2" />
  <Item href="#id3" />
</q1:Map>
[...]

.NET 的示例输出:

<q1:Array xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="id1" q1:arrayType="Item[2]" xmlns:q1="http://schemas.xmlsoap.org/soap/encoding/">
  <Item href="#id2" />
  <Item href="#id3" />
</q1:Array>
[...]

【讨论】:

  • 你的答案是迄今为止我见过的最好的答案,尽管它在 .net 上不起作用......如果有人能理解为什么......我会给你奖励你的努力制作。谢谢。
【解决方案2】:

您可以使用 KeyValue 对类或 Dictionary 类,如下所示:

        Dictionary<string, string> d = new Dictionary<string, string>();
        d.Add("apiKey", "******");
        var response = new object[] { d };

        KeyValuePair<string, string> d = new KeyValuePair<string, string>("apiKey", "******");
        var response = new object[] { d };

【讨论】:

  • {"类型 System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=]] 不是预期的。使用 XmlInclude 或 SoapInclude 属性来指定静态未知的类型。"}
  • 这是我遇到的例外情况......提琴手根本没有捕获任何发送给我的计算机的请求......
  • 我尝试了所有可能的方法,但由于 object[] @params 找不到使用服务的方法。我建议您可以更改路线:创建一个 PHP Webservice 应用程序,该应用程序将在内部调用上述 Web 服务,如上所述。从您的 .Net 应用程序使用第一个服务并发送需要的参数。现在你可以破解这个坚韧的坚果了。希望对您有所帮助。
  • 我同意这是一个解决方案,除非我有其他方法,否则我会这样做,但这让我感到害怕,因为它只是一个 Web 服务,我无法从中得到诚实的回应.. ..必须有一种方法只使用.net
  • 其实上面的Webservice并不是一个标准的webservice&不遵循WS-I webservice规范。您可以使用此在线 SoapClient 来测试服务:soapclient.com/soaptest.html 虽然它可以获取/调用方法但不能构造参数。可以看到参数列表是空的。但是,如果您尝试其他一些公共网络服务,您可以传递参数。我宁愿建议联系他们的支持团队或选择我在之前评论中提到的其他路线。
【解决方案3】:

看来问题在于 PHP 和 C# 中的数组之间的差异。在 PHP 中,它是一个键值对。他在从 wdsl 创建的生成类中的外观如何?这是与您的问题相关的 SO 问题的一行。 C# equivalent to php associative array 一个答案说尝试Dictionary&lt;String, String&gt;。也许值得尝试使用作为对象数组传递的KeyValuePair&lt;String, String&gt;。

KeyValuePair<String, String> parm = new KeyValuePair<String, String>("apiKey","******");

var response = service.getTransactions(new object[] { parm });

【讨论】:

  • @MatanL,这很难。我认为这将归结为在您导入之前手动更改 wdsl 以帮助它创建将与此 A 一起使用的类型
猜你喜欢
  • 1970-01-01
  • 2016-08-28
  • 2012-07-13
  • 2023-04-02
  • 1970-01-01
  • 2021-07-29
  • 2017-03-04
  • 2019-10-19
  • 1970-01-01
相关资源
最近更新 更多