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

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

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

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

1.编写代码

新建一个工程,命名为Saturation  

首先加入以下引用:

代码:

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 
  6 using System.Collections.Specialized;
  7 
  8 using System.Runtime.InteropServices;
  9 using System.EnterpriseServices;
 10 
 11 using ESRI.ArcGIS.esriSystem;
 12 using ESRI.ArcGIS.Server;
 13 using ESRI.ArcGIS.Geometry;
 14 using ESRI.ArcGIS.Geodatabase;
 15 using ESRI.ArcGIS.Carto;
 16 using ESRI.ArcGIS.SOESupport;
 17 using ESRI.ArcGIS.GeoAnalyst;
 18 using ESRI.ArcGIS.DataSourcesRaster;
 19 
 20 
 21 //TODO: sign the project (project properties > signing tab > sign the assembly)
 22 //      this is strongly suggested if the dll will be registered using regasm.exe <your>.dll /codebase
 23 
 24 
 25 namespace Saturation
 26 {
 27     [ComVisible(true)]
 28     [Guid("f8cb9f88-1dc9-4f34-a0a9-fa931afb8730")]
 29     [ClassInterface(ClassInterfaceType.None)]
 30     public class Saturation : ServicedComponent, IServerObjectExtension, IObjectConstruct, IRESTRequestHandler
 31     {
 32         private string soe_name;
 33 
 34         private IPropertySet configProps;
 35         private IServerObjectHelper serverObjectHelper;
 36         private ServerLogger logger;
 37         private IRESTRequestHandler reqHandler;
 38 
 39         //Member variables
 40         private string m_layerNameToAnalyst = null;
 41         private IFeatureClass m_fcToAnalyst = null;//进行插值的要素类
 42 
 43         public Saturation()
 44         {
 45             soe_name = this.GetType().Name;
 46             logger = new ServerLogger();
 47             reqHandler = new SoeRestImpl(soe_name, CreateRestSchema()) as IRESTRequestHandler;
 48         }
 49 
 50         #region IServerObjectExtension Members
 51 
 52         public void Init(IServerObjectHelper pSOH)
 53         {
 54             serverObjectHelper = pSOH;
 55         }
 56 
 57         public void Shutdown()
 58         {
 59             logger.LogMessage(ServerLogger.msgType.infoStandard, "Shutdown", 8000, "Custom error message: Shutting down the SOE");
 60             soe_name = null;
 61             m_fcToAnalyst = null;
 62             serverObjectHelper = null;
 63             m_layerNameToAnalyst = null;
 64             logger = null;
 65         }
 66 
 67         #endregion
 68 
 69         #region IObjectConstruct Members
 70 
 71         public void Construct(IPropertySet props)
 72         {
 73             logger.LogMessage(ServerLogger.msgType.error, "Construct", 8000, "SOE Construct:start");
 74             configProps = props;
 75             m_layerNameToAnalyst = "testPoint";
 76             //获得所要分析的FeatureClass
 77             try
 78             {
 79                 IMapServer3 mapServer = serverObjectHelper.ServerObject as IMapServer3;
 80 
 81                 string mapName = mapServer.DefaultMapName;
 82                 IMapLayerInfos layerInfos = mapServer.GetServerInfo(mapName).MapLayerInfos;
 83                 IMapLayerInfo layerInfo = null;
 84 
 85                 //获得所要分析图层的index
 86                 int c = layerInfos.Count;
 87                 int layerIndex = 0;
 88                 for (int i = 0; i < c; i++)
 89                 {
 90                     layerInfo = layerInfos.get_Element(i);
 91                     if (layerInfo.Name == m_layerNameToAnalyst)
 92                     {
 93                         layerIndex = i;
 94                         break;
 95                     }
 96                 }
 97 
 98                 //使用IMapServerDataAccess获取数据
 99                 IMapServerDataAccess dataAccess = mapServer as IMapServerDataAccess;
100                 m_fcToAnalyst = dataAccess.GetDataSource(mapName, layerIndex) as IFeatureClass;
101 
102                 if (m_fcToAnalyst == null)
103                 {
104                     logger.LogMessage(ServerLogger.msgType.error, "Construct", 8000, "SOE custom error: Layer name not found.");
105                     return;
106                 }
107             }
108             catch (Exception es)
109             {
110                 logger.LogMessage(ServerLogger.msgType.error, "Construct", 8000, "SOE custom error: Could not get the feature layer.");
111             }
112         }
113 
114         #endregion
115 
116         #region IRESTRequestHandler Members
117 
118         public string GetSchema()
119         {
120             return reqHandler.GetSchema();
121         }
122 
123         public byte[] HandleRESTRequest(string Capabilities, string resourceName, string operationName, string operationInput, string outputFormat, string requestProperties, out string responseProperties)
124         {
125             return reqHandler.HandleRESTRequest(Capabilities, resourceName, operationName, operationInput, outputFormat, requestProperties, out responseProperties);
126         }
127 
128         #endregion
129 
130         private RestResource CreateRestSchema()
131         {
132             RestResource rootRes = new RestResource(soe_name, false, RootResHandler);
133 
134             RestOperation sampleOper = new RestOperation("sampleOperation",
135                                                       new string[] { "field" },
136                                                       new string[] { "json" },
137                                                       SaturationAnalystOpeartionHandler);
138 
139             rootRes.operations.Add(sampleOper);
140 
141             return rootRes;
142         }
143 
144         private byte[] RootResHandler(NameValueCollection boundVariables, string outputFormat, string requestProperties, out string responseProperties)
145         {
146             responseProperties = null;
147 
148             JsonObject result = new JsonObject();
149             //result.AddString("hello", "world");
150 
151             return Encoding.UTF8.GetBytes(result.ToJson());
152         }
153 
154         private byte[] SaturationAnalystOpeartionHandler(NameValueCollection boundVariables,
155                                                   JsonObject operationInput,
156                                                       string outputFormat,
157                                                       string requestProperties,
158                                                   out string responseProperties)
159         {
160             responseProperties = null;
161             //反序列化参数
162             string strField;
163             bool found = operationInput.TryGetString("field", out strField);
164             if (!found || string.IsNullOrEmpty(strField))
165                 throw new ArgumentNullException("field");
166 
167             byte[] result = SaturationAnalyst(strField);
168 
169             return result;
170         }
171 
172         private byte[] SaturationAnalyst(string field)
173         {
174             if (field.Length <= 0)
175             {
176                 throw new ArgumentOutOfRangeException("field");
177             }
178 
179             //插值
180             IRaster krigeRaster = BuildKrigeRaster(m_fcToAnalyst, field);
181             //重分类
182             IRaster reclassRastr = BuildReclassRaster(krigeRaster, 4);
183             //栅格转面,字段名作为生成的要素名称
184             IFeatureClass ConPolygon = RasterToPolygon(reclassRastr, field);
185             //将要素类序列化成json格式
186             JsonObject resultJsonObject = FclassToJsonObj(ConPolygon);
187 
188             byte[] result = Encoding.UTF8.GetBytes(resultJsonObject.ToJson());
189             return result;
190 
191         }
192 
193         #region Helper 函数
194         /// <summary>
195         /// 克里金插值
196         /// </summary>
197         /// <param name="inputFclass">插值数据</param>
198         /// <param name="inputField">字段</param>
199         /// <returns></returns>
200         private IRaster BuildKrigeRaster(IFeatureClass inputFclass, string inputField)
201         {
202             if (inputFclass == null)
203             {
204                 logger.LogMessage(ServerLogger.msgType.error, "BuildKrigeRaster", 8000, "SOE custom error: inputFclass is null.");
205                 return null;
206             }
207             if (inputField.Length == 0)
208             {
209                 logger.LogMessage(ServerLogger.msgType.error, "BuildKrigeRaster", 8000, "SOE custom error: inputField is null.");
210                 return null;
211             }
212             
213             //生成IFeatureClassDescriptor
214             IFeatureClassDescriptor pFcDescriptor = new FeatureClassDescriptorClass();
215             pFcDescriptor.Create(inputFclass, null, inputField);
216             //设置分析环境
217             IInterpolationOp pInterpolationOp = new RasterInterpolationOpClass();
218             IRasterAnalysisEnvironment pEnv = pInterpolationOp as IRasterAnalysisEnvironment;
219             object cellSize = 5.80481468000016E-04;
220             pEnv.Reset();//栅格单元大小
221             pEnv.SetCellSize(esriRasterEnvSettingEnum.esriRasterEnvValue, ref cellSize);
222 
223             IRasterRadius pRadius = new RasterRadius();
224             object obj = Type.Missing;//可变搜索半径
225             pRadius.SetVariable(12, ref obj);
226 
227             IGeoDataset pGeodataset = inputFclass as IGeoDataset;
228             IEnvelope pRasterExt = new EnvelopeClass();
229             pRasterExt.XMin = 117.178625;
230             pRasterExt.XMax = 117.376715;
231             pRasterExt.YMax = 31.922649;
232             pRasterExt.YMin = 31.777529;
233             object extentPro = pRasterExt;//分析范围
234             pEnv.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, ref extentPro, ref obj);
235             pEnv.OutSpatialReference = pGeodataset.SpatialReference;
236             //执行差值
237             IGeoDataset pGeoDataset = pInterpolationOp.Krige((IGeoDataset)pFcDescriptor, esriGeoAnalysisSemiVariogramEnum.esriGeoAnalysisLinearSemiVariogram,
238                 pRadius, false, ref obj);
239 
240             return pGeoDataset as IRaster;
241         }
242 
243         /// <summary>
244         /// 对栅格进行等间距重分类
245         /// </summary>
246         /// <param name="inputRaster">待分类栅格</param>
247         /// <param name="pClassNo">分类数</param>
248         /// <returns></returns>
249         private IRaster BuildReclassRaster(IRaster inputRaster, int pClassNo)
250         {
251             if (inputRaster == null)
252             {
253                 logger.LogMessage(ServerLogger.msgType.error, "BuildReclassRaster", 8000, "SOE custom error: inputRaster is null.");
254                 return null;
255             }
256             if (pClassNo <= 0)
257             {
258                 logger.LogMessage(ServerLogger.msgType.error, "BuildReclassRaster", 8000, "SOE custom error: pClassNo is null.");
259                 return null;
260             }
261 
262             //获取栅格分类数组和频度数组
263             object dataValues = null, dataCounts = null;
264             GetRasterClass(inputRaster, out dataValues, out dataCounts);
265 
266             //获取栅格分类间隔数组
267             IClassifyGEN pEqualIntervalClass = new EqualIntervalClass();
268             pEqualIntervalClass.Classify(dataValues, dataCounts, ref pClassNo);
269             double[] breaks = pEqualIntervalClass.ClassBreaks as double[];
270 
271             //设置新分类值
272             INumberRemap pNemRemap = new NumberRemapClass();
273             for (int i = 0; i < breaks.Length - 1; i++)
274             {
275                 pNemRemap.MapRange(breaks[i], breaks[i + 1], i+1);
276             }
277             IRemap pRemap = pNemRemap as IRemap;
278             
279             //设置环境
280             IReclassOp pReclassOp = new RasterReclassOpClass();
281             IGeoDataset pGeodataset = inputRaster as IGeoDataset;
282             IRasterAnalysisEnvironment pEnv = pReclassOp as IRasterAnalysisEnvironment;
283             object obj = Type.Missing;
284 
285             IEnvelope pRasterExt = new EnvelopeClass();
286             pRasterExt.XMin = 117.178625;
287             pRasterExt.XMax = 117.376715;
288             pRasterExt.YMax = 31.922649;
289             pRasterExt.YMin = 31.777529;
290             object extentPro = pRasterExt;//分析范围
291             pEnv.SetExtent(esriRasterEnvSettingEnum.esriRasterEnvValue, ref extentPro, ref obj);
292             pEnv.OutSpatialReference = pGeodataset.SpatialReference;
293 
294             //重分类
295             IRaster pRaster = pReclassOp.ReclassByRemap(pGeodataset, pRemap, false) as IRaster;
296             return pRaster;
297         }
298 
299         /// <summary>
300         /// 获取栅格分类数组和频度数组
301         /// </summary>
302         /// <param name="inputRaster">输入栅格</param>
303         /// <param name="dataValues"></param>
304         /// <param name="dataCounts"></param>
305         private void GetRasterClass(IRaster inputRaster, out object dataValues, out object dataCounts)
306         {
307             IRasterBandCollection pRasBandCol = inputRaster as IRasterBandCollection;
308             IRasterBand pRsBand = pRasBandCol.Item(0);
309             pRsBand.ComputeStatsAndHist();//IRasterBand中本无统计直方图,必须先进行ComputeStatsAndHist()
310             IRasterStatistics pRasterStatistic = pRsBand.Statistics;
311 
312             double mMean = pRasterStatistic.Mean;
313             double mStandsrdDeviation = pRasterStatistic.StandardDeviation;
314 
315             IRasterHistogram pRasterHistogram = pRsBand.Histogram;
316             double[] dblValues;
317             dblValues = pRasterHistogram.Counts as double[];
318             int intValueCount = dblValues.GetUpperBound(0) + 1;
319             double[] vValues = new double[intValueCount];
320 
321             double dMaxValue = pRasterStatistic.Maximum;
322             double dMinValue = pRasterStatistic.Minimum;
323             double BinInterval = Convert.ToDouble((dMaxValue - dMinValue) / intValueCount);
324             for (int i = 0; i < intValueCount; i++)
325             {
326                 vValues[i] = i * BinInterval + pRasterStatistic.Minimum;
327             }
328 
329             dataValues = vValues as object;
330             dataCounts = dblValues as object;
331         }
332 
333         /// <summary>
334         /// 栅格转面
335         /// </summary>
336         /// <param name="inputRaster">待转换栅格</param>
337         /// <param name="fcName">生成要素类名称</param>
338         /// <returns></returns>
339         private IFeatureClass RasterToPolygon(IRaster inputRaster, string fcName)
340         {
341             //获得testPoint所在工作空间
342             IWorkspace pWorkspace = (m_fcToAnalyst as IDataset).Workspace;
343             IRasterBandCollection pRasBandCol = inputRaster as IRasterBandCollection;
344             IRasterBand pRsBand = pRasBandCol.Item(0);
345             IRasterDataset pRasterDataset = pRsBand as IRasterDataset;
346             IGeoDataset pRasterGeoDataset = pRasterDataset as IGeoDataset;
347 
348             //栅格转面
349             IConversionOp pConversionOp = new RasterConversionOpClass();
350             ISpatialReference pSpatialReference = pRasterGeoDataset.SpatialReference;
351 
352             IGeoDataset pGeoDataset = pConversionOp.RasterDataToPolygonFeatureData(pRasterGeoDataset, pWorkspace, fcName, true);
353             return pGeoDataset as IFeatureClass;
354         }
355 
356         /// <summary>
357         /// 将要素类序列化成json格式对象
358         /// </summary>
359         /// <param name="inputFeaClass">输入要素类</param>
360         /// <returns></returns>
361         private JsonObject FclassToJsonObj(IFeatureClass inputFeaClass)
362         {
363             //获取要素数目
364             IQueryFilter pQueryFilter = new QueryFilterClass();
365             pQueryFilter.WhereClause = null;
366             int count = inputFeaClass.FeatureCount(pQueryFilter);
367 
368             //将每一个要素序列化成json数据
369             IFeature pFeature = null;
370             List<JsonObject> jsonGeometries = new List<JsonObject>();
371             for (int i = 1; i < count; i++)//OBJECTID从1开始
372             {
373                 pFeature = inputFeaClass.GetFeature(i);
374                 IGeometry pGeometry = pFeature.Shape;
375                 JsonObject featureJson = new JsonObject();
376                 JsonObject feaGeoJson = null;//几何对象
377                 if (pGeometry != null)
378                 {
379                     feaGeoJson = Conversion.ToJsonObject(pGeometry);
380                     featureJson.AddJsonObject("geometry", feaGeoJson);//加入几何对象
381                 }
382 
383                  
384                 double grid_Code = (double)pFeature.get_Value(pFeature.Fields.FindField("GRIDCODE"));
385                 featureJson.AddLong("id", i);//id
386                 featureJson.AddDouble("gridCode", grid_Code);//等级
387 
388                 jsonGeometries.Add(featureJson);
389             }
390 
391             JsonObject resultJson = new JsonObject();
392             resultJson.AddArray("geometries", jsonGeometries.ToArray());
393             return resultJson;
394         }
395         #endregion
396     }
397 }

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

加入以下引用

代码:

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using ESRI.ArcGIS.esriSystem;
  6 using ESRI.ArcGIS.Server;
  7 using ESRI.ArcGIS;
  8 using ESRI.ArcGIS.ADF.Connection.AGS;
  9 
 10 namespace RegisterSaturation
 11 {
 12     class Program
 13     {
 14         static void Main(string[] args)
 15         {
 16             // Must run as an user in the agsadmin group on the SOM
 17             ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsServerConnection =
 18                 new ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection();
 19             agsServerConnection.Host = "localhost";
 20             agsServerConnection.Connect();
 21             ESRI.ArcGIS.Server.IServerObjectAdmin2 serverObjectAdmin =
 22                 agsServerConnection.ServerObjectAdmin as ESRI.ArcGIS.Server.IServerObjectAdmin2;
 23 
 24             // This name must match those defined for property pages 
 25             string extensionName = "Saturation";
 26 
 27             // Check command line arguments to see if SOE is to be unregistered
 28             if (args.Length == 1 && args[0] == "/unregister")
 29             {
 30                 // Check whether the SOE is registered
 31                 if (ExtensionRegistered(serverObjectAdmin, extensionName))
 32                 {
 33                     // Delete the SOE
 34                     serverObjectAdmin.DeleteExtensionType("MapServer", extensionName);
 35                     Console.WriteLine(extensionName + " successfully unregistered");
 36                 }
 37                 else
 38                     Console.WriteLine(extensionName + " is not registered with ArcGIS Server");
 39             }
 40             else
 41             {
 42                 // Check whether the SOE is registered
 43                 if (!ExtensionRegistered(serverObjectAdmin, extensionName))
 44                 {
 45                     // Use IServerObjectExtensionType3 to get access to info properties
 46                     ESRI.ArcGIS.Server.IServerObjectExtensionType3 serverObjectExtensionType =
 47                         serverObjectAdmin.CreateExtensionType() as ESRI.ArcGIS.Server.IServerObjectExtensionType3;
 48 
 49                     // Must match the namespace and class name of the class implementing IServerObjectExtension
 50                     serverObjectExtensionType.CLSID = "Saturation.Saturation";
 51                     //serverObjectExtensionType.CLSID = "{C41E8674-F186-4a0c-8FC9-AAB7885EFD00}";
 52                     serverObjectExtensionType.Description = "the shops saturation";
 53                     serverObjectExtensionType.Name = extensionName;
 54 
 55                     // Name that will be shown in the capabilities list on property pages
 56                     serverObjectExtensionType.DisplayName = "Saturation REST";
 57 
 58                     // Use info properties to define capabilities and msd support
 59                     serverObjectExtensionType.Info.SetProperty("DefaultWebCapabilities", "GetInfo");
 60                     serverObjectExtensionType.Info.SetProperty("AllWebCapabilities", "GetInfo,Saturation");
 61                     serverObjectExtensionType.Info.SetProperty("SupportsMSD", "true");
 62 
 63                     // Required to enable exposure of SOE with ArcGIS Server REST endpoint
 64                     serverObjectExtensionType.Info.SetProperty("SupportsREST", "true");
 65 
 66                     // Register the SOE with the server
 67                     serverObjectAdmin.AddExtensionType("MapServer", serverObjectExtensionType);
 68 
 69                     Console.WriteLine(extensionName + " successfully registered with ArcGIS Server");
 70                 }
 71                 else
 72                     Console.WriteLine(extensionName + " is already registered with ArcGIS Server");
 73             }
 74 
 75             Console.ReadLine();
 76         }
 77 
 78         // Checks whether an extension with the passed-in name is already registered with the passed-in server
 79         static private bool ExtensionRegistered(ESRI.ArcGIS.Server.IServerObjectAdmin2 serverObjectAdmin, string extensionName)
 80         {
 81             // Get the extensions that extend MapServer server objects
 82             ESRI.ArcGIS.Server.IEnumServerObjectExtensionType extensionTypes = serverObjectAdmin.GetExtensionTypes("MapServer");
 83             extensionTypes.Reset();
 84 
 85             // If an extension with a name matching that passed-in is found, return true
 86             ESRI.ArcGIS.Server.IServerObjectExtensionType extensionType = extensionTypes.Next();
 87             while (extensionType != null)
 88             {
 89                 if (extensionType.Name == extensionName)
 90                 {
 91                     //serverObjectAdmin.DeleteExtensionType("MapServer", extensionName);
 92                     return true;
 93                 }
 94                     
 95 
 96                 extensionType = extensionTypes.Next();
 97             }
 98 
 99             // No matching extension was found, so return false
100             return false;
101         }
102     }
103 }

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

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对他不太了解,而且我们的东西不需要使用属性页,所以暂时还无法解决他。希望有哪位大神看了这篇文章后能给小人指点一下,感激不尽。

 

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值