ArcGIS 服务对象扩展(SOE)新手自学笔记(5):注册与调试

 上一篇到现在过去好几天了,本来打算用ESRI官方自带的例子呢,后来觉得还是应该实践一下。这几天都在忙着写这个例子,其中也出现了好多问题,从一开始思考解决问题的方法,到找代码,再调试成功,费了不少事,好在问题都已经解决了。不喜欢说废话,还是忍不住说了这么多,下面正式进入主题。

  首先说说我们要解决的问题。gp服务广泛使用的一个原因是他可以做栅格数据的分析,那好我们就用SOE来解决一个插值问题。在gp服务中,我们可以通过设置输入输出类型来保客户端成功加载分析结果,大部分分析结果是以图片形式传到客户端。在SOE中理论上是可以设置输出图片形式,但帮助中只是简单地说了几句,很不详细,所以我用的方法是将栅格分类后转换成矢量数据,再将矢量数据序列化成json格式,传给客户端。流图如下:

  获取要素类---》插值---》重分类---》栅格转面---》序列化成json---》客户端

1.编写代码

新建一个工程,命名为Saturation  

首先加入以下引用:

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections.Specialized;

using System.Runtime.InteropServices;
using System.EnterpriseServices;

using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.SOESupport;
using ESRI.ArcGIS.GeoAnalyst;
using ESRI.ArcGIS.DataSourcesRaster;

//TODO: sign the project (project properties > signing tab > sign the assembly)
//      this is strongly suggested if the dll will be registered using regasm.exe <your>.dll /codebase

namespace Saturation
{
    [ComVisible(true)]
    [Guid("f8cb9f88-1dc9-4f34-a0a9-fa931afb8730")]
    [ClassInterface(ClassInterfaceType.None)]
    public class Saturation : ServicedComponent, IServerObjectExtension, IObjectConstruct, IRESTRequestHandler
    {
        private string soe_name;

        private IPropertySet configProps;
        private IServerObjectHelper serverObjectHelper;
        private ServerLogger logger;
        private IRESTRequestHandler reqHandler;

        //Member variables
        private string m_layerNameToAnalyst = null;
        private IFeatureClass m_fcToAnalyst = null;//进行插值的要素类

        public Saturation()
        {
            soe_name = this.GetType().Name;
            logger = new ServerLogger();
            reqHandler = new SoeRestImpl(soe_name, CreateRestSchema()) as IRESTRequestHandler;
        }

        #region IServerObjectExtension Members

        public void Init(IServerObjectHelper pSOH)
        {
            serverObjectHelper = pSOH;
        }

        public void Shutdown()
        {
            logger.LogMessage(ServerLogger.msgType.infoStandard, "Shutdown", 8000, "Custom error message: Shutting down the SOE");
            soe_name = null;
            m_fcToAnalyst = null;
            serverObjectHelper = null;
            m_layerNameToAnalyst = null;
            logger = null;
        }

        #endregion

        #region IObjectConstruct Members

        public void Construct(IPropertySet props)
        {
            logger.LogMessage(ServerLogger.msgType.error, "Construct", 8000, "SOE Construct:start");
            configProps = props;
            m_layerNameToAnalyst = "testPoint";
            //获得所要分析的FeatureClass
            try
            {
                IMapServer3 mapServer = serverObjectHelper.ServerObject as IMapServer3;

                string mapName = mapServer.DefaultMapName;
                IMapLayerInfos layerInfos = mapServer.GetServerInfo(mapName).MapLayerInfos;
                IMapLayerInfo layerInfo = null;

                //获得所要分析图层的index
                int c = layerInfos.Count;
                int layerIndex = 0;
                for (int i = 0; i < c; i++)
                {
                    layerInfo = layerInfos.get_Element(i);
                    if (layerInfo.Name == m_layerNameToAnalyst)
                    {
                        layerIndex = i;
                        break;
                    }
                }

                //使用IMapServerDataAccess获取数据
                IMapServerDataAccess dataAccess = mapServer as IMapServerDataAccess;
                m_fcToAnalyst = dataAccess.GetDataSource(mapName, layerIndex) as IFeatureClass;

                if (m_fcToAnalyst == null)
                {
                    logger.LogMessage(ServerLogger.msgType.error, "Construct", 8000, "SOE custom error: Layer name not found.");
                    return;
                }
            }
            catch (Exception es)
            {
                logger.LogMessage(ServerLogger.msgType.error, "Construct", 8000, "SOE custom error: Could not get the feature layer.");
            }
        }

        #endregion

        #region IRESTRequestHandler Members

        public string GetSchema()
        {
            return reqHandler.GetSchema();
        }

        public byte[] HandleRESTRequest(string Capabilities, string resourceName, string operationName, string operationInput, string outputFormat, string requestProperties, out string responseProperties)
        {
            return reqHandler.HandleRESTRequest(Capabilities, resourceName, operationName, operationInput, outputFormat, requestProperties, out responseProperties);
        }

        #endregion

        private RestResource CreateRestSchema()
        {
            RestResource rootRes = new RestResource(soe_name, false, RootResHandler);

            RestOperation sampleOper = new RestOperation("sampleOperation",
                                                      new string[] { "field" },
                                                      new string[] { "json" },
                                                      SaturationAnalystOpeartionHandler);

            rootRes.operations.Add(sampleOper);

            return rootRes;
        }

        private byte[] RootResHandler(NameValueCollection boundVariables, string outputFormat, string requestProperties, out string responseProperties)
        {
            responseProperties = null;

            JsonObject result = new JsonObject();
            //result.AddString("hello", "world");

            return Encoding.UTF8.GetBytes(result.ToJson());
        }

        private byte[] SaturationAnalystOpeartionHandler(NameValueCollection boundVariables,
                                                  JsonObject operationInput,
                                                      string outputFormat,
                                                      string requestProperties,
                                                  out string responseProperties)
        {
            responseProperties = null;
            //反序列化参数
            string strField;
            bool found = operationInput.TryGetString("field", out strField);
            if (!found || string.IsNullOrEmpty(strField))
                throw new ArgumentNullException("field");

            byte[] result = SaturationAnalyst(strField);

            return result;
        }

        private byte[] SaturationAnalyst(string field)
        {
            if (field.Length <= 0)
            {
                throw new ArgumentOutOfRangeException("field");
            }

            //插值
            IRaster krigeRaster = BuildKrigeRaster(m_fcToAnalyst, field);
            //重分类
            IRaster reclassRastr = BuildReclassRaster(krigeRaster, 4);
            //栅格转面,字段名作为生成的要素名称
            IFeatureClass ConPolygon = RasterToPolygon(reclassRastr, field);
            //将要素类序列化成json格式
            JsonObject resultJsonObject = FclassToJsonObj(ConPolygon);

            byte[] result = Encoding.UTF8.GetBytes(resultJsonObject.ToJson());
            return result;

        }

        #region Helper 函数
        /// <summary>
        /// 克里金插值
        /// </summary>
        /// <param name="inputFclass">插值数据</param>
        /// <param name="inputField">字段</param>
        /// <returns></returns>
        private IRaster BuildKrigeRaster(IFeatureClass inputFclass, string inputField)
        {
            if (inputFclass == null)
            {
                logger.LogMessage(ServerLogger.msgType.error, "BuildKrigeRaster", 8000, "SOE custom error: inputFclass is null.");
                return null;
            }
            if (inputField.Length == 0)
            {
                logger.LogMessage(ServerLogger.msgType.error, "BuildKrigeRaster", 8000, "SOE custom error: inputField is null.");
                return null;
            }

            //生成IFeatureClassDescriptor
            IFeatureClassDescriptor pFcDescriptor = new FeatureClassDescriptorClass();
            pFcDescriptor.Create(inputFclass, null, inputField);
            //设置分析环境
            IInterpolationOp pInterpolationOp = new RasterInterpolationOpClass();
            IRasterAnalysisEnvironment pEnv = pInterpolationOp as IRasterAnalysisEnvironment;
            object cellSize = 5.80481468000016E-04;
            pEnv.Reset();//栅格单元大小
            pEnv.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, ref cellSize);

            IRasterRadius pRadius = new RasterRadius();
            object obj = Type.Missing;//可变搜索半径
            pRadius.SetVariable(12, ref obj);

            IGeoDataset pGeodataset = inputFclass as IGeoDataset;
            IEnvelope pRasterExt = new EnvelopeClass();
            pRasterExt.XMin = 117.178625;
            pRasterExt.XMax = 117.376715;
            pRasterExt.YMax = 31.922649;
            pRasterExt.YMin = 31.777529;
            object extentPro = pRasterExt;//分析范围
            pEnv.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, ref extentPro, ref obj);
            pEnv.OutSpatialReference = pGeodataset.SpatialReference;
            //执行差值
            IGeoDataset pGeoDataset = pInterpolationOp.Krige((IGeoDataset)pFcDescriptor, esriGeoAnalysisSemiVariogramEnum.esriGeoAnalysisLinearSemiVariogram,
                pRadius, false, ref obj);

            return pGeoDataset as IRaster;
        }

        /// <summary>
        /// 对栅格进行等间距重分类
        /// </summary>
        /// <param name="inputRaster">待分类栅格</param>
        /// <param name="pClassNo">分类数</param>
        /// <returns></returns>
        private IRaster BuildReclassRaster(IRaster inputRaster, int pClassNo)
        {
            if (inputRaster == null)
            {
                logger.LogMessage(ServerLogger.msgType.error, "BuildReclassRaster", 8000, "SOE custom error: inputRaster is null.");
                return null;
            }
            if (pClassNo <= 0)
            {
                logger.LogMessage(ServerLogger.msgType.error, "BuildReclassRaster", 8000, "SOE custom error: pClassNo is null.");
                return null;
            }

            //获取栅格分类数组和频度数组
            object dataValues = null, dataCounts = null;
            GetRasterClass(inputRaster, out dataValues, out dataCounts);

            //获取栅格分类间隔数组
            IClassifyGEN pEqualIntervalClass = new EqualIntervalClass();
            pEqualIntervalClass.Classify(dataValues, dataCounts, ref pClassNo);
            double[] breaks = pEqualIntervalClass.ClassBreaks as double[];

            //设置新分类值
            INumberRemap pNemRemap = new NumberRemapClass();
            for (int i = 0; i < breaks.Length - 1; i++)
            {
                pNemRemap.MapRange(breaks[i], breaks[i + 1], i+1);
            }
            IRemap pRemap = pNemRemap as IRemap;

            //设置环境
            IReclassOp pReclassOp = new RasterReclassOpClass();
            IGeoDataset pGeodataset = inputRaster as IGeoDataset;
            IRasterAnalysisEnvironment pEnv = pReclassOp as IRasterAnalysisEnvironment;
            object obj = Type.Missing;

            IEnvelope pRasterExt = new EnvelopeClass();
            pRasterExt.XMin = 117.178625;
            pRasterExt.XMax = 117.376715;
            pRasterExt.YMax = 31.922649;
            pRasterExt.YMin = 31.777529;
            object extentPro = pRasterExt;//分析范围
            pEnv.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, ref extentPro, ref obj);
            pEnv.OutSpatialReference = pGeodataset.SpatialReference;

            //重分类
            IRaster pRaster = pReclassOp.ReclassByRemap(pGeodataset, pRemap, false) as IRaster;
            return pRaster;
        }

        /// <summary>
        /// 获取栅格分类数组和频度数组
        /// </summary>
        /// <param name="inputRaster">输入栅格</param>
        /// <param name="dataValues"></param>
        /// <param name="dataCounts"></param>
        private void GetRasterClass(IRaster inputRaster, out object dataValues, out object dataCounts)
        {
            IRasterBandCollection pRasBandCol = inputRaster as IRasterBandCollection;
            IRasterBand pRsBand = pRasBandCol.Item(0);
            pRsBand.ComputeStatsAndHist();//IRasterBand中本无统计直方图,必须先进行ComputeStatsAndHist()
            IRasterStatistics pRasterStatistic = pRsBand.Statistics;

            double mMean = pRasterStatistic.Mean;
            double mStandsrdDeviation = pRasterStatistic.StandardDeviation;

            IRasterHistogram pRasterHistogram = pRsBand.Histogram;
            double[] dblValues;
            dblValues = pRasterHistogram.Counts as double[];
            int intValueCount = dblValues.GetUpperBound(0) + 1;
            double[] vValues = new double[intValueCount];

            double dMaxValue = pRasterStatistic.Maximum;
            double dMinValue = pRasterStatistic.Minimum;
            double BinInterval = Convert.ToDouble((dMaxValue - dMinValue) / intValueCount);
            for (int i = 0; i < intValueCount; i++)
            {
                vValues[i] = i * BinInterval + pRasterStatistic.Minimum;
            }

            dataValues = vValues as object;
            dataCounts = dblValues as object;
        }

        /// <summary>
        /// 栅格转面
        /// </summary>
        /// <param name="inputRaster">待转换栅格</param>
        /// <param name="fcName">生成要素类名称</param>
        /// <returns></returns>
        private IFeatureClass RasterToPolygon(IRaster inputRaster, string fcName)
        {
            //获得testPoint所在工作空间
            IWorkspace pWorkspace = (m_fcToAnalyst as IDataset).Workspace;
            IRasterBandCollection pRasBandCol = inputRaster as IRasterBandCollection;
            IRasterBand pRsBand = pRasBandCol.Item(0);
            IRasterDataset pRasterDataset = pRsBand as IRasterDataset;
            IGeoDataset pRasterGeoDataset = pRasterDataset as IGeoDataset;

            //栅格转面
            IConversionOp pConversionOp = new RasterConversionOpClass();
            ISpatialReference pSpatialReference = pRasterGeoDataset.SpatialReference;

            IGeoDataset pGeoDataset = pConversionOp.RasterDataToPolygonFeatureData(pRasterGeoDataset, pWorkspace, fcName, true);
            return pGeoDataset as IFeatureClass;
        }

        /// <summary>
        /// 将要素类序列化成json格式对象
        /// </summary>
        /// <param name="inputFeaClass">输入要素类</param>
        /// <returns></returns>
        private JsonObject FclassToJsonObj(IFeatureClass inputFeaClass)
        {
            //获取要素数目
            IQueryFilter pQueryFilter = new QueryFilterClass();
            pQueryFilter.WhereClause = null;
            int count = inputFeaClass.FeatureCount(pQueryFilter);

            //将每一个要素序列化成json数据
            IFeature pFeature = null;
            List<JsonObject> jsonGeometries = new List<JsonObject>();
            for (int i = 1; i < count; i++)//OBJECTID从1开始
            {
                pFeature = inputFeaClass.GetFeature(i);
                IGeometry pGeometry = pFeature.Shape;
                JsonObject featureJson = new JsonObject();
                JsonObject feaGeoJson = null;//几何对象
                if (pGeometry != null)
                {
                    feaGeoJson = Conversion.ToJsonObject(pGeometry);
                    featureJson.AddJsonObject("geometry", feaGeoJson);//加入几何对象
                }

                double grid_Code = (double)pFeature.get_Value(pFeature.Fields.FindField("GRIDCODE"));
                featureJson.AddLong("id", i);//id
                featureJson.AddDouble("gridCode", grid_Code);//等级

                jsonGeometries.Add(featureJson);
            }

            JsonObject resultJson = new JsonObject();
            resultJson.AddArray("geometries", jsonGeometries.ToArray());
            return resultJson;
        }
        #endregion
    }
}

增加一个控制台应用程序,命名为RegisterSaturation

加入以下引用

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Server;
using ESRI.ArcGIS;
using ESRI.ArcGIS.ADF.Connection.AGS;

namespace RegisterSaturation
{
    class Program
    {
        static void Main(string[] args)
        {
            // Must run as an user in the agsadmin group on the SOM
            ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsServerConnection =
                new ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection();
            agsServerConnection.Host = "localhost";
            agsServerConnection.Connect();
            ESRI.ArcGIS.Server.IServerObjectAdmin2 serverObjectAdmin =
                agsServerConnection.ServerObjectAdmin as ESRI.ArcGIS.Server.IServerObjectAdmin2;

            // This name must match those defined for property pages
            string extensionName = "Saturation";

            // Check command line arguments to see if SOE is to be unregistered
            if (args.Length == 1 && args[0] == "/unregister")
            {
                // Check whether the SOE is registered
                if (ExtensionRegistered(serverObjectAdmin, extensionName))
                {
                    // Delete the SOE
                    serverObjectAdmin.DeleteExtensionType("MapServer", extensionName);
                    Console.WriteLine(extensionName + " successfully unregistered");
                }
                else
                    Console.WriteLine(extensionName + " is not registered with ArcGIS Server");
            }
            else
            {
                // Check whether the SOE is registered
                if (!ExtensionRegistered(serverObjectAdmin, extensionName))
                {
                    // Use IServerObjectExtensionType3 to get access to info properties
                    ESRI.ArcGIS.Server.IServerObjectExtensionType3 serverObjectExtensionType =
                        serverObjectAdmin.CreateExtensionType() as ESRI.ArcGIS.Server.IServerObjectExtensionType3;

                    // Must match the namespace and class name of the class implementing IServerObjectExtension
                    serverObjectExtensionType.CLSID = "Saturation.Saturation";
                    //serverObjectExtensionType.CLSID = "{C41E8674-F186-4a0c-8FC9-AAB7885EFD00}";
                    serverObjectExtensionType.Description = "the shops saturation";
                    serverObjectExtensionType.Name = extensionName;

                    // Name that will be shown in the capabilities list on property pages
                    serverObjectExtensionType.DisplayName = "Saturation REST";

                    // Use info properties to define capabilities and msd support
                    serverObjectExtensionType.Info.SetProperty("DefaultWebCapabilities", "GetInfo");
                    serverObjectExtensionType.Info.SetProperty("AllWebCapabilities", "GetInfo,Saturation");
                    serverObjectExtensionType.Info.SetProperty("SupportsMSD", "true");

                    // Required to enable exposure of SOE with ArcGIS Server REST endpoint
                    serverObjectExtensionType.Info.SetProperty("SupportsREST", "true");

                    // Register the SOE with the server
                    serverObjectAdmin.AddExtensionType("MapServer", serverObjectExtensionType);

                    Console.WriteLine(extensionName + " successfully registered with ArcGIS Server");
                }
                else
                    Console.WriteLine(extensionName + " is already registered with ArcGIS Server");
            }

            Console.ReadLine();
        }

        // Checks whether an extension with the passed-in name is already registered with the passed-in server
        static private bool ExtensionRegistered(ESRI.ArcGIS.Server.IServerObjectAdmin2 serverObjectAdmin, string extensionName)
        {
            // Get the extensions that extend MapServer server objects
            ESRI.ArcGIS.Server.IEnumServerObjectExtensionType extensionTypes = serverObjectAdmin.GetExtensionTypes("MapServer");
            extensionTypes.Reset();

            // If an extension with a name matching that passed-in is found, return true
            ESRI.ArcGIS.Server.IServerObjectExtensionType extensionType = extensionTypes.Next();
            while (extensionType != null)
            {
                if (extensionType.Name == extensionName)
                {
                    //serverObjectAdmin.DeleteExtensionType("MapServer", extensionName);
                    return true;
                }

                extensionType = extensionTypes.Next();
            }

            // No matching extension was found, so return false
            return false;
        }
    }
}

在代码中有个地方需要注意:

serverObjectExtensionType.CLSID = "Saturation.Saturation";

CLSID的值必须与你的命名空间的类名相一致

 

2.注册

  (1)注册COM组件

  SOE其实是运行在服务器端的COM组件,并且你需要在每台运行SOC的机器上都为其注册COM组件

  * 右击Saturation工程--》属性--》生成,将目标平台选为“x86”,因为ArcServer是运行在32位机器上

  *在属性中选择“签名”选项卡,为程序集生成一个签名

  *在开始菜单-》visual studio 20110-》visual studio tools-》命令提示,打开命令提示工具

  *在命令提示工具中输入命令:regasm <path to DLL> /codebase,在本例中输入如下命令:

  regasm “C:\Users\LZZ\Documents\Visual Studio 2010\Projects\Saturation\Saturation\bin\Debug\Saturation.dll” /codebase

  (2)ArcServer服务器注册

  现在程序集已经注册号,接下来要在ArcServer服务器上注册,这里要用到RegisterSaturation工程,右击工程-》属性-》调试-》启动新实例,如果注册成功,你会看到一个提示成功的信息。

   注意:在注册的时候一定要保证让运行在这台机器上的soc用户能够访问到你上面注册的dll,否则会提示你无法注册(给soc用户能够读取你注册的dll的权限)

3.调试

  如果没有调试的话,那岂不是太痛苦了,不过还有说回来,SOE这个东西有调试也很痛苦。他需要附加到SOC进程中去,而你的机器上往往会有多个SOC进程,这时候如果你附加错误的话,你是无法进行调试的,我常用的方法是把其他的服务全部删除,是删除不是停止;这里还会碰到一个古怪的问题,就是第一次你可以调试,当你停止调后,再一次附加到进城后却无法调试,我的方法是停止服务,将该工程重新生成,然后启动服务,在附加到进程中去。这是我的这几天捉摸出来的经验。在调试之前我们首先需要使服务支持SOE,貌似在ArcGIS10中只支持MapServer的SOE。

  这里我建议你用Manager来发布服务,发布服务的方法跟发布普通mapServer的方法一样,如果你的SOE在服务器上注册成功的话,你会看到以下内容:

 

  在这里你不需要选中,我碰到过注册成功后这在里面却不显示的问题,这时候你只要重启一下计算机即可。发布服务成功后,点击编辑服务:

 

在这里选中Saturation REST,在下方选中两个check框,点击右边按钮保存并重启,现在我们的mapServer已经有了SOE能力。接下来我们进行调试:

在VS中点击调试-》附加到进程:

如果你看到你附加到进城后,断点依然显示的话,说明可以正常调试,否则你就需要看一下前文提到的解决方法啦。

当点击按钮时,后进入VS中的断点处:

运行成功后,你会看到返回的结果为json类型对象

现在我们已经介绍完SOE的内容了,如果你还有什么不了解的可以直接看帮助:

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Extending_ArcGIS_Server/0001000000mv000000/

  这里补充几句:官网中有三个例子,其中空间查询的那个我没运行成功,是跟里面设置属性也有关,因为我没用过里面的WebControl对他不太了解,而且我们的东西不需要使用属性页,所以暂时还无法解决他。希望有哪位大神看了这篇文章后能给小人指点一下,感激不尽。

 

  这个教程到这里就暂时告一段落了,如果以后还碰到关于这种技术的问题话,我会继续发博文的。

  在这里顺便感谢一下群哥多年来的帮助,这个技术也是从他那听说的。可以说没有群哥,也就没有这系列教程。呵呵,祝大家好运!!!

时间: 2024-10-29 05:39:13

ArcGIS 服务对象扩展(SOE)新手自学笔记(5):注册与调试的相关文章

ArcGIS 服务对象扩展(SOE)新手自学笔记(1):初识SOE

1.SOE介绍 在ArcGIS 10.1中ArcGIS Server不在支持DCOM方式的连接,这也就意味着我们不能通过本地方式的连接使用ArcObjects提供的更多功能,所以我们推荐一种新的方式来实现这些功能,这种方式就是SOE服务器对象扩展.SOE存在于整个服务对象的生存期内,可以利用服务对象的资源并对其进行扩展.一个SOE通常在服务对象创建是初始化,并且在整个服务对象的生存期内只会被创建一次.SOE支持SOAP和REST两种访问方式,其通过强大的AO来扩展服务对象,并可以运行在一个没有A

ArcGIS 服务对象扩展(SOE)新手自学笔记(4):Schema、Resource、Operation

前面几节我们介绍了SOE基本概念.REST SOE模板以及如何处理输入输出数据.今天详细介绍一下SOE中三个重要概念:Schema.Resource.Operation. 1.Schema SOE中的Resource和Operation所组成的结构就是Schema,也可以说Shcema确定了SOE中Resource和Operation的层次结构.通常由IRESTRequestHandler接口的GetSchema()方法来返回该SOE的Schema,作为一个JSON格式的字符串被返回.在REST

ArcGIS 服务对象扩展(SOE)新手自学笔记(2):REST SOE模板上

1.REST SOE 当客户端使用REST方式发送SOE请求时,实际上是利用HTTP协议发送了一个请求字符串,ArcServer获得该字符串后会将其解析成一系列命令执行,并返回JSON数据. 返回的JSON格式数据如下:   2.创建REST SOE (1)提醒 为了确保你创建的REST SOE能够成功执行,你需要仔细考虑一下向服务器端发送请求的数据类型和你希望返回的数据. 一个REST SOE通常包含资源和操作两部分(Resource和Operation): Resource---可以从服务器

ArcGIS 服务对象扩展(SOE)新手自学笔记(3):REST SOE模板下

1.CreateRESTSchema()和Handle function CreateRESTSchema函数中定义了在你的SOE中可以获取的Resource和Operation,每一个Resource和Operation都与一个处理函数(handle function)相关联.该处理函数用来在Resource或Operation被触发时,描述所要进行的处理操作.这里面就是你需要编写大量AO代码的地方. 在REST SOE模板中,有一个处理resource逻辑的RootRESTHandler函数

运行Node.js的IIS扩展iisnode安装配置笔记

 这篇文章主要介绍了运行Node.js的IIS扩展iisnode安装配置笔记,iisnode的扩展可以把Node.js程序托管到IIS,托管之后也意味着可以使用IIS里面的各种功能,需要的朋友可以参考下     今年年初打算用Node.js基于Express框架重写博客程序,从此告别ASP.NET.然而,我目前用的VPS是Windows Server系统.IIS服务器,如果让Express和IIS都监听80端口,明显会产生冲突.幸好,有一个叫做iisnode的扩展可以把Node.js程序托管到I

新手自学才c++,请教前辈个问题

问题描述 新手自学才c++,请教前辈个问题 一个类的成员函数 string toString() const 这个const在这里是做什么用的呢,小弟不太理解 解决方案 把成员函数标记为const ,意思就是将此成员函数内部用到的数据成员都标记为const 引用,就是不能够在此函数内部修改对象的数据成员. 非const 对象可以调用const成员函数和非const 成员函数,const对象只能调用const 成员函数 解决方案二: 说明这个函数里不能更改数据成员,也不能调用非const函数.一般

新手自学unity3d遇到了一些问题

问题描述 新手自学unity3d遇到了一些问题 我在"我要自学网"按照caoyutan老师那个射弹游戏案例自己做了一下,卡在了那个让消灭数自加的脚本代码中,代码如下: #pragma strict function Start () { } var sd:int=0; var xm:int=0; function Update () { if(gameObject.transform.position.y<0) { xm=++gameObject.Find("Main

SpringBoot自学笔记(四)

SpringBoot自学笔记(四) 特此声明:本自学笔记,主要是参照<从零开始学Spring Boot>(作者: 林祥纤)一书,并对部分例子进行了改动,便于理解,非盈利为目的,仅供学习交流,如有侵权,立即撤下!  历史笔记链接:<SpringBoot自学笔记(一)>   历史笔记链接:<SpringBoot自学笔记(二)>   历史笔记链接:<SpringBoot自学笔记(三)>  (七)Srping Boot--使用JdbcTemplate及修改Sprin

SpringBoot自学笔记(三)

SpringBoot自学笔记(三) 特此声明:本自学笔记,主要是参照<从零开始学Spring Boot>(作者: 林祥纤)一书,并对部分例子进行了改动,便于理解,非盈利为目的,仅供学习交流,如有侵权,立即撤下!  历史笔记链接:<SpringBoot自学笔记(一)>   历史笔记链接:<SpringBoot自学笔记(二)>  (六)Srping Boot--整合Mysql及Hibernate 1.新建Maven工程,博主以"spring-boot-databa