-----------------------------------

Acquista i software ArcGIS tramite Studio A&T srl, rivenditore autorizzato dei prodotti Esri.

I migliori software GIS, il miglior supporto tecnico!

I migliori software GIS, il miglior supporto tecnico!
Azienda operante nel settore GIS dal 2001, specializzata nell’utilizzo della tecnologia ArcGIS e aderente ai programmi Esri Italia Business Network ed Esri Partner Network

-----------------------------------



martedì 23 giugno 2009

SOE via SOAP

Aspettando la 9.4 10.0 dove l'implementazione di una SOE (Server Object Extension) via SOAP e REST sarà molto più agevole, è possibile fornire le funzionalità di una propria SOE via SOAP.

La nostra classe SOE dovrà implementare le interfacce IRequestHandler e IRequestHandler2:



[AutomationProxy(true), ClassInterface(ClassInterfaceType.None), GuidAttribute("8C37367E-DF95-4441-AD77-A3DF68877966")]
public class LayoutSOE : ServicedComponent, ILayout, IServerObjectExtension, ILogSupport, IObjectConstruct, IRequestHandler, IRequestHandler2
{



Implementazione di IRequestHandler e IRequestHandler2:

#region IRequestHandler Membri di
 
            public byte[] HandleBinaryRequest(ref byte[] request)
            {
                throw new NotImplementedException();
            }
 
            public string HandleStringRequest(string Capabilities, string request)
            {
 
                ESRI.ArcGIS.esriSystem.IXMLStream requestXmlStream = new ESRI.ArcGIS.esriSystem.XMLStreamClass();
                requestXmlStream.LoadFromString(request);
 
                ESRI.ArcGIS.esriSystem.IMessage requestMessage = new ESRI.ArcGIS.esriSystem.MessageClass();
                requestMessage.ReadXML(requestXmlStream as ESRI.ArcGIS.esriSystem.IStream);
 
                string responseHeader = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
                responseHeader += "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" ";
                responseHeader += "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ";
                responseHeader += "xmlns:tns=\"http://www.esri.com/schemas/ArcGIS/9.3\">";
                responseHeader += "<soap:Body>";
 
                string response = null;
 
                if (requestMessage.Name == "GetLayoutSOERequest")
                {
                    ESRI.ArcGIS.esriSystem.IXMLSerializeData requestParameters = requestMessage.Parameters;
                    int idxTemplate = requestParameters.Find("Template");
                    string template = requestParameters.GetString(idxTemplate);
                    int idxFormat = requestParameters.Find("Format");
                    string format = requestParameters.GetString(idxFormat);
 
                    int idxMapDescription = requestParameters.Find("MapDescription");
                    //IMapDescription p =
                    //(IMapDescription)requestParameters.GetObject(
                    //idxMapDescription, "http://www.esri.com/schemas/ArcGIS/9.3", "MapDescription");
 
                    string mapDescriptionSerialize = requestParameters.GetString(idxMapDescription);
                    System.Xml.XmlDocument xmlDocument = new System.Xml.XmlDocument();
                    xmlDocument.LoadXml(mapDescriptionSerialize);
                    System.Xml.XmlElement xmlElement = xmlDocument.DocumentElement;
                    string soapSerializedValueObject = xmlElement.OuterXml;
                    ESRI.ArcGIS.esriSystem.IXMLSerializerAlt comXmlSerializerAlt = new
                      ESRI.ArcGIS.esriSystem.XMLSerializerAlt();
                    IMapDescription mapDescription = (IMapDescription)
                      comXmlSerializerAlt.LoadFromString(soapSerializedValueObject,
                      "MapDescription", "http://www.esri.com/schemas/ArcGIS/9.3");
 
 
 
                    int idxPropertyChanges = requestParameters.Find("PropertyChanges");
                    //IPropertySet prp =
                    //(IPropertySet)requestParameters.GetObject(
                    //idxPropertyChanges, "http://www.esri.com/schemas/ArcGIS/9.3", "PropertySet");
 
                    string propertySetSerialize = requestParameters.GetString(idxPropertyChanges);
                    xmlDocument = new System.Xml.XmlDocument();
                    xmlDocument.LoadXml(propertySetSerialize);
                    xmlElement = xmlDocument.DocumentElement;
                    soapSerializedValueObject = xmlElement.OuterXml;
                    comXmlSerializerAlt = new
                      ESRI.ArcGIS.esriSystem.XMLSerializerAlt();
 
                    IPropertySet propertySet = (IPropertySet)
                      comXmlSerializerAlt.LoadFromString(soapSerializedValueObject,
                      "PropertySet", "http://www.esri.com/schemas/ArcGIS/9.3");
 
                    try
                    {
 
                        ILayout layout = this;
                        ILayoutAttribute layoutAttribute = layout.ExportLayout(mapDescription, template, propertySet, format);
                        response = responseHeader;
                        response += "<tns:GetLayoutSOEResponse>";
                        response += string.Format("<Url>{0}</Url>", layoutAttribute.Url);
                        response += string.Format("<HasError>{0}</HasError>",layoutAttribute.HasError.ToString().ToLower());
                        response += "</tns:GetLayoutSOEResponse>";
                        response += "</soap:Body></soap:Envelope>";
                    }
                    catch (Exception ex)
                    {
                        response = responseHeader;
                        response += "<tns:GetLayoutSOEResponse>";
                        response += string.Format("<Url>{0}</Url>", ex.Message);
                        response += "<HasError>true</HasError>";
                        response += "</tns:GetLayoutSOEResponse>";
                        response += "</soap:Body></soap:Envelope>";
                        return response;
                    }
                }
                return response;
 
 
            }
 
            #endregion
 
            #region IRequestHandler2 Membri di
 
 
            public byte[] HandleBinaryRequest2(string Capabilities, ref byte[] request)
            {
                throw new NotImplementedException();
            }
 
            #endregion


Nella SOE deserializzamo la stringa SOAP in oggetti ArcObjects con IXMLSerializerAlt


Nella cartella C:\Program Files (x86)\ArcGIS\XmlSchema creiamo il file WSDL con lo stesso nome della SOE:



File LayoutSOE.wsdl:

<?xml version="1.0" encoding="utf-8"?>
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:e="http://www.esri.com/schemas/ArcGIS/9.3" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.esri.com/schemas/ArcGIS/9.3">
  <types>
    <xs:schema targetNamespace="http://www.esri.com/schemas/ArcGIS/9.3" xmlns="http://www.esri.com/schemas/ArcGIS/9.3">
      <xs:element name="GetLayoutSOERequest">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="MapDescription" type="xs:string" />
            <xs:element name="Template" type="xs:string" />
            <xs:element name="PropertyChanges" type="xs:string" />
            <xs:element name="Format" type="xs:string" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="GetLayoutSOEResponse">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Url" type="xs:string" />
            <xs:element name="HasError" type="xs:boolean" />
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
  </types>
  <message name="GetLayoutSOERequestIn">
    <part name="parameters" element="e:GetLayoutSOERequest" />
  </message>
  <message name="GetLayoutSOERequestOut">
    <part name="parameters" element="e:GetLayoutSOEResponse" />
  </message>
  <portType name="LayoutSOEPort">
    <operation name="GetLayoutSOERequest">
      <input message="e:GetLayoutSOERequestIn" />
      <output message="e:GetLayoutSOERequestOut" />
    </operation>
  </portType>
  <binding name="LayoutSOEBinding" type="e:LayoutSOEPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <operation name="GetLayoutSOERequest">
      <soap:operation soapAction="" style="document" />
      <input>
        <soap:body use="literal" />
      </input>
      <output>
        <soap:body use="literal" />
      </output>
    </operation>
  </binding>
  <service name="#NAME#">
    <port name="LayoutSOEPort" binding="e:LayoutSOEBinding">
      <soap:address location="#URL#" />
    </port>
  </service>
</definitions>


Creiamo un servizio ArcGIS Server, abilitiamo la SOE e il web access per consentire una connessione internet.

Testiamo il wsdl:




Ora testiamo la SOE creando una web application basata sul servizio creato precedentemente. Nei web references puntiamo alla SOE:



I values ArcGIS Server saranno convertiti in stringhe SOAP:

using System;
using System.Collections.Generic;
using System.Web;
using ESRI.ArcGIS.ADF.Web.UI.WebControls;
using ESRI.ArcGIS.ADF.Web.DataSources;
using ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools;
using ESRI.ArcGIS.esriSystem;
using System.Text;
using ESRI.ArcGIS.ADF.ArcGISServer;
using PrintSOAP;
 
 
public class PrintTest : IMapServerCommandAction
{
 
    #region IServerAction Membri di
 
    public void ServerAction(ToolbarItemInfo info)
    {
 
 
        string ResourceName = "NameResource";
        string TemplateName = "NameTemplate";
 
        ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap =
            (ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)info.BuddyControls[0];
 
        ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality agsMapFunctionality =
            (ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)adfMap.GetFunctionality(ResourceName);
 
 
        ESRI.ArcGIS.ADF.ArcGISServer.MapDescription agsSoapMapDescription = agsMapFunctionality.MapDescription;
 
        //Serialize value object into SOAP string
        Type valueType = agsSoapMapDescription.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, agsSoapMapDescription);
 
        string soapSerializedValueObjectMapDescription = stringBuilder.ToString();
 
 
 
        #region Set Property PDF
        ESRI.ArcGIS.ADF.ArcGISServer.PropertySet prp = new ESRI.ArcGIS.ADF.ArcGISServer.PropertySet();
        PropertySetProperty[] parameters = new PropertySetProperty[13];
 
        PropertySetProperty property = new PropertySetProperty();
        property.Key = "Resolution";
        property.Value = 300;
        parameters.SetValue(property, 0);
 
        property = new PropertySetProperty();
        property.Key = "LayoutScale";
        property.Value = 5000.0;
        parameters.SetValue(property, 1);
 
        property = new PropertySetProperty();
        property.Key = "MarkerSymbolsToPolygons";
        property.Value = false;
        parameters.SetValue(property, 2); 
 
        property = new PropertySetProperty();
        property.Key = "EmbedFonts";
        property.Value = true;
        parameters.SetValue(property, 3); 
 
        property = new PropertySetProperty();
        property.Key = "CompressVectorGraphics";
        property.Value = false;
        parameters.SetValue(property, 4);
 
        property = new PropertySetProperty();
        property.Key = "ImageCompression";
        property.Value = "esriExportImageCompressionDeflate";
        parameters.SetValue(property, 5);
 
        property = new PropertySetProperty();
        property.Key = "ExportMeasureInfo";
        property.Value = false;
        parameters.SetValue(property, 6);
 
        property = new PropertySetProperty();
        property.Key = "ExportPDFLayersAndFeatureAttributes";
        property.Value = "esriExportPDFLayerOptionsNone";
        parameters.SetValue(property, 7);
 
        property = new PropertySetProperty();
        property.Key = "ExportPictureSymbolOptions";
        property.Value = "esriPSORasterizeIfRasterData";
        parameters.SetValue(property, 8);
 
        property = new PropertySetProperty();
        property.Key = "ExportColorspaceSettings";
        property.Value = "esriExportColorspaceRGB";
        parameters.SetValue(property, 9);
 
        property = new PropertySetProperty();
        property.Key = "ResampleRatio";
        property.Value = "esriRasterOutputNormal";
        parameters.SetValue(property, 10);
 
        property = new PropertySetProperty();
        property.Key = "ResolutionScreen";
        property.Value = 96;
        parameters.SetValue(property, 11);
 
        property = new PropertySetProperty();
        property.Key = "Graphics";
        property.Value = null;
        parameters.SetValue(property, 12);
 
        prp.PropertyArray = parameters;
        #endregion
 
 
        valueType = prp.GetType();
        xmlSerializer =
          new System.Xml.Serialization.XmlSerializer(valueType);
        stringBuilder = new StringBuilder();
        stringWriter = new System.IO.StringWriter(stringBuilder);
        xmlSerializer.Serialize(stringWriter, prp);
        string soapSerializedValueObjectPropertySet = stringBuilder.ToString();
 
        PrintSOAP.Test_Layoutsoe p = new Test_Layoutsoe();
 
 
        bool hasError;
        string urlPDF = p.GetLayoutSOERequest(soapSerializedValueObjectMapDescription, TemplateName, soapSerializedValueObjectPropertySet, "pdf", out hasError);   
 
 
    //    p.GetLayoutSOERequestCompleted += new PrintSOAP.GetLayoutSOERequestCompletedEventHandler(getLayoutSOERequestCompletedEventHandler);
    //    p.GetLayoutSOERequestAsync(soapSerializedValueObjectMapDescription, TemplateName, soapSerializedValueObjectPropertySet, "pdf");
    //
    }
 
    //public void getLayoutSOERequestCompletedEventHandler(object sender, GetLayoutSOERequestCompletedEventArgs e)
    //{
 
    //    string s = e.Result;
    //    //e.HasError
    //}
 
    #endregion
}

5 commenti:

Unknown ha detto...

thanks for the update here and thanks also for the SOE via REST post.
Have a question though : I'd like to know how have you generated the WSDL?? or what is the common approach ?
[i'm a beginner in the field of ws :)]

grazie.

Michael

Ing. Domenico Ciavarella ha detto...

if by WSDL you mean the file to be inserted in the folder C:\Program Files (x86)\ArcGIS\XmlSchema, I simply watched the other ESRI WSDL in this folder and I created one similar to them. In fact I haven't found any official documents about this matter.

Unknown ha detto...

Thanks Domenico,

I was looking more for some automatic generating tool, but at least I know how other people are approaching to this problem ;)
thanks again!

Unknown ha detto...

Hi Domenico, How to do this work with flex? (no Java), How to do a Flex Widget similar the Java widget for flexviewer? (remember no Java) My map application is developed in Flex Action Script (it generates a swf file different of the sample in Java Script Resource center in esri website) Can you guide me how to do it?, I am very newbie in Flex, Can you send me a feedback to my email adress? oletic@gmail.com, since now thanks very lot!!! and congratulations about your blog and your job it´s very interesting...
Regards
Leonardo Oletic

Ing. Domenico Ciavarella ha detto...

For call rest you can see this sample: http://resources.arcgis.com/gallery/file/arcobjects-net-api/details?entryID=87BEC705-1422-2418-34B5-308930DE323A

It's a soe rest developed from esri where you can see how call rest service (there are examples for web client (sl, flex, js).