public void HandleSoapMessage(IMessage request, IMessage response) { int parameterIndex = Utility.FindFieldIndex("inputQuery", request.Parameters, true); parameterIndex = Utility.FindFieldIndex("inputQuery", request.Parameters, true); Query query = (Query)request.Parameters.GetObject(parameterIndex, "http://www.mynamespace.com", "Query"); . . . }
<?xml version="1.0" encoding="utf-8" ?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.mynamespace.com" xmlns:esri="http://www.esri.com/schemas/ArcGIS/10.0"><soap:Body><tns:CustomerSearch><ns1:inputQuery xmlns:ns1=""><ns1:Test>Test Text</ns1:Test></ns1:inputQuery></tns:CustomerSearch></soap:Body></soap:Envelope> <?xml version="1.0" encoding="utf-8" ?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.mynamespace.com" xmlns:esri="http://www.esri.com/schemas/ArcGIS/10.0"><soap:Body><tns:CustomerSearch><ns1:inputPoint xmlns:ns1=""><ns1:X>0</ns1:X><ns1:Y>0</ns1:Y></ns1:inputPoint></tns:CustomerSearch></soap:Body></soap:Envelope>
**UPDATE**
After much experimenting, the problem seems to stem from the call to GetObject being limited to whatever XML / COM-visible type mappings are defined in the ESRI-specific XmlSupport.dat file located in the "bin" folder of the ArcGIS Server install folder.
In other words, my custom XML / COM-visible type mapping file in the XmlClassRegistry folder never seems to be used.
I was able to verify this by copying my type-mapping snippet into XmlSupport.dat, after which the call to GetObject on the SOAP request worked successfully for my custom "Query" type.
Per the ESRI SOAP SOE walkthrough I created the appropriate folders and dropped the specially named mapping file in them. The full path of the custom XML support file is: C:\Program Files (x86)\ArcGIS\Server10.0\XmlClassRegistry\MyCompany\XmlSupportMyProject.dat
So the next question is, why isn't ArcGIS Server looking to my custom type mapping file during calls to GetObject?
I have same problem, but with ArcGis Server 10.1, and i cant find XmlClassRegistry folder. Is somethink changed in Server 10.1 ? Thanks
Erin, the originator of this thread, writes that a SOAP SOE was written that successfully sends an array of strings as input. I have a working SOAP SOE that takes a custom type but have had no luck with sending arrays (either with my custom type or even with simple types). Does any one know of samples out there that show the correct syntax for this?
<xs:element name="GetStuffByStringArray"> <xs:complexType> <xs:sequence> <xs:element name="aStringArray" type="ArrayOfString" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="GetStuffByStringArrayResponse"> <xs:complexType> <xs:sequence> <xs:element name="resultString" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element>
private void GetStuffByStringArray(IMessage request, IMessage response) { // Begin by parsing the string array from the request parameter. IStringArray stringCollection; int fieldIndex = Utility.FindFieldIndex("aStringArray", request.Parameters, true); stringCollection = request.Parameters.GetObject(fieldIndex, Utility.EsriNamespace, "ArrayOfString") as IStringArray; // Do something with the string values... }
<xs:complexType name="MyTypeCollection"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="MyType" type="tns:MyType"/> </xs:sequence> </xs:complexType>
MyTypeCollection collection = new MyTypeCollection(); int fieldIndex = Utility.FindFieldIndex("myTypeCollectionInput", request.Parameters, true); collection = request.Parameters.GetObject(fieldIndex, Utility.CustomTypesNamespace, "MyTypeCollection ") as MyTypeCollection;
<xs:element name="TestArrayArguments"> <xs:complexType> <xs:sequence> <xs:element name="aCustomTypeCollection" type="tns:MyCustomTypeCollection" /> </xs:sequence> </xs:complexType> </xs:element> <xs:complexType name="MyCustomTypeCollection"> <xs:sequence> <xs:element minOccurs="0" maxOccurs="unbounded" name="MyCustomType" type="tns:MyCustomType"/> </xs:sequence> </xs:complexType> <xs:complexType name="MyCustomType"> <xs:sequence> <xs:element name="ID" type="xs:string"/> </xs:sequence> </xs:complexType> <xs:element name="TestArrayArgumentsResponse"> <xs:complexType> <xs:sequence> <xs:element name="Result" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <message name="TestArrayArgumentsIn"> <part name="parameters" element="e:TestArrayArguments" /> </message> <message name="TestArrayArgumentsOut"> <part name="parameters" element="e:TestArrayArgumentsResponse" /> </message> <operation name="TestArrayArguments"> <input message="e:TestArrayArgumentsIn" /> <output message="e:TestArrayArgumentsOut" /> </operation>
private void TestArrayArguments(IMessage reqMsg, IMessage respMsg) { IXMLSerializeData reqParams = reqMsg.Parameters; string retString = ""; int idx = reqParams.Find("aCustomTypeCollection"); if (idx == -1) throw new ArgumentNullException("PROBLEM MAPPING FIELD TO INDEX"); retString += "field index is " + idx; MyCustomTypeCollection myTypeColl = (MyCustomTypeCollection)reqParams.GetObject(idx, c_ns_soe, "MyCustomTypeCollection"); respMsg.Name = "TestArrayArgumentsResponse"; respMsg.NamespaceURI = c_ns_soe; respMsg.Parameters.AddString("Result", retString); }
using System; using System.Runtime.InteropServices; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.SOESupport; namespace SoapSOE1 { [ComVisible(true)] [Guid("FCA9A8B6-4B78-45CB-B240-AEA7A6E2F489")] [ClassInterface(ClassInterfaceType.None)] public class MyCustomType : IXMLSerialize { public string ID { get; set; } public void Serialize(IXMLSerializeData data) { data.TypeName = this.GetType().Name; data.TypeNamespaceURI = SoapSOE1.c_ns_soe; data.AddString("ID", ID); } public void Deserialize(IXMLSerializeData data) { int idx = FindMandatoryParam("ID", data); this.ID = data.GetString(idx); } private int FindMandatoryParam(string fieldName, IXMLSerializeData data) { int idx = data.Find(fieldName); if (idx == -1) throw new MissingMandatoryFieldException(fieldName); return idx; } internal class MissingMandatoryFieldException : Exception { internal MissingMandatoryFieldException(string fieldName) : base("Missing mandatory field: " + fieldName) { } } } [ComVisible(true)] [Guid("D2BC82CA-F8C5-46AD-BFD6-0B80760A351E")] [ClassInterface(ClassInterfaceType.None)] public class MyCustomTypeCollection : SerializableList<MyCustomType> { public MyCustomTypeCollection(string namespaceURI) : base(namespaceURI) { } } }
I've carefully constructed my XmlSupportAdot.dat file (everything works if I just send an instance of my custom type and not an array so I know this file is getting seen).