ARCGIS 10.1 for Server SOE介绍及开发实例(2)
2014-10-16 09:01
441 查看
第二章 SOE使用
1.1 必选接口
1.1.1 IRESTRequestHandler 接口
该接口主要有下面两个方法:
string GetSchema(); byte[] HandleRESTRequest()
1.1.1.1 IRESTRequestHandler.handleRESTREquest() 方法主要有下面
两个作用:
回调资源和操作的方法
获取资源在实例级别的描述该方法在识别这两个作用的时候是通过operationName参数,如果该参数是空字符产那就是第二个作用,否则是第一个作用。
该方法的参数如下:
1. String capabilities:一组被资源授权的操作,可以为空字符串
2. String resourceName: 资源名称. 空字符串表示根级别,子资源会通过
‘/’ 表示
3. String operationName: 操作名称
4. String operationInput: 操作的参数,JSON格式
5. String outputFormat:客户端请求的输出格式,如JSON,AMF
6. String[] responseProperties: 通过操作返回的一组键值对,逗号分开 1.1.1.2 IRESTRequestHandler.getSchema() 方法
以 JSON 格式返回 SOE 的资源列表
1.1.2 IServerObjectExtension
该接口主要有个方法:Init(IServerObjectHelper pSOH)和void Shutdown();
当Server启动的时候会调用该方法,并将IServerObjectHelper对象传入,该接口是对Server对象的弱引用,可以通过IServerObjectHelper.ServerObject得到服务器对象。 Shutdown方法用在服务器关闭时调用,经常我们在该方法中释放SOE中使用的资源。
1.2 可选接口
1.2.1 IObjectConstruct
该接口只有一个方法Construct,该方法在Init方法执行后,立即被执行,如果我们的SOE有配置属性,就可通过该方法的参数得到,该方法只调用1次,我们可以将SOE中用的的比较耗费资源的逻辑写在该方法中,比如:获取地图代码,或者你始终操作某一个图层,就可以把获取该图层的代码写在这里。
1.2.2 IObjectActivate
当 init 和 Construct 调用后,SOE 的对象已经被创建,并且相应的配置信息也得到了,如果 SOE 的整个逻辑中需要不停的获取和释放服务器上下文,那么就必须实现改接口,改接口有两个方法: activate()和 deactivate(),当客户端调用CreateServerContext() 的时候 activate()方法被调用,当客户端释放服务器上下文对象时 deactivate()方法被调用。
SOE 的执行过程
在对接口介绍的时候,我们已经提到了 SOE 的的运行过程,我们通过下面
的图可进一步了解:
![](http://img.blog.csdn.net/20141015201309828?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWVsbG9f/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20141015201812548?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWVsbG9f/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
当点了确定之后,我们可以看到VS 已经为我们生成了一个 RestSOETest 的类,该类已经实现了了我们前面介绍过的接口,如下:
public class
RestSOETest : IServerObjectExtension,
IObjectConstruct, IRESTRequestHandler
{
private
string soe_name;
private
IPropertySet configProps;
private
IServerObjectHelper serverObjectHelper;
private
ServerLogger logger; private
IRESTRequestHandler reqHandler;
public RestSOETest()
{
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()
{
}
#endregion
#region IObjectConstruct Members
public void Construct(IPropertySet props)
{
configProps = props;
}
#endregion
#region IRESTRequestHandler Members
public string GetSchema()
{
returnreqHandler.GetSchema();
}
public byte[] HandleRESTRequest(string Capabilities,string resourceName,string operationName,
stringoperationInput,string outputFormat,stringrequestProperties,outstring responseProperties)
{
returnreqHandler.HandleRESTRequest(Capabilities, resourceName, operationName,operationInput, outputFormat, requestProperties,out responseProperties);
}
在构造函数中多了一个ServerLogger 的对象,通过名称我们就可知道,该对象是一个日志记录对象,用该对象可以对我们的 SOE进行信息记录,记录后的信息,最后可以通过 Manager 的日志查看。在构造函数中还调用了
CreateRestSchema 函数,如下:
private RestResource CreateRestSchema()
{
RestResource rootRes =
new RestResource(soe_name,
false,RootResHandler);
RestOperation sampleOper =
new RestOperation("sampleOperation",newstring[] {"parm1","parm2"
},
new string[] {"json" }, SampleOperHandler);
rootRes.operations.Add(sampleOper);
return rootRes;
}
在该函数中创建了Rest 资源和 Rest 资源的操作,并且资源和 Rest 操作都对应一个处理函数,我们一般称作 Resthandler,这里的资源和操作可能比较抽象,我们举一个例子,比如说MapService 就是一个资源,而查询就是一个操作,当我们执行操作的时候,处理整个逻辑的就是Resthandler,如上图的
RootResHandler 和SampleOperHandler 分别是处理资源和资源操作的方法,这些 handler 的具体实现如下:
private byte[] RootResHandler(NameValueCollection boundVariables,string outputFormat,string
requestProperties,outstring responseProperties)
{
responseProperties = null;
JsonObject result =
new JsonObject();
result.AddString("hello",
"world");
return
Encoding.UTF8.GetBytes(result.ToJson());
}
private byte[] SampleOperHandler(NameValueCollectio boundVariables, JsonObject operationInput,
string outputFormat,string requestProperties, outstring responseProperties)
{
responseProperties = null;
string parm1Value;
bool found = operationInput.TryGetString("parm1",out parm1Value);
if (!found ||
string.IsNullOrEmpty(parm1Value))
throw newArgumentNullException("parm1");
string parm2Value;
found =operationInput.TryGetString("parm2",out parm2Value);
if (!found ||
string.IsNullOrEmpty(parm2Value))
throw newArgumentNullException("parm2");
JsonObject result =
new JsonObject();
result.AddString("parm1", parm1Value);
result.AddString("parm2", parm2Value);
return
Encoding.UTF8.GetBytes(result.ToJson());
}
在这里我们要注意RestOperation类,该类对应了我们SOE的一个操作,该类的参数如下:
RestOperation (string name, string[]parameters, string[]supportedFormats, OperationHandlerhandler),这些参数分别对应了操作
的名称,参数,支持的格式,以及该操作的处理函数。一个资源可以有子资源,并且一个资源可以对应多个操作,对于资源的handler我们可以不用关注,但是操作的handler是我们整个SOE的核心部分。下面是我们自定义的一个操作,其中pLineOperHandler是对应我们的handler
定义的操作:
RestOperation pLineOper =
new RestOperation("pLineOperation",newstring[] {"RouteFieldName",
"RouteID", "Stationfrom","Stationto" },newstring[] {"json"
},pLineOperHandler);
当定义好了RestOperation 之后,并且成功部署,那么可以在服务目录中看到下面的页面:
![](http://img.blog.csdn.net/20141015202748126?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWVsbG9f/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
我们可以看出,RestOperation 类中的参数和这个对应,当我们点了 GET 或者 POST 操作之后,这个时候就执行 PlineOperHandler 操作,该函数的定义如下:
private byte[] pLineOperHandler(NameValueCollection boundVariables,
JsonObject operationInput,
string outputFormat,
string requestProperties,
out string responseProperties)
{
responseProperties = "";
if (serverObjectHelper.ServerObject is IMapServer)
{
mapServer = (IMapServer3)serverObjectHelper.ServerObject;
}
// IMapServerObjects pMSO = serverObjectHelper.ServerObject as IMapServerObjects;
IMapServerDataAccess pMapServerDataAcc = null;
IFeatureClass pFeatureClass = null;
if (serverObjectHelper.ServerObject is IMapServerDataAccess)
{
pMapServerDataAcc = serverObjectHelper.ServerObject as IMapServerDataAccess;
pFeatureClass = pMapServerDataAcc.GetDataSource(mapServer.DefaultMapName, 0) as IFeatureClass;
}
// // IMapServer.DefaultMapName
//// IMap map = pMSO.get_Map(mapServer.DefaultMapName);
// //返回参与线性参考
// // routeFeatureLayer = (IFeatureLayer)map.get_Layer(0);
// //线性参考代码
// IFeatureLayer featureLayer = routeFeatureLayer;
string _pPKName;
operationInput.TryGetString("RouteFieldName", out _pPKName);
if (_pPKName==null)
throw new ArgumentNullException("StationMeasure");
long? _pID;
operationInput.TryGetAsLong("RouteID", out _pID);
if (_pID == null)
throw new ArgumentNullException("RouteID");
double ? _pFrom;
operationInput.TryGetAsDouble("Stationfrom", out _pFrom);
if (_pFrom == null)
throw new ArgumentNullException("Stationfrom");
double? _pTo;
operationInput.TryGetAsDouble("Stationto", out _pTo);
if (_pTo == null)
throw new ArgumentNullException("Stationto");
IPolyline pointColl = FindRoutByMeasure(pFeatureClass, _pPKName.Substring(1, _pPKName.Length - 2), _pID.Value, _pFrom.Value, _pTo.Value);
JsonObject featureJson = new JsonObject();
featureJson.AddJsonObject("geometry", Conversion.ToJsonObject(pointColl as IGeometry));
return Encoding.UTF8.GetBytes( featureJson.ToJson());
}
在前面已经介绍过,SOE里面的很大一部分代码是和AO对象打交道,而这部分也是我们的核心功能,当我们使用Esri提供给的SOE模板之后,我们要核心要做的就是写SOE请求函数,在这个请求函数也就是handler中,我们的核心AO代码就在这里,我这个函数的核心代码如下:
IPolyline FindRoutByMeasure(IFeatureClass _pRouteFC, string _pPKName, object _pID, double _pFrom,
double _pTo)
{
IDataset pDataset = (IDataset)_pRouteFC;
IName pName = pDataset.FullName;
IRouteLocatorName pRouteLocatorName = new RouteMeasureLocatorNameClass();
pRouteLocatorName.RouteFeatureClassName = pName;
pRouteLocatorName.RouteIDFieldName = _pPKName;
pRouteLocatorName.RouteMeasureUnit = esriUnits.esriFeet;
pName = (IName)pRouteLocatorName;
IRouteLocator2 pRouteLocator = (IRouteLocator2)pName.Open();
IRouteLocation pRouteLoc = new RouteMeasureLineLocationClass();
pRouteLoc.MeasureUnit = esriUnits.esriFeet;
pRouteLoc.RouteID = _pID;
IRouteMeasureLineLocation rMLineLoc = (IRouteMeasureLineLocation)pRouteLoc;
rMLineLoc.FromMeasure = _pFrom;
rMLineLoc.ToMeasure = _pTo;
IGeometry pGeo = null;
esriLocatingError locError;
pRouteLocator.Locate(pRouteLoc, out pGeo, out locError);
return pGeo as IPolyline;
}
其实如果在ArcGIS Engine中做过和线性参考相关的工作,那么这端代码是完全可以在ArcGIS Engine中使用的,所以说SOE的开发并不是想象中的困难,相反如果有了AO基础的话,的确是很简单。
注意:
在这里我将自己遇到的问题说一下,如果在ArcGIS 10或者之前的版本中使用过SOE,那么发现下面的代码是可以运行的,而且没有问题:
IMapServer mapServer = (IMapServer3)serverObjectHelper.ServerObject;
IMapServerObjects3 pMSO = mapServer as IMapServerObjects3;
IMap map = pMSO.get_Map(mapServer.DefaultMapName);
但是在10.1的时候,这句代码是不会成功的,错误的地方在IMapServerObjects3,这是因为10.1中发布的服务是使用MSD文档,而IMapServerObjects3是针对MXD文档的,因此在10.1中应避免,避免IMap,Ilayer等,那么如何访问要素类,栅格对象,表等对象呢?使用IMapServerDataAccess接口,该接口主要有两个方法,如下图:
![](http://img.blog.csdn.net/20141016092105235?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTWVsbG9f/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
第一个方法主要获取表,要素类,栅格数据,但是在地图文档中我们有的数据是和其他数据有关联的的比如join操作,那么通过第二个方法我们不但可以获取源表的数据,还可以获取目的表的数据。
1.1 必选接口
1.1.1 IRESTRequestHandler 接口
该接口主要有下面两个方法:
string GetSchema(); byte[] HandleRESTRequest()
1.1.1.1 IRESTRequestHandler.handleRESTREquest() 方法主要有下面
两个作用:
回调资源和操作的方法
获取资源在实例级别的描述该方法在识别这两个作用的时候是通过operationName参数,如果该参数是空字符产那就是第二个作用,否则是第一个作用。
该方法的参数如下:
1. String capabilities:一组被资源授权的操作,可以为空字符串
2. String resourceName: 资源名称. 空字符串表示根级别,子资源会通过
‘/’ 表示
3. String operationName: 操作名称
4. String operationInput: 操作的参数,JSON格式
5. String outputFormat:客户端请求的输出格式,如JSON,AMF
6. String[] responseProperties: 通过操作返回的一组键值对,逗号分开 1.1.1.2 IRESTRequestHandler.getSchema() 方法
以 JSON 格式返回 SOE 的资源列表
1.1.2 IServerObjectExtension
该接口主要有个方法:Init(IServerObjectHelper pSOH)和void Shutdown();
当Server启动的时候会调用该方法,并将IServerObjectHelper对象传入,该接口是对Server对象的弱引用,可以通过IServerObjectHelper.ServerObject得到服务器对象。 Shutdown方法用在服务器关闭时调用,经常我们在该方法中释放SOE中使用的资源。
1.2 可选接口
1.2.1 IObjectConstruct
该接口只有一个方法Construct,该方法在Init方法执行后,立即被执行,如果我们的SOE有配置属性,就可通过该方法的参数得到,该方法只调用1次,我们可以将SOE中用的的比较耗费资源的逻辑写在该方法中,比如:获取地图代码,或者你始终操作某一个图层,就可以把获取该图层的代码写在这里。
1.2.2 IObjectActivate
当 init 和 Construct 调用后,SOE 的对象已经被创建,并且相应的配置信息也得到了,如果 SOE 的整个逻辑中需要不停的获取和释放服务器上下文,那么就必须实现改接口,改接口有两个方法: activate()和 deactivate(),当客户端调用CreateServerContext() 的时候 activate()方法被调用,当客户端释放服务器上下文对象时 deactivate()方法被调用。
SOE 的执行过程
在对接口介绍的时候,我们已经提到了 SOE 的的运行过程,我们通过下面
的图可进一步了解:
1.3 创建SOE
现在我们创建一个完整的SOE,在 VS2010 中新建一个项目,选择 Server
Object Extention,并在右边选择REST 模板,如下图:当点了确定之后,我们可以看到VS 已经为我们生成了一个 RestSOETest 的类,该类已经实现了了我们前面介绍过的接口,如下:
public class
RestSOETest : IServerObjectExtension,
IObjectConstruct, IRESTRequestHandler
{
private
string soe_name;
private
IPropertySet configProps;
private
IServerObjectHelper serverObjectHelper;
private
ServerLogger logger; private
IRESTRequestHandler reqHandler;
public RestSOETest()
{
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()
{
}
#endregion
#region IObjectConstruct Members
public void Construct(IPropertySet props)
{
configProps = props;
}
#endregion
#region IRESTRequestHandler Members
public string GetSchema()
{
returnreqHandler.GetSchema();
}
public byte[] HandleRESTRequest(string Capabilities,string resourceName,string operationName,
stringoperationInput,string outputFormat,stringrequestProperties,outstring responseProperties)
{
returnreqHandler.HandleRESTRequest(Capabilities, resourceName, operationName,operationInput, outputFormat, requestProperties,out responseProperties);
}
在构造函数中多了一个ServerLogger 的对象,通过名称我们就可知道,该对象是一个日志记录对象,用该对象可以对我们的 SOE进行信息记录,记录后的信息,最后可以通过 Manager 的日志查看。在构造函数中还调用了
CreateRestSchema 函数,如下:
private RestResource CreateRestSchema()
{
RestResource rootRes =
new RestResource(soe_name,
false,RootResHandler);
RestOperation sampleOper =
new RestOperation("sampleOperation",newstring[] {"parm1","parm2"
},
new string[] {"json" }, SampleOperHandler);
rootRes.operations.Add(sampleOper);
return rootRes;
}
在该函数中创建了Rest 资源和 Rest 资源的操作,并且资源和 Rest 操作都对应一个处理函数,我们一般称作 Resthandler,这里的资源和操作可能比较抽象,我们举一个例子,比如说MapService 就是一个资源,而查询就是一个操作,当我们执行操作的时候,处理整个逻辑的就是Resthandler,如上图的
RootResHandler 和SampleOperHandler 分别是处理资源和资源操作的方法,这些 handler 的具体实现如下:
private byte[] RootResHandler(NameValueCollection boundVariables,string outputFormat,string
requestProperties,outstring responseProperties)
{
responseProperties = null;
JsonObject result =
new JsonObject();
result.AddString("hello",
"world");
return
Encoding.UTF8.GetBytes(result.ToJson());
}
private byte[] SampleOperHandler(NameValueCollectio boundVariables, JsonObject operationInput,
string outputFormat,string requestProperties, outstring responseProperties)
{
responseProperties = null;
string parm1Value;
bool found = operationInput.TryGetString("parm1",out parm1Value);
if (!found ||
string.IsNullOrEmpty(parm1Value))
throw newArgumentNullException("parm1");
string parm2Value;
found =operationInput.TryGetString("parm2",out parm2Value);
if (!found ||
string.IsNullOrEmpty(parm2Value))
throw newArgumentNullException("parm2");
JsonObject result =
new JsonObject();
result.AddString("parm1", parm1Value);
result.AddString("parm2", parm2Value);
return
Encoding.UTF8.GetBytes(result.ToJson());
}
在这里我们要注意RestOperation类,该类对应了我们SOE的一个操作,该类的参数如下:
RestOperation (string name, string[]parameters, string[]supportedFormats, OperationHandlerhandler),这些参数分别对应了操作
的名称,参数,支持的格式,以及该操作的处理函数。一个资源可以有子资源,并且一个资源可以对应多个操作,对于资源的handler我们可以不用关注,但是操作的handler是我们整个SOE的核心部分。下面是我们自定义的一个操作,其中pLineOperHandler是对应我们的handler
定义的操作:
RestOperation pLineOper =
new RestOperation("pLineOperation",newstring[] {"RouteFieldName",
"RouteID", "Stationfrom","Stationto" },newstring[] {"json"
},pLineOperHandler);
当定义好了RestOperation 之后,并且成功部署,那么可以在服务目录中看到下面的页面:
我们可以看出,RestOperation 类中的参数和这个对应,当我们点了 GET 或者 POST 操作之后,这个时候就执行 PlineOperHandler 操作,该函数的定义如下:
private byte[] pLineOperHandler(NameValueCollection boundVariables,
JsonObject operationInput,
string outputFormat,
string requestProperties,
out string responseProperties)
{
responseProperties = "";
if (serverObjectHelper.ServerObject is IMapServer)
{
mapServer = (IMapServer3)serverObjectHelper.ServerObject;
}
// IMapServerObjects pMSO = serverObjectHelper.ServerObject as IMapServerObjects;
IMapServerDataAccess pMapServerDataAcc = null;
IFeatureClass pFeatureClass = null;
if (serverObjectHelper.ServerObject is IMapServerDataAccess)
{
pMapServerDataAcc = serverObjectHelper.ServerObject as IMapServerDataAccess;
pFeatureClass = pMapServerDataAcc.GetDataSource(mapServer.DefaultMapName, 0) as IFeatureClass;
}
// // IMapServer.DefaultMapName
//// IMap map = pMSO.get_Map(mapServer.DefaultMapName);
// //返回参与线性参考
// // routeFeatureLayer = (IFeatureLayer)map.get_Layer(0);
// //线性参考代码
// IFeatureLayer featureLayer = routeFeatureLayer;
string _pPKName;
operationInput.TryGetString("RouteFieldName", out _pPKName);
if (_pPKName==null)
throw new ArgumentNullException("StationMeasure");
long? _pID;
operationInput.TryGetAsLong("RouteID", out _pID);
if (_pID == null)
throw new ArgumentNullException("RouteID");
double ? _pFrom;
operationInput.TryGetAsDouble("Stationfrom", out _pFrom);
if (_pFrom == null)
throw new ArgumentNullException("Stationfrom");
double? _pTo;
operationInput.TryGetAsDouble("Stationto", out _pTo);
if (_pTo == null)
throw new ArgumentNullException("Stationto");
IPolyline pointColl = FindRoutByMeasure(pFeatureClass, _pPKName.Substring(1, _pPKName.Length - 2), _pID.Value, _pFrom.Value, _pTo.Value);
JsonObject featureJson = new JsonObject();
featureJson.AddJsonObject("geometry", Conversion.ToJsonObject(pointColl as IGeometry));
return Encoding.UTF8.GetBytes( featureJson.ToJson());
}
在前面已经介绍过,SOE里面的很大一部分代码是和AO对象打交道,而这部分也是我们的核心功能,当我们使用Esri提供给的SOE模板之后,我们要核心要做的就是写SOE请求函数,在这个请求函数也就是handler中,我们的核心AO代码就在这里,我这个函数的核心代码如下:
IPolyline FindRoutByMeasure(IFeatureClass _pRouteFC, string _pPKName, object _pID, double _pFrom,
double _pTo)
{
IDataset pDataset = (IDataset)_pRouteFC;
IName pName = pDataset.FullName;
IRouteLocatorName pRouteLocatorName = new RouteMeasureLocatorNameClass();
pRouteLocatorName.RouteFeatureClassName = pName;
pRouteLocatorName.RouteIDFieldName = _pPKName;
pRouteLocatorName.RouteMeasureUnit = esriUnits.esriFeet;
pName = (IName)pRouteLocatorName;
IRouteLocator2 pRouteLocator = (IRouteLocator2)pName.Open();
IRouteLocation pRouteLoc = new RouteMeasureLineLocationClass();
pRouteLoc.MeasureUnit = esriUnits.esriFeet;
pRouteLoc.RouteID = _pID;
IRouteMeasureLineLocation rMLineLoc = (IRouteMeasureLineLocation)pRouteLoc;
rMLineLoc.FromMeasure = _pFrom;
rMLineLoc.ToMeasure = _pTo;
IGeometry pGeo = null;
esriLocatingError locError;
pRouteLocator.Locate(pRouteLoc, out pGeo, out locError);
return pGeo as IPolyline;
}
其实如果在ArcGIS Engine中做过和线性参考相关的工作,那么这端代码是完全可以在ArcGIS Engine中使用的,所以说SOE的开发并不是想象中的困难,相反如果有了AO基础的话,的确是很简单。
注意:
在这里我将自己遇到的问题说一下,如果在ArcGIS 10或者之前的版本中使用过SOE,那么发现下面的代码是可以运行的,而且没有问题:
IMapServer mapServer = (IMapServer3)serverObjectHelper.ServerObject;
IMapServerObjects3 pMSO = mapServer as IMapServerObjects3;
IMap map = pMSO.get_Map(mapServer.DefaultMapName);
但是在10.1的时候,这句代码是不会成功的,错误的地方在IMapServerObjects3,这是因为10.1中发布的服务是使用MSD文档,而IMapServerObjects3是针对MXD文档的,因此在10.1中应避免,避免IMap,Ilayer等,那么如何访问要素类,栅格对象,表等对象呢?使用IMapServerDataAccess接口,该接口主要有两个方法,如下图:
第一个方法主要获取表,要素类,栅格数据,但是在地图文档中我们有的数据是和其他数据有关联的的比如join操作,那么通过第二个方法我们不但可以获取源表的数据,还可以获取目的表的数据。
相关文章推荐
- ARCGIS 10.1 for Server SOE介绍及开发实例(3)
- ARCGIS 10.1 for Server SOE介绍及开发实例(1)
- ARCGIS 10.1 for Server SOE介绍及开发实例(4)
- ARCGIS 10.1 for Server SOE介绍及开发实例(5)
- ArcGIS 10.1 for Server 扩展开发(SOE)
- ArcGIS 10.1 for Server 扩展开发(SOE)
- ArcGIS 10.1 for Server 扩展开发(SOE)
- ArcGIS for Server的SOE开发思路解析
- ArcGIS 10.1 for Server 新特性简要介绍(构建云GIS平台的基石)
- ArcGIS for Server的SOE开发思路解析
- 安装arcgis9.3 server for Java 开发环境(图文篇)
- [ ArcGIS for Server 10.1 系列 ] - 云计算 之 后台接口篇
- 为ArcGIS 10.1 for Server 准备的博文
- ArcGIS for Server 10.1智能支持云的架构(下)
- ArcGIS 10.1 for Server安装教程系列—— Linux下的单机安装
- ArcGIS 10.1 for Server 在windows下的安装
- ArcGIS 10.1 for Server 如何使用10或者之前的切片
- ArcGIS API for Silverlight开发入门(2):一个基础地图实例
- [ ArcGIS for Server 10.1 系列 ] - 分布式部署GIS Servers