开发 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 拦截这些请求,您需要实现以下接口:

所有这些接口都可以在 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 数据和对象的功能。

posted @   误会馋  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示