如何将php数组结构传递给soap客户端?

问题描述:

我试图从.NET使用magento购物平台API,并不像我想象的那么甜。 事情是主要方法有args参数这在.NET生成的客户端是由PHP样品开发生产的对象,在SOAP信封看起来像这样:如何将php数组结构传递给soap客户端?

<args SOAP-ENC:arrayType="xsd:ur-type[4]" xsi:type="SOAP-ENC:Array"> 
    <item xsi:type="xsd:string">simple</item> 
    <item xsi:type="xsd:int">4</item> 
    <item xsi:type="xsd:string">sku_of_product</item> 
    <item xsi:type="ns2:Map"> 
     <item> 
     <key xsi:type="xsd:string">name</key> 
     <value xsi:type="xsd:string">name of product</value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">short_description</key> 
     <value xsi:type="xsd:string">short description</value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">description</key> 
     <value xsi:type="xsd:string">description</value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">status</key> 
     <value xsi:type="xsd:int">1</value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">weight</key> 
     <value xsi:type="xsd:int">0</value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">tax_class_id</key> 
     <value xsi:type="xsd:int">1</value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">categories</key> 
     <value SOAP-ENC:arrayType="xsd:int[1]" xsi:type="SOAP-ENC:Array"> 
      <item xsi:type="xsd:int">3</item> 
     </value> 
     </item> 
     <item> 
     <key xsi:type="xsd:string">price</key> 
     <value xsi:type="xsd:float">12.05</value> 
     </item> 
    </item> 
    </args> 

问题是,根元素是阵列,其中有一些字符串类型元素,然后是一些关键值对,其中一些关键值对是数组。 如何在c#中描述对象来产生这样的层次结构?

更新:服务引用没有描述任何状态结构,只是接口。

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
[System.ServiceModel.ServiceContractAttribute(Namespace="urn:Magento", ConfigurationName="EpcServiceReference.Mage_Api_Model_Server_HandlerPortType")] 
public interface Mage_Api_Model_Server_HandlerPortType { 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="callReturn")] 
    object call(string sessionId, string resourcePath, object args); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="multiCallReturn")] 
    object[] multiCall(string sessionId, object[] calls, object options); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="endSessionReturn")] 
    bool endSession(string sessionId); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="loginReturn")] 
    string login(string username, string apiKey); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="startSessionReturn")] 
    string startSession(); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="resourcesReturn")] 
    object[] resources(string sessionId); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="globalFaultsReturn")] 
    object[] globalFaults(string sessionId); 

    [System.ServiceModel.OperationContractAttribute(Action="urn:Mage_Api_Model_Server_HandlerAction", ReplyAction="*")] 
    [System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc, SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)] 
    [return: System.ServiceModel.MessageParameterAttribute(Name="resourceFaultsReturn")] 
    object[] resourceFaults(string resourceName, string sessionId); 
} 

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
public interface Mage_Api_Model_Server_HandlerPortTypeChannel : MagentoTest.EpcServiceReference.Mage_Api_Model_Server_HandlerPortType, System.ServiceModel.IClientChannel { 
} 

[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")] 
public partial class Mage_Api_Model_Server_HandlerPortTypeClient : System.ServiceModel.ClientBase<MagentoTest.EpcServiceReference.Mage_Api_Model_Server_HandlerPortType>, MagentoTest.EpcServiceReference.Mage_Api_Model_Server_HandlerPortType { 

    public Mage_Api_Model_Server_HandlerPortTypeClient() { 
    } 

    public Mage_Api_Model_Server_HandlerPortTypeClient(string endpointConfigurationName) : 
      base(endpointConfigurationName) { 
    } 

    public Mage_Api_Model_Server_HandlerPortTypeClient(string endpointConfigurationName, string remoteAddress) : 
      base(endpointConfigurationName, remoteAddress) { 
    } 

    public Mage_Api_Model_Server_HandlerPortTypeClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
      base(endpointConfigurationName, remoteAddress) { 
    } 

    public Mage_Api_Model_Server_HandlerPortTypeClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
      base(binding, remoteAddress) { 
    } 

    public object call(string sessionId, string resourcePath, object args) { 
     return base.Channel.call(sessionId, resourcePath, args); 
    } 

    public object[] multiCall(string sessionId, object[] calls, object options) { 
     return base.Channel.multiCall(sessionId, calls, options); 
    } 

    public bool endSession(string sessionId) { 
     return base.Channel.endSession(sessionId); 
    } 

    public string login(string username, string apiKey) { 
     return base.Channel.login(username, apiKey); 
    } 

    public string startSession() { 
     return base.Channel.startSession(); 
    } 

    public object[] resources(string sessionId) { 
     return base.Channel.resources(sessionId); 
    } 

    public object[] globalFaults(string sessionId) { 
     return base.Channel.globalFaults(sessionId); 
    } 

    public object[] resourceFaults(string resourceName, string sessionId) { 
     return base.Channel.resourceFaults(resourceName, sessionId); 
    } 
} 

,我试图调用此方法:

object call(string sessionId, string resourcePath, object args); 

还我发现类似的问题here,遗憾的是它没有一个答案也。

+0

使用对象的数组,然后把合适的类型,每个插槽 –

+0

可能你更具体一些?因为简单的对象数组将不会序列化我认为。还有关键和价值元素,数组项不会产生它们。 – Giedrius

+0

一个对象数组会很好地串行化。如果您添加了Web引用,则应在服务名称空间中为您的ns2:Map类型提供一个类。 –

我已经找到了,希望这将有助于任何人,谁必须通过PHP的Web服务,即希望PHP阵列整合:

[SoapType(TypeName = "Map", Namespace = "http://xml.apache.org/xml-soap")] 
public class item 
{ 
    [XmlElement(Form = XmlSchemaForm.Unqualified)] 
    public string key { get; set; } 

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

    [XmlArray("item")] 
    [XmlArrayItem(typeof(item), ElementName = "item")] 
    public item[] items { get; set; } 
} 

通常是PHP Web服务不指定他们希望什么样的类型(那是在我的情况最少),所以不要忘了作为已知类型添加类型到你的客户端操作:

 foreach (var operation in client.Endpoint.Contract.Operations) 
     { 
      operation.KnownTypes.Add(typeof(item));    
     } 
+0

这看起来像是用于magento Soap V1(我知道它也是一个通用的解决方案)。我的问题是,似乎无法使用Magento V1客户端访问端点。 – davehay

+0

我认为这取决于生成的代理类型。如果它是旧的Visual Studio,它可能不会使用svcutil来生成代理,所以代理不会有端点属性(这只是我的猜测,我没有检查过,如果这是真的)。你也是对的,那就是magento v1。 – Giedrius

+0

@Giedrius你有一个例子,你现在如何使用multiCall与物品类? – vikasde