开发 SOI
开发SOI
SOI 特性
[ComVisible(true)]
[Guid("b3494a31-9aff-405d-bc25-548c01550f2f")]
[ClassInterface(ClassInterfaceType.None)]
[ServerObjectInterceptor("MapServer",//"MapServer"|"ImageServer"
Description = "",
DisplayName = "SimpleSOI1",
Properties = "",
SupportsSharedInstances = false)]
public class SimpleSOI1 : IServerObjectExtension,
IRequestHandler2, IRequestHandler,
IWebRequestHandler,
IRESTRequestHandler
{
}
类型 | 必填 | 可空 | 说明 | |
---|---|---|---|---|
serverobject | string | 是 | 否 | "MapServer" 或 "ImageServer"。其中, "ImageServer"是从 10.8.1 开始受支持。 |
Description | string | 是 | 是 | 在 ArcGIS Server Manager 上的站点 > 扩展 选项卡上单击扩展的帮助按钮后,将显示这个值。 |
DisplayName | string | 是 | 否 | 是显示在 ArcGIS Server Manager 的服务 > 功能 选项卡下的 SOI 名称。 |
Properties | string | 是 | 是 | 交由服务器管理员来编辑的 SOI 属性。例如:若 Properties = "isEditable=false;configFile=",则服务器管理员可以在启用 SOI 时,为isEditable 和 configFile 配置相应的值。SOI 实现IObjectConstruct 接口的方法 void Construct(IPropertySet props) 可读取到由服务器管理员配置的值:string editableString = props.GetProperty("isEditable") as string; 。 |
SupportsSharedInstances | bool | 否 | 否 | 从 10.8 开始受支持。 |
拦截 REST、SOAP 和 OGC 服务请求
地图和影像服务(包括地图和影像服务扩展,例如要素服务)支持三种不同类型的请求:
-
REST API 请求
-
SOAP API 请求
-
OGC 请求
为了让 SOI 拦截这些请求,您需要实现以下接口:
- IRESTRequestHandler - 用于处理 REST API 请求
- IRequestHandler2 - 用于处理 SOAP API 请求,包括 ArcGIS for Desktop 客户端(例如 ArcMap)发出的请求
- IWebRequestHandler - 用于处理 OGC 请求
所有这些接口都可以在 Esri.ArcGIS.esriSystem 命名空间中找到。
即使特定的服务配置不支持 OGC 请求,您也需要处理上述所有接口。
根据您正在实施的业务逻辑,您可以采用两种通用方法。
- 如果您正在实现一个【执行安全功能的 SOI】,那么建议您首先实现上述所有接口并阻止所有请求。当您实现自定义代码时,您可以在逻辑上允许通过上述接口进行访问。如果您最初没有阻止传入请求并随后根据需要允许访问,则您会冒更大的风险无意中暴露安全漏洞。【译注:为实现安全功能,需先阻止所有请求,然后再根据需要允许对应访问的发生】
- 如果您没有实现安全功能,您可以通过将所有请求传递给【底层标准实现】来实现这三个接口,以实现正常功能,然后将其他业务逻辑添加到您希望增强的一个或多个操作中。
当一个服务配置了 SOI ,服务器框架会把【所有对这个服务的请求】都路由到 SOI。SOI 负责处理请求,将请求委托给实际的地图或影像服务对象(如果适用),然后在将响应返回给客户端之前,选择是否进一步处理响应。
实现 IRESTRequestHandler 接口
所有操作参数和响应都是 text/json 格式,并且可以轻松记录到磁盘。
该接口主要包含以下功能:
[C#]
public byte[] HandleRESTRequest(string capabilities, string resourceName, string
operationName, string operationInput, string outputFormat, string
requestProperties, ref string responseProperties)
{
responseProperties = null;
IRESTRequestHandler restRequestHandler = _restSOIHelper.FindRequestHandlerDelegate<IRESTRequestHandler>();
if (restRequestHandler == null)
return null;
return restRequestHandler.HandleRESTRequest(
Capabilities, resourceName, operationName, operationInput,
outputFormat, requestProperties, out responseProperties);
}
该函数根据资源和操作及其相应的请求属性对 REST API 进行建模。operationInput 参数通常包含一个表示输入的 JSON 对象。您可以使用所选平台中可用的 JSON 库轻松过滤此对象。为了获得服务的默认配置,【REST 服务目录】通过为所有参数传入空 JSON 对象来调用此操作。通过将此调用委托给底层服务,然后在 SOI 中操作输出,您可以影响服务目录和客户端呈现的资源(层)和操作(导出、查找、识别等)。
示例一,对 export 操作的请求进行预处理:
public byte[] HandleRESTRequest(string Capabilities, string resourceName, string operationName,
string operationInput, string outputFormat, string requestProperties, out string responseProperties)
{
responseProperties = null;
IRESTRequestHandler restRequestHandler = _restSOIHelper.FindRequestHandlerDelegate<IRESTRequestHandler>();
if (restRequestHandler == null)
return null;
if (operationName == "export")
{
//To use JavaScriptSerializer: Add Reference > Assemblies > Framework > System.Web.Extensions
JavaScriptSerializer sr = new JavaScriptSerializer { MaxJsonLength = int.MaxValue };
var operationInputJson = sr.DeserializeObject(operationInput) as IDictionary<string, object>;
operationInputJson["layers"] = "show:0"; //This statement shows only the first layer
string modifiedOpInput = sr.Serialize(operationInputJson);
return restRequestHandler.HandleRESTRequest(
Capabilities, resourceName, operationName, modifiedOpInput,
outputFormat, requestProperties, out responseProperties);
}
return restRequestHandler.HandleRESTRequest(
Capabilities, resourceName, operationName, operationInput,
outputFormat, requestProperties, out responseProperties);
}
示例二,对 query 操作的响应,修改 feature 的 attributes:
public byte[] HandleRESTRequest(string Capabilities, string resourceName, string operationName,
string operationInput, string outputFormat, string requestProperties, out string responseProperties)
{
responseProperties = null;
IRESTRequestHandler restRequestHandler = _restSOIHelper.FindRequestHandlerDelegate<IRESTRequestHandler>();
if (restRequestHandler == null)
return null;
//map service query operation example:
//operationName = "query", resourceName = "layer/0", outputFormat = "json"
if (operationName == "query" && resourceName.Length>0 && outputFormat == "json")
{
byte[] originalResponse = restRequestHandler.HandleRESTRequest(Capabilities, resourceName, operationName,
operationInput, outputFormat, requestProperties, out responseProperties);
String originalResult = System.Text.Encoding.UTF8.GetString(originalResponse);
//To use JavaScriptSerializer: Add Reference > Assemblies > Framework > System.Web.Extensions
JavaScriptSerializer sr = new JavaScriptSerializer { MaxJsonLength = int.MaxValue };
var resultJSON = sr.DeserializeObject(originalResult) as IDictionary<string, object>;
if (resultJSON != null && resultJSON.ContainsKey("features"))
{
var resultfeatures = resultJSON["features"] as object[];
if (resultfeatures != null)
{
foreach (var feature in resultfeatures)
{
var featureDictionary = feature as IDictionary<string, object>;
var featureAttr = featureDictionary["attributes"] as IDictionary<string, object>;
if (featureAttr!=null)
{
if (featureAttr.ContainsKey("TYPE") && featureAttr.ContainsKey("ID"))
if (featureAttr["TYPE"]!=null && featureAttr["TYPE"].ToString() == "non-forest")
featureAttr["ID"] = "N/A"; //Override the ID to be "N/A" in the query response for records with a "non-forest" Type
}
}
string modifiedResult = sr.Serialize(resultJSON);
return System.Text.Encoding.UTF8.GetBytes(modifiedResult);
}
}
}
return restRequestHandler.HandleRESTRequest(
Capabilities, resourceName, operationName, operationInput,
outputFormat, requestProperties, out responseProperties);
}
另一个必须处理的功能是:
[C#]
public string getSchema()
此函数通知 【REST 服务目录】如何表示服务配置。通常,您的 SOI 实现应该将此调用委托给底层地图或影像服务对象,然后根据需要选择性地操作输出。
实现 IRequestHandler2 接口
此接口的实现涉及更多,因为它处理二进制请求(来自 ArcGIS for Desktop 和其他基于 ArcObjects 的应用程序)和 SOAP 请求(来自自定义 SOAP 客户端)。
无论哪种情况,您都需要使用 ArcObjects API 来解包传入的请求;然后根据需要,选择是否修改请求参数;然后重新打包请求并发送到底层【地图或影像服务对象】。
要对响应进行“返回前处理”,您需要使用 ArcObjects API 来解包响应,然后再将其发送到客户端。SDK 中包含了一些实用程序类,来帮助您打包和解包响应对象。
此接口包含您需要实现的两个方法:
[C#]
public byte[] HandleBinaryRequest2(string capabilities, byte[] request)
当服务器接收到服务的二进制请求(来自 ArcGIS for Desktop)时,将调用上述函数。request 参数包含的二进制请求,必须使用 ArcObjects API 解包。
[C#]
public string HandleStringRequest(string capabilities, string request)
当服务器接收到 SOAP (XML) 请求时调用此函数。SOAP 客户端通常会发出这些请求。request 参数包含的 XML 请求,必须使用 ArcObjects API 解包。
实现 IWebRequestHandler 接口
IWebRequestHandler 接口,可以实现拦截 KML 请求和 OGC 服务请求(WMS 和 WFS)的功能。接口中的方法(HandleStringWebRequest)代表了一个典型的 OGC 请求:一个带有查询参数的 HTTP 请求。您需要实现以下功能:
[C#]
public byte[] HandleStringWebRequest(esriHttpMethod httpMethod, string requestURL,
string queryString, string capabilities, string requestData, ref string
responseContentType, ref int respDataType)
requestData 参数通常是 text/xml 格式,并作为请求的输入。但是,参数通常通过 queryString 参数发送。respDataType 参数通知您的代码必须如何解释【返回的值 byte []】。如果 respDataType 指示其为文件,则您的代码必须流式传输文件路径的内容而返回 byte [] 。respDataType 通知 Web 处理程序【在响应 HTTP 请求时】要设置的内容类型。
用于处理 JSON 和【基于 ArcObjects 的结果】的实用程序类
名为 SOISupport 的实用程序类,可作为“关于层访问”的示例的一部分。该实用程序类,包含了用于与父服务交互的、可委托传入请求的方法,包含了用于在 ArcObjects 响应对象之间进行转换的方法等等。有关如何使用这些方法的示例,尤其是在处理 SOAP 和二进制请求时,请参阅 层访问示例。 ESRI.ArcGIS.SOESupport 程序集中的其他类,提供了处理 JSON 数据和对象的功能。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?