Serialization in the SOAP API


Local (DCOM) connections are only supported for ArcGIS Server versions prior to 10.1.

About serialization in the SOAP API

Since ArcGIS Server Simple Object Access Protocol (SOAP) proxies emulate ArcObjects server object interfaces, SOAP value objects used by SOAP proxies emulate ArcObjects types. While not all ArcObjects types can be represented as a SOAP type, all SOAP value objects represent an ArcObjects type. In general, all ArcObjects that implement the ESRI.ArcGIS.esriSystem.IXMLSerialize interface can be serialized to and from SOAP. In some cases, you might need to convert from ArcObjects Component Object Model (COM) types to SOAP value object types and vice versa. Both ArcObjects and the native development environment, in this case Microsoft .NET, provide Extensible Markup Language (XML) serializer classes to enable the conversion.

SOAP to ArcObjects

To convert from a SOAP value object to an ArcObjects COM object, use the .NET classes System.Xml.Serialization.XmlSerializer and System.Xml.XmlDocument to create an XML string, then convert the XML string to an ArcObjects object using the ESRI.ArcGIS.esriSystem.XMLSerializerAlt class. The following code sample shows this pattern and includes the appropriate comments. The code sample uses SOAP value objects dynamically generated from an ArcGIS Server Web Service Description Language (WSDL) (for example, Map Server WSDL) and given the namespace wsmap. An ArcGIS Server SOAP PolylineN is converted to an ArcObjects ESRI.ArcGIS.Geometry.Polyline. This ArcObjects COM object is immediately cast to ESRI.ArcGIS.Geometry.IPolyline.
[C#]
// The SOAP PolylineN variable references a wsmap.PolylineN value object.
// The geometry class used for convenience to retrieve ArcGIS namespace is
// included with all service types except Catalog. The proxy namespace 
// for 9.3 is http://www.esri.com/schemas/ArcGIS/9.3.
string proxyNamespace = null;
Type nameType = typeof(wsmap.Geometry);
foreach (object attribute in nameType.GetCustomAttributes(true))
{
    if (attribute is System.Xml.Serialization.XmlTypeAttribute)
    {
        System.Xml.Serialization.XmlTypeAttribute xmlTypeAttribute = attribute as
            System.Xml.Serialization.XmlTypeAttribute;
        proxyNamespace = xmlTypeAttribute.Namespace;
        break;
    }
}

// Generate a string representation of a SOAP value object.
Type valueType = soapPolylineN.GetType();
System.Xml.Serialization.XmlSerializer xmlSerializer = new
    System.Xml.Serialization.XmlSerializer(valueType, proxyNamespace);
System.Text.StringBuilder stringBuilder = new StringBuilder();
System.IO.StringWriter stringWriter = new System.IO.StringWriter(stringBuilder);
xmlSerializer.Serialize(stringWriter, soapPolylineN);
string soapSerializedValueObject = stringBuilder.ToString();
// Strip off prolog. 
System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
xmlDocument.LoadXml(soapSerializedValueObject);
System.Xml.XmlElement xmlElement = xmlDocument.DocumentElement;
soapSerializedValueObject = xmlElement.OuterXml;
// Create an ArcObjects COM object using an XML string.
// Local ArcObjects:
ESRI.ArcGIS.esriSystem.IXMLSerializerAlt comXmlSerializerAlt = new
    ESRI.ArcGIS.esriSystem.XMLSerializerAlt();
ESRI.ArcGIS.Geometry.IPolyline comPolyline = (ESRI.ArcGIS.Geometry.IPolyline)
    comXmlSerializerAlt.LoadFromString(soapSerializedValueObject, valueType.Name,
    proxyNamespace);

ArcObjects to SOAP

To convert from an ArcObjects COM object to a SOAP value object, use the ArcObjects ESRI.ArcGIS.esriSystem.XMLSerializer class to convert to an XML string. Then use the .NET classes System.Xml.XmlTextReader and System.Xml.Serialization.XmlSerializer to deserialize the XML string to a SOAP value object. In most cases, the name of the ArcObjects type is the same or similar to the SOAP value type. The following code sample shows this pattern and includes the appropriate comments. The code sample uses SOAP value objects included with the Web Application Developer Framework (ADF) runtime in the ESRI.ArcGIS.ADF.ArcGISServer assembly and namespace. An ArcObjects ESRI.ArcGIS.Geometry.Polyline is converted to an ArcGIS Server SOAP PolylineN.
[C#]
// Create an ArcObjects serializer to generate an XML serialized string from the COM object.
ESRI.ArcGIS.esriSystem.IXMLSerializer comXmlSerializer = new
    ESRI.ArcGIS.esriSystem.XMLSerializer();
string xmlSerializedString = comXmlSerializer.SaveToString(comPolyline, null, null);
// Create .NET XmlTextReader and XmlSerializer to deserialize the XML string to a value object.
System.Xml.XmlTextReader xmlTextReader = new System.Xml.XmlTextReader(new
    System.IO.StringReader(xmlSerializedString));
System.Xml.Serialization.XmlSerializer mySerializer = new
    System.Xml.Serialization.XmlSerializer(typeof
    (ESRI.ArcGIS.ADF.ArcGISServer.PolylineN));

object valueObject = mySerializer.Deserialize(xmlTextReader);
ESRI.ArcGIS.ADF.ArcGISServer.PolylineN polylinen = 
    (ESRI.ArcGIS.ADF.ArcGISServer.PolylineN)valueObject;

Using ArcObjects serializers with ArcGIS Server

ArcObjects can be accessed locally or remotely via ArcGIS Server. The following code illustrates local access. To use ArcObjects remotely, connect to ArcGIS Server, create an empty server context and create the appropriate ArcObjects to perform the serialization. The following code snippet demonstrates how this can be accomplished in the context of the previous code example. This code can be used to create ESRI.ArcGIS.esriSystem.XMLSerializerAlt (SOAP to ArcObjects) or ESRI.ArcGIS.esriSystem.XMLSerializer (ArcObjects to SOAP).
[C#]
// Remote ArcObjects.
string serverName = "localhost";
string userName = "user";
string password = "pass";
string domain = "domainname";
ESRI.ArcGIS.ADF.Identity identity = new ESRI.ArcGIS.ADF.Identity(userName, password,
    domain);
ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsServerConnection = new
    ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection(serverName, identity);
agsServerConnection.Connect();
ESRI.ArcGIS.Server.IServerObjectManager serverObjectManager =
    agsServerConnection.ServerObjectManager;
ESRI.ArcGIS.Server.IServerContext serverContext =
    serverObjectManager.CreateServerContext("", "");
ESRI.ArcGIS.esriSystem.IXMLSerializerAlt comXmlSerializerAlt =
    serverContext.CreateObject("esriSystem.XMLSerializerAlt")as
    ESRI.ArcGIS.esriSystem.IXMLSerializerAlt;

SOAP to SOAP

Since SOAP value objects are defined in a WSDL, the same value object types can be generated in different namespaces. SOAP proxies and value objects must have the same namespace to be used together. This can present a problem when devising solutions that use dynamic ArcGIS Server value objects you've generated and ArcGIS Server value objects in another product for which you cannot change the namespace. For example, assume you generate a set of dynamic value objects with the namespace wsmap. If you create a wsmap.Envelope and attempt to use it with ESRI.ArcGIS.ADF.ArcGISServer.SpatialFilter by assigning it to the FilterGeometry property, a compile time error occurs. In general, the types are different because the namespaces are different.
If you have complete control over the generation of SOAP proxies and value objects, you can generate value object types that can be shared across ArcGIS Server service types (for example, PolygonN is included with every ArcGIS Server service type). If you are unable to modify the namespace for SOAP proxies and value objects, you can use the following code to convert between namespaces. In this example, a PolylineN created dynamically is being converted to an ESRI.ArcGIS.ADF.ArcGISServer.PolylineN. A .NET System.Xml.Serialization.XmlSerializer is used to serialize and deserialize the SOAP value object to and from a string.
[C#]
// Serialize the value object into a SOAP string.
Type valueType = dynamicSoapPolylineN.GetType();
System.Xml.Serialization.XmlSerializer xmlSerializer = new
    System.Xml.Serialization.XmlSerializer(valueType);
System.Text.StringBuilder stringBuilder = new StringBuilder();
System.IO.StringWriter stringWriter = new System.IO.StringWriter(stringBuilder);
xmlSerializer.Serialize(stringWriter, dynamicSoapPolylineN);
string soapSerializedValueObject = stringBuilder.ToString();
// Read the SOAP string to deserialize to the same type but different namespace.
System.Xml.XmlTextReader xmlTextReader = new System.Xml.XmlTextReader(new
    System.IO.StringReader(soapSerializedValueObject));
System.Xml.Serialization.XmlSerializer mySerializer = new
    System.Xml.Serialization.XmlSerializer(typeof
    (ESRI.ArcGIS.ADF.ArcGISServer.PolylineN));
object newValueObject = mySerializer.Deserialize(xmlTextReader);
ESRI.ArcGIS.ADF.ArcGISServer.PolylineN adfSoapPolylineN = 
    (ESRI.ArcGIS.ADF.ArcGISServer.PolylineN)newValueObject;


See Also:

Implementing the ArcGIS Server SOAP API