ArcGIS Engine管理訪問ArcGIS Server

第一章  使用ArcGIS Engine 管理ArcGIS Server

1.1   原因

在10版本以及之前的版本中,有一些用戶通過ArcGIS Engine來管理ArcGIS Server,比如發佈服務,停止服務等,對服務的管理是通過DCOM方式的,而在10.1中ArcGIS 不支持DOCM方式的連接,。如果你在代碼中使用了Server庫中的GISServerConnection或者GISClient庫中的AGSServerConnection,在ArcGIS Server 10.1環境下,這些代碼必須移除,如下面的代碼:
1.png
  
如果強行執行,那麼會有下面的錯誤:
2.png 

1.2   解決

ArcGIS Server在10.1版本中提供了ADMIN API,只要我們通過http請求構造相應的參數就行,對於ArcGIS Server的連接,我們可以看下desktop是如何連接的:

3.png
4.png

從這兩個圖中就可以看出,在選擇連接Server的時候,選擇角色,選擇服務的類型(SDS和ArcGIS Server),在10版本以及之前的版本的時候跟這個有較大區別,連接ArcGIS 10.1 for Server的代碼如下(註釋已經寫出):

public  IServerObjectAdmin ConnectAGS(string host, string username, string password)
        {
            try
            {
                IPropertySet propertySet = new PropertySetClass();
                propertySet.SetProperty("url", host);
                propertySet.SetProperty("ConnectionMode", esriAGSConnectionMode.esriAGSConnectionModeAdmin);
                propertySet.SetProperty("ServerType", esriAGSServerType.esriAGSServerTypeDiscovery);
                propertySet.SetProperty("user", username);
                propertySet.SetProperty("password", password);
                propertySet.SetProperty("ALLOWINSECURETOKENURL", true); //設置爲false會彈出一個警告對話框

                IAGSServerConnectionName3 pConnectName = new AGSServerConnectionNameClass() as IAGSServerConnectionName3;//10.1新增接口
                pConnectName.ConnectionProperties = propertySet;

                IAGSServerConnectionAdmin pAGSAdmin = ((IName)pConnectName).Open() as IAGSServerConnectionAdmin;

                token = GenerateAGSToken_RESTAdmin(host, "arcgis", "arcgis");
               
                return pAGSAdmin.ServerObjectAdmin;
            }
            catch (Exception exc)
            {
                Console.WriteLine("連接失敗: {0}. Message: {1}", host, exc.Message);
                return null ;
            }
        }

ConnectAGS("http://192.168.110.136:6080/arcgis/admin", "arcgis", "arcgis");

當獲得了IAGSServerConnectionAdmin 這個接口我們進而可以獲取IServerObjectAdmin,IServerObjectAdmin接口,
在幫助中看到了IDiscoveryServerObjectAdmin接口,該接口的方法和屬性如下:
5.png

我欣喜若狂,因爲這些和ArcGIS Server的Admin幾乎是對應的,實現該接口的類不能被實例化,必須通過其他對象獲取。但是不幸的是我在dll中並沒有發現這個。

1.2.1   一個猜想

既然這個接口不能自己new,必須通過其他的實例化,那麼這個對象是誰?
6.png

我們很自然的想到應該在連接成功之後就返回這個對象,該對象實現的接口如下:
7.png
我們注意下IRESTServerObjectAdmin 接口,字面意思就是通過rest方式跟Server打交道,而該接口只被一個類實現,該類就DiscoveryServerObjectAdmin
8.png

如果連接成功返回的真是DiscoveryServerObjectAdmin對象,那麼我們QI到IRESTServerObjectAdmin上是沒有問題的,結果正如我猜想的一樣,有圖爲證:
9.png 
以上是我的個人猜想,但是不知道爲什麼dll中沒找到這個接口,還是ESRI故意將這個接口隱藏起來了。

1.3  AO操作

當連接上ArcGIS Server,我們獲取了IAGSServerConnectionAdmin,通過該對象我們獲取了IServerObjectAdmin,通過該對象可以對Server進行管理

1.3.1  更改實例數

   private void ChangInstance(IServerObjectAdmin pSAdmin, IServerObjectConfiguration pConf, int pMin, int pMax)
        {
            IEnumServerObjectConfiguration pEnServerConf = pSAdmin.GetConfigurations();

            IServerObjectConfiguration pSConf = pEnServerConf.Next();

            IServerObjectConfiguration pSOConfig = null;

            while (pSConf != null)
            {
                if (pSConf.Name == pConf.Name && pSConf.TypeName == pConf.TypeName)
                {
                    pSOConfig = pSConf;
                    break;
                }

                pSConf = pEnServerConf.Next();
            }

            if (pSConf != null)
            {
                pSConf.MinInstances = pMin;
                pSOConfig.MaxInstances = pMax;
                pSAdmin.UpdateConfiguration(pSOConfig);
            }

        }

1.3.2  停止服務

pServerAdmin.StopConfiguration("Flow", "MapServer");

1.3.3  刪除服務

   pServerAdmin.DeleteConfiguration("BusSimulation/DataPrep", "MapServer");//如果自己建立了目錄請按照這種方式寫,不然出錯

1.4  REST方式操作

ArcGIS 10.1 for Server可以通過http請求的方式訪問,server接到請求後,然後響應,響應的結果是json格式的,對json格式我們可以自己去解析,但是這個很麻煩,在10.1中增加了很多對json格式處理的接口IJSONReader2,IJSONWriter等很多,我在這裏偷懶直接使用了AO中自帶的接口,如果不用AO中的這些接口,自己藉助一些json的解析工具如:JSON.NET也是可以的。

1.4.1 獲取token

        public string GenerateAGSToken_RESTAdmin(string restAdmin, string username, string password)
        {
            try
            {
                if (restAdmin.EndsWith("\\"))
                {
                    restAdmin = restAdmin.Substring(0, restAdmin.Length - 1);
                }
                if (restAdmin.EndsWith("services"))
                {
                    restAdmin = restAdmin.Substring(0, restAdmin.Length - 9);
                }

                string loginUrl = restAdmin + "/generateToken";
                WebRequest request = WebRequest.Create(loginUrl);
                request.Method = "POST";
                string credential = "username=" + username + "&password=" + password + "&client=requestip&expiration=&f=json";
                byte[] content = Encoding.UTF8.GetBytes(credential);
                request.ContentLength = content.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();


                IJSONReader2 pJsonReader = new JSONReaderClass();

                IJSONObject pOb = pJsonReader.ParseJSONString(result) as IJSONObject;

                string token;
                if (pOb.TryGetValueAsString("token", out token))
                {

                }
            
                return token;
            }
            catch { return ""; }
        }
//""表示根目錄
        public bool DeleteService_RESTAdmin(string restAdmin, string username, string password, string serviceName,string pType,string pFolder )
        {
            try
            {

                //string token = GenerateAGSToken_RESTAdmin(restAdmin, username, password);
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;
                string serviceUrl = restAdmin + "/services" +pFolder+"/"+ serviceName + "." + pType + "/delete";
                WebRequest request = WebRequest.Create(serviceUrl);
                string postcontent = "f=pjson&token=" + token;
                Byte[] content = Encoding.UTF8.GetBytes(postcontent);
                request.ContentLength = content.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                request.Method = "POST";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();
                return result.Contains("success");
            }
            catch { return false; }
        }

1.4.2   停止服務


        public  bool StopService_RESTAdmin(string restAdmin, string username, string password, string serviceName, string pType, string pFolder)
        {
            try
            {
              //  string token = GenerateAGSToken_RESTAdmin(restAdmin, username, password);
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;
if (pFolder.Length > 0)
                {
                    pFolder = pFolder.StartsWith("/") ? pFolder : "/" + pFolder;
                }

                string serviceUrl = restAdmin + "/services" +pFolder+"/"+  serviceName + "." + pType + "/stop";
                WebRequest request = WebRequest.Create(serviceUrl);
                string postcontent = "f=pjson&token=" + token;
                Byte[] content = Encoding.UTF8.GetBytes(postcontent);
                request.ContentLength = content.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                request.Method = "POST";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();
                return result.Contains("success");
            }
            catch { return false; }
        }

1.4.3  啓動服務


        public  bool StartService_RESTAdmin(string restAdmin, string username, string password, string serviceName,string pServiceType,string pFolder)
        {
            try
            {
             //  string token = GenerateAGSToken_RESTAdmin(restAdmin, username,password);
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;
if (pFolder.Length > 0)
                {
                    pFolder = pFolder.StartsWith("/") ? pFolder : "/" + pFolder;
                }

                string serviceUrl = restAdmin + "/services" + pFolder + "/" + serviceName + "." + pServiceType + "/start";//服務名稱+"."+類型
                WebRequest request = WebRequest.Create(serviceUrl);
               string postcontent = "f=pjson&token=" + token;

        
                Byte[] content = Encoding.UTF8.GetBytes(postcontent);
                request.ContentLength = content.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                request.Method = "POST";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();
                return result.Contains("success");
            }
            catch { return false; }
        }

1.4.4   獲取服務的目錄,名稱和類型


        //目錄,服務名稱,類型
        Dictionary<string, Dictionary<string, string>>  pServiceType = new Dictionary<string, Dictionary<string, string>>();
        Dictionary<string, string> pDic = new Dictionary<string, string>();
        public Dictionary<string, Dictionary<string, string>>  ListServices_RESTAdmin(string restAdmin, string username, string password, string folder)
        {
            try
            {
               //使用WebRequest 發送請求
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;
                string serviceUrl = restAdmin + "/" + folder;
                WebRequest request = WebRequest.Create(serviceUrl);
               string postcontent = "f=json&token=" + token;

               // json格式
                Byte[] content = Encoding.UTF8.GetBytes(postcontent);
                request.ContentLength = content.Length;
                //
                request.ContentType ="application/x-www-form-urlencoded";
                request.Method = "POST";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();


                int index = result.IndexOf("services");

                Dictionary<string, string> pSer = new Dictionary<string, string>();


                IJSONReader2 pJsonReader = new JSONReaderClass();

                IJSONObject pOb = pJsonReader.ParseJSONString(result) as IJSONObject;


                //"folders":["BusSimulation","System","Utilities"]
                //根目錄
                   pServiceType.Add("/", new Dictionary<string, string>());

                   IJSONArray pFodArr;
              
                    if(pOb.TryGetValueAsArray("folders",out pFodArr))
                    {
                        for (int i = 0; i < pFodArr.Count; i++)
                        {
                            pServiceType.Add(pFodArr.get_Value(i).ToString(), new Dictionary<string, string>());
                          
                        }
                       
                    }
                

                if (pOb.MemberExists("services"))
                {
                   object pJs;
                   if (pOb.TryGetValue("services", out pJs))
                   {
                       if (pJs is IJSONArray)
                       {
                           IJSONArray pArray = pJs as IJSONArray;

                           for (int i = 0; i < pArray.Count; i++)
                           {
                               if (pArray.get_Value(i) is IJSONObject)
                               {
                                   IJSONObject pType = pArray.get_Value(i) as IJSONObject;

                                  // {"folderName":"/","serviceName":"GZCache","type":"MapServer","description":""}
                                   string folderName;
                                   //服務的目錄
                                   if(pType.TryGetValueAsString("folderName",out folderName))
                                   {
                                   }
                                    string serviceName;
                                    //服務的名稱
                                   if(pType.TryGetValueAsString("serviceName",out serviceName))
                                   {
                                   }
                                    string AGSType;
                                    //服務的類型
                                   if(pType.TryGetValueAsString("type",out AGSType))
                                   {
                                   }
                                   pServiceType[folderName].Add(serviceName, AGSType);
                               }

                           }


                       }
                   }
                }

            }
            catch { }

            return pServiceType;
        }

1.4.5  刪除服務

     public bool DeleteService_RESTAdmin(string restAdmin, string username, string password, string serviceName,string pType,string pFolder )
        {
            try
            {

                //string token = GenerateAGSToken_RESTAdmin(restAdmin, username, password);
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;

if (pFolder.Length > 0)
                {
                    pFolder = pFolder.StartsWith("/") ? pFolder : "/" + pFolder;
                }

                string serviceUrl = restAdmin + "/services" +pFolder+"/"+ serviceName + "." + pType + "/delete";
                WebRequest request = WebRequest.Create(serviceUrl);
                string postcontent = "f=pjson&token=" + token;
                Byte[] content = Encoding.UTF8.GetBytes(postcontent);
                request.ContentLength = content.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                request.Method = "POST";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();
                return result.Contains("success");
            }
            catch { return false; }
        }

1.4.6    服務是否停止

   public bool GetStatus_RESTAdmin(string restAdmin, string username, string password, string serviceName, string pServiceType, string pFolder)
        {
            try
            {
                //  string token = GenerateAGSToken_RESTAdmin(restAdmin, username,password);
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;
                string serviceUrl = restAdmin + "/services" + pFolder + "/" + serviceName + "." + pServiceType + "/status";//服務名稱+"."+類型
                WebRequest request = WebRequest.Create(serviceUrl);
                string postcontent = "f=pjson&token=" + token;
                Byte[] content = Encoding.UTF8.GetBytes(postcontent);
                request.ContentLength = content.Length;
                request.ContentType = "application/x-www-form-urlencoded";
                request.Method = "POST";
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(content, 0, content.Length);
                requestStream.Close();
                WebResponse response = request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                string result = reader.ReadToEnd();
                return result.Contains("STOPPED");
            }
            catch { return false; }
        }


1.5   小結

在1.3和1.4我們分別用了AO的方式和REST的方式管理了ArcGIS 10.1 for Server,關於兩種方法各有利弊,在這裏我略總結如下:
       11.jpg

第二章  使用ArcGIS Engine 訪問ArcGIS Server

2.1  以前是如何訪問的

上面提到了我們以前通過DCOM的方式也就是本地連接來管理ArcGIS Server,而管理ArcGIS Server是通過IAGSServerConnectionAdmin接口,以前我們通過IGISServerConnection接口的connect方法來獲取connect方法只有一個參數就是機器所在的位置,而該方法“隱性”的使用當前操作系統登陸用戶名和密碼去驗證,爲了保證連接的正確,當前的用戶名必須在agsadmin組或者agsuser組,而前者是用來管理Server的,後者是用來訪問Server的服務的,如果當前登陸的操作系統的賬戶不屬於這兩個組,那麼就會報錯,現在這種方式不存在了。
        private IServerObjectAdmin5 Admin()
        {
            ESRI.ArcGIS.Server.IGISServerConnection pServerConn = new ESRI.ArcGIS.Server.GISServerConnectionClass();
            pServerConn.Connect("esri-LiuYu");
            IServerObjectAdmin5 pServerAdim = pServerConn.ServerObjectAdmin as IServerObjectAdmin5;
            return pServerAdim;
        }
在管理ArcGIS 10.1 for Server的時候我們必須”顯性”的指定用戶名和密碼,所以該接口在10.1的時候肯定是不能用,正如我們開始提到的那樣,會報錯。

2.2   IAGSServerConnection接口還能用嗎?

IAGSServerConnection這個接口也是可以用來連接,該接口被AGSServerConnectionClass類實現,但是這個類是不可以自己實例化的,必須通過其他類創建,這個類實現的接口如下:

我們現在用user的身份連接,代碼如下:

   public  List<IAGSServerObjectName>  ConnectUserAGS(string host, string username, string password)
      {
          try
          {

              List<IAGSServerObjectName> pList = new List<IAGSServerObjectName>();
              IPropertySet propertySet = new PropertySetClass();
              propertySet.SetProperty("url", host);
              propertySet.SetProperty("ConnectionMode", esriAGSConnectionMode.esriAGSConnectionModeConsumer);
              propertySet.SetProperty("user", username);
              propertySet.SetProperty("password", password);
          

              //打開連接

             // IAGSServerConnectionFactory pFactory = new AGSServerConnectionFactory();
              //Type factoryType = Type.GetTypeFromProgID(
              //    "esriGISClient.AGSServerConnectionFactory");
              //IAGSServerConnectionFactory agsFactory = (IAGSServerConnectionFactory)
              //    Activator.CreateInstance(factoryType);


              IAGSServerConnectionName3 pConnectName = new AGSServerConnectionNameClass() as IAGSServerConnectionName3;//10.1新增接口
              pConnectName.ConnectionProperties = propertySet;

              IAGSServerConnection pConnection = ((IName)pConnectName).Open() as IAGSServerConnection;

              //IAGSServerConnection pConnection = pFactory.Open(propertySet, 0);
              IAGSEnumServerObjectName pServerObjectNames = pConnection.ServerObjectNames;
              pServerObjectNames.Reset();

              IAGSServerObjectName agsServerObjectName = pServerObjectNames.Next();
              while (agsServerObjectName != null)
              {
                  pList.Add(agsServerObjectName);
                  agsServerObjectName = pServerObjectNames.Next();
              }

              return pList;

          }

在這裏我取回List中的第一個,然後在MapControl中顯示,代碼如下:

    List<IAGSServerObjectName> pList = pServerMnt.ConnectUserAGS("http://192.168.110.136:6080/arcgis/rest/services", "", "");


          //  IRESTServerObjectAdmin pRest = pServerAdmin as IRESTServerObjectAdmin;


            ESRI.ArcGIS.Carto.IMapServerLayer pMapServerLayer = new ESRI.ArcGIS.Carto.MapServerLayerClass();

            IName pName = (IName)pList[0];
            IAGSServerObject pServerObject = (IAGSServerObject)pName.Open();
            IMapServer pMapServer = (IMapServer)pServerObject;
            pMapServerLayer.ServerConnect(pList[0], pMapServer.DefaultMapName);

            axMapControl1.AddLayer(pMapServerLayer as ILayer);

            axMapControl1.Refresh();

效果如下:
10.png

看到結果,這個問題已經有了答案了,對於以用戶的身份連接ArcGIS Server的話,我們只需要修改下IPropertySet屬性即可 。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章