/// <summary>
        /// create image service configuration
        /// </summary>
        private static void CreateISConfig()
        {
            try
            {
                if (!ConnectAGS(restAdmin)) return;

                //get source type
                esriImageServiceSourceType sourceType = GetSourceType(sourcePath);

                //connect to ArcGIS Server and create configuration
                IServerObjectConfiguration5 soConfig = (IServerObjectConfiguration5)soAdmin.CreateConfiguration();

                //set general service parameters
                soConfig.Name = serviceName;
                soConfig.TypeName = "ImageServer";
                soConfig.TargetCluster = "default";

                soConfig.StartupType = esriStartupType.esriSTAutomatic;
                soConfig.IsPooled = true;
                soConfig.IsolationLevel = esriServerIsolationLevel.esriServerIsolationHigh;
                soConfig.MinInstances = 1;
                soConfig.MaxInstances = 2;

                //customize recycle properties
                IPropertySet propertySet_Recycle = soConfig.RecycleProperties;
                propertySet_Recycle.SetProperty("Interval", "24");


                //path to the data
                IPropertySet propertySet = soConfig.Properties;
                IWorkspace workspace = ((IDataset)rasterDataset).Workspace;
                if (workspace.WorkspaceFactory.WorkspaceType == esriWorkspaceType.esriRemoteDatabaseWorkspace)
                {
                    IWorkspaceName2 wsName2 = ((IDataset)workspace).FullName as IWorkspaceName2;
                    string connString = wsName2.ConnectionString;
                    propertySet.SetProperty("ConnectionString", connString);
                    propertySet.SetProperty("Raster", ((IDataset)rasterDataset).Name);
                }
                else
                    propertySet.SetProperty("Path", sourcePath);
                propertySet.SetProperty("EsriImageServiceSourceType", sourceType.ToString());

                //MIME+URL (virtual directory)
                propertySet.SetProperty("SupportedImageReturnTypes", "MIME+URL");
                IEnumServerDirectory dirs = soAdmin.GetServerDirectories();
                dirs.Reset();
                IServerDirectory serverDir = dirs.Next();
                while (serverDir != null)
                {
                    if (((IServerDirectory2)serverDir).Type == esriServerDirectoryType.esriSDTypeOutput)
                    {
                        propertySet.SetProperty("OutputDir", serverDir.Path);
                        propertySet.SetProperty("VirtualOutputDir", serverDir.URL);
                        break;
                    }
                    serverDir = dirs.Next();
                }

                //copy right
                propertySet.SetProperty("CopyRight", "");

                //properties for a mosaic dataset;
                if (sourceType == esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset)
                {
                    IFunctionRasterDataset functionRasterDataset = (IFunctionRasterDataset)rasterDataset;
                    IPropertySet propDefaults = functionRasterDataset.Properties;

                    object names, values;
                    propDefaults.GetAllProperties(out names, out values);
                    List<string> propNames = new List<string>();
                    propNames.AddRange((string[])names);
                    if (propNames.Contains("MaxImageHeight"))
                        propertySet.SetProperty("MaxImageHeight", propDefaults.GetProperty("MaxImageHeight"));//4100
                    if (propNames.Contains("MaxImageWidth"))
                        propertySet.SetProperty("MaxImageWidth", propDefaults.GetProperty("MaxImageWidth"));//15000
                    if (propNames.Contains("AllowedCompressions"))
                        propertySet.SetProperty("AllowedCompressions", propDefaults.GetProperty("AllowedCompressions"));//"None,JPEG,LZ77,LERC"
                    if (propNames.Contains("DefaultResamplingMethod"))
                        propertySet.SetProperty("DefaultResamplingMethod", propDefaults.GetProperty("DefaultResamplingMethod"));//0
                    if (propNames.Contains("DefaultCompressionQuality"))
                        propertySet.SetProperty("DefaultCompressionQuality", propDefaults.GetProperty("DefaultCompressionQuality"));//75
                    if (propNames.Contains("MaxRecordCount"))
                        propertySet.SetProperty("MaxRecordCount", propDefaults.GetProperty("MaxRecordCount"));//500
                    if (propNames.Contains("MaxMosaicImageCount"))
                        propertySet.SetProperty("MaxMosaicImageCount", propDefaults.GetProperty("MaxMosaicImageCount"));//20
                    if (propNames.Contains("MaxDownloadSizeLimit"))
                        propertySet.SetProperty("MaxDownloadSizeLimit", propDefaults.GetProperty("MaxDownloadSizeLimit"));//20
                    if (propNames.Contains("MaxDownloadImageCount"))
                        propertySet.SetProperty("MaxDownloadImageCount", propDefaults.GetProperty("MaxDownloadImageCount"));//20
                    if (propNames.Contains("AllowedFields"))
                        propertySet.SetProperty("AllowedFields", propDefaults.GetProperty("AllowedFields"));//"Name,MinPS,MaxPS,LowPS,HighPS,CenterX,CenterY"
                    if (propNames.Contains("AllowedMosaicMethods"))
                        propertySet.SetProperty("AllowedMosaicMethods", propDefaults.GetProperty("AllowedMosaicMethods"));//"Center,NorthWest,LockRaster,ByAttribute,Nadir,Viewpoint,Seamline"
                    if (propNames.Contains("AllowedItemMetadata"))
                        propertySet.SetProperty("AllowedItemMetadata", propDefaults.GetProperty("AllowedItemMetadata"));//"Full"
                    if (propNames.Contains("AllowedMensurationCapabilities"))
                        propertySet.SetProperty("AllowedMensurationCapabilities", propDefaults.GetProperty("AllowedMensurationCapabilities"));//"Full"
                    if (propNames.Contains("DefaultCompressionTolerance"))
                        propertySet.SetProperty("DefaultCompressionTolerance", propDefaults.GetProperty("DefaultCompressionTolerance"));//"0.01" LERC compression
                    //propertySet.SetProperty("RasterFunctions", @"\\server\dir\rft1.rft.xml,\\server\dir\rft2.rft.xml");//"put raster function templates here, the first one is applied to exportimage request by default"
                    //propertySet.SetProperty("RasterTypes", @"Raster Dataset,\\server\dir\art1.art.xml,\\server\dir\art2.art");//"put raster types here"
                    //propertySet.SetProperty("DynamicImageWorkspace", @"\\server\dynamicImageDir"); //put the workspace that holds uploaded imagery here
                    //propertySet.SetProperty("supportsOwnershipBasedAccessControl", true); //ownership based access control
                    //propertySet.SetProperty("AllowOthersToUpdate", true); //allow others to update a catalog item
                    //propertySet.SetProperty("AllowOthersToDelete", true); //allow others to delete a catalog item
                    //propertySet.SetProperty("DownloadDir", ""); //put the download directory here
                    //propertySet.SetProperty("VirutalDownloadDir", ""); //put the virtual download directory here
                }
                else
                {
                    propertySet.SetProperty("MaxImageHeight", 4100);
                    propertySet.SetProperty("MaxImageWidth", 15000);
                    propertySet.SetProperty("AllowedCompressions", "None,JPEG,LZ77");
                    propertySet.SetProperty("DefaultResamplingMethod", 0);
                    propertySet.SetProperty("DefaultCompressionQuality", 75);//for jpg compression
                    propertySet.SetProperty("DefaultCompressionTolerance", 0.01);//for LERC compression                 
                    //    rasterDataset = OpenRasterDataset(sourcePath);
                    IMensuration measure = new MensurationClass();
                    measure.Raster = ((IRasterDataset2)rasterDataset).CreateFullRaster();
                    string mensurationCaps = "";
                    if (measure.CanMeasure)
                        mensurationCaps = "Basic";
                    if (measure.CanMeasureHeightBaseToTop)
                        mensurationCaps += ",Base-Top Height";
                    if (measure.CanMeasureHeightBaseToTopShadow)
                        mensurationCaps += ",Base-Top Shadow Height";
                    if (measure.CanMeasureHeightTopToTopShadow)
                        mensurationCaps += ",Top-Top Shadow Height";
                    propertySet.SetProperty("AllowedMensurationCapabilities", mensurationCaps); //set mensuration here
                }

                //not cached
                propertySet.SetProperty("IsCached", false);
                propertySet.SetProperty("IgnoreCache", true);
                propertySet.SetProperty("UseLocalCacheDir", false);
                propertySet.SetProperty("ClientCachingAllowed", false);

                //propertySet.SetProperty("DEM", ""); //put the elevation raster dataset or service for 3D mensuration, may need to add 3D to AllowedMensurationCapabilities

                //convert colormap to RGB or not
                propertySet.SetProperty("ColormapToRGB", false);

                //whether to return jpgs for all jpgpng request or not
                propertySet.SetProperty("ReturnJPGPNGAsJPG", false);

                //allow server to process client defined function
                propertySet.SetProperty("AllowFunction", true); //allow raster function


                //capabilities
                if (sourceType == esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset)
                    soConfig.Info.SetProperty("Capabilities", "Image,Catalog,Metadata,Mensuration");
                //Full set: Image,Catalog,Metadata,Download,Pixels,Edit,Mensuration
                else
                    soConfig.Info.SetProperty("Capabilities", "Image,Metadata,Mensuration");

                //enable wcs, assume data has spatial reference
                soConfig.set_ExtensionEnabled("WCSServer", true);
                IPropertySet wcsInfo = new PropertySetClass();
                wcsInfo.SetProperty("WebEnabled", "true");
                soConfig.set_ExtensionInfo("WCSServer", wcsInfo);
                IPropertySet propertySetWCS = new PropertySetClass();
                propertySetWCS.SetProperty("CustomGetCapabilities", false);
                propertySetWCS.SetProperty("PathToCustomGetCapabilitiesFiles", "");
                soConfig.set_ExtensionProperties("WCSServer", propertySetWCS);

                //enable wms
                soConfig.set_ExtensionEnabled("WMSServer", true);
                IPropertySet wmsInfo = new PropertySetClass();
                wmsInfo.SetProperty("WebEnabled", "true");
                soConfig.set_ExtensionInfo("WMSServer", wmsInfo);
                IPropertySet propertySetWMS = new PropertySetClass();
                propertySetWMS.SetProperty("name", "WMS"); //set other properties here
                soConfig.set_ExtensionProperties("WMSServer", propertySetWMS);


                //add configuration and start
                soAdmin.AddConfiguration(soConfig);
                soAdmin.StartConfiguration(serviceName, "ImageServer");

                if (soAdmin.GetConfigurationStatus(serviceName, "ImageServer").Status == esriConfigurationStatus.esriCSStarted)
                    Console.WriteLine("{0} on {1} has been configured and started.", serviceName, restAdmin);
                else
                    Console.WriteLine("{0} on {1} was configured but can not be started, please investigate.", serviceName, restAdmin);

                if (rasterDataset != null)
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(rasterDataset);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error: {0}", exc.Message);
            }
        }
        /// <summary>
        /// create image service
        /// </summary>
        /// <param name="restAdmin">host machine name (windows or linux)</param>
        /// <param name="sourcePath">data source path, must be windows path (linux path is constructed automaticlly by windows path)</param>
        /// <param name="serviceName">configuration name</param>
        /// <param name="createImageServiceParams">Cration parameters, e.g. raster functions, colormaptorgb, raster types, dem, dynamicimageworkspace, customized propertyset etc</param>
        /// <returns>true if created successfully</returns>
        public static bool CreateISConfig_RESTAdmin()
        {
            //string restAdmin, string username, string password, string sourcePath, string serviceName
            try
            {
                esriImageServiceSourceType sourceType = GetSourceType(sourcePath);

                string serviceType = "ImageServer";
                //DeleteService_RESTAdmin();
                restAdmin = restAdmin.EndsWith("/") ? restAdmin.Substring(0, restAdmin.Length - 1) : restAdmin;
                string serviceFolder = "";
                if (serviceName.Contains("/"))
                {
                    serviceFolder = serviceName.Substring(0, serviceName.IndexOf("/"));
                    CreateServerFolder_RESTAdmin(serviceFolder, "");
                    serviceName = serviceName.Substring(serviceFolder.Length + 1, serviceName.Length - serviceFolder.Length - 1);
                }
                string createServiceUrl = "";
                if (serviceFolder == "")
                    createServiceUrl = restAdmin + "/services/createService";
                else
                    createServiceUrl = restAdmin + "/services/" + serviceFolder + "/createService";
                //createServiceUrl = "http://*****:*****@"D:\UploadDir"));                    
                }
                //if (cacheDir != "")
                //{
                //    sBuilder.AppendFormat("{0}: {1},", QuoteString("cacheDir"), QuoteString(cacheDir));
                //    sBuilder.AppendFormat("{0}: {1},", QuoteString("virtualCacheDir"), QuoteString(virtualCacheDir));//http://istest2:6080/arcgis/server/arcgisoutput"));                    
                //}
                sBuilder.AppendFormat("{0}: {1},", QuoteString("copyright"), QuoteString(""));

                //properties for a mosaic Dataset;
                if (sourceType == esriImageServiceSourceType.esriImageServiceSourceTypeMosaicDataset)
                {
                    IFunctionRasterDataset functionRasterDataset = (IFunctionRasterDataset)rasterDataset;
                    IPropertySet propDefaults = functionRasterDataset.Properties;
                    object names, values;
                    propDefaults.GetAllProperties(out names, out values);
                    List<string> propNames = new List<string>();
                    propNames.AddRange((string[])names);
                    if (propNames.Contains("AllowedCompressions"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("allowedCompressions"), QuoteString(propDefaults.GetProperty("AllowedCompressions").ToString()));//string
                    if (propNames.Contains("MaxImageHeight"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("maxImageHeight"), QuoteString(propDefaults.GetProperty("MaxImageHeight").ToString()));//should be int     
                    if (propNames.Contains("MaxImageWidth"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("maxImageWidth"), QuoteString(propDefaults.GetProperty("MaxImageWidth").ToString()));//should be int
                    if (propNames.Contains("DefaultResamplingMethod"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("defaultResamplingMethod"), QuoteString(propDefaults.GetProperty("DefaultResamplingMethod").ToString()));//should be int
                    if (propNames.Contains("DefaultCompressionQuality"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("defaultCompressionQuality"), QuoteString(propDefaults.GetProperty("DefaultCompressionQuality").ToString()));//should be int
                    if (propNames.Contains("MaxRecordCount"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("maxRecordCount"), QuoteString(propDefaults.GetProperty("MaxRecordCount").ToString()));//should be int
                    if (propNames.Contains("MaxMosaicImageCount"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("maxMosaicImageCount"), QuoteString(propDefaults.GetProperty("MaxMosaicImageCount").ToString()));//should be int
                    if (propNames.Contains("MaxDownloadImageCount"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("maxDownloadImageCount"), QuoteString(propDefaults.GetProperty("MaxDownloadImageCount").ToString()));//should be int
                    if (propNames.Contains("MaxDownloadSizeLimit"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("MaxDownloadSizeLimit"), QuoteString(propDefaults.GetProperty("MaxDownloadSizeLimit").ToString()));//should be int
                    if (propNames.Contains("AllowedFields"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("allowedFields"), QuoteString(propDefaults.GetProperty("AllowedFields").ToString()));//string
                    if (propNames.Contains("AllowedMosaicMethods"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("allowedMosaicMethods"), QuoteString(propDefaults.GetProperty("AllowedMosaicMethods").ToString()));//string
                    if (propNames.Contains("AllowedItemMetadata"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("allowedItemMetadata"), QuoteString(propDefaults.GetProperty("AllowedItemMetadata").ToString()));//string
                    if (propNames.Contains("AllowedMensurationCapabilities"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("AllowedMensurationCapabilities"), QuoteString(propDefaults.GetProperty("AllowedMensurationCapabilities").ToString()));//string
                    if (propNames.Contains("DefaultCompressionTolerance"))
                        sBuilder.AppendFormat("{0}: {1},", QuoteString("defaultCompressionTolerance"), QuoteString(propDefaults.GetProperty("DefaultCompressionTolerance").ToString()));//string                    
                    //sBuilder.AppendFormat("{0}: {1},", QuoteString("downloadDir"), QuoteString(@"c:\temp"));//string
                    //sBuilder.AppendFormat("{0}: {1},", QuoteString("virutalDownloadDir"), QuoteString(@"http://localhost/temp");//string
                }
                else if (sourceType != esriImageServiceSourceType.esriImageServiceSourceTypeCatalog) //not iscdef
                {
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("allowedCompressions"), QuoteString("None,JPEG,LZ77"));
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("maxImageHeight"), QuoteString("4100"));//should be int     
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("maxImageWidth"), QuoteString("15000"));//should be int
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("defaultResamplingMethod"), QuoteString("0"));//should be int
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("defaultCompressionQuality"), QuoteString("75"));//should be int
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("defaultCompressionTolerance"), QuoteString("0.01"));//should be int
                    IMensuration measure = new MensurationClass();
                    measure.Raster = ((IRasterDataset2)rasterDataset).CreateFullRaster();
                    string mensurationCaps = "";
                    if (measure.CanMeasure)
                        mensurationCaps = "Basic";
                    if (measure.CanMeasureHeightBaseToTop)
                        mensurationCaps += ",Base-Top Height";
                    if (measure.CanMeasureHeightBaseToTopShadow)
                        mensurationCaps += ",Base-Top Shadow Height";
                    if (measure.CanMeasureHeightTopToTopShadow)
                        mensurationCaps += ",Top-Top Shadow Height";
                    sBuilder.AppendFormat("{0}: {1},", QuoteString("AllowedMensurationCapabilities"), QuoteString(mensurationCaps));//string
                }

                //sBuilder.AppendFormat("{0}: {1},", QuoteString("dEM"), QuoteString(@"c:\elevation\elevation.tif"));                
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("supportsOwnershipBasedAccessControl"), QuoteString("true"));
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("allowOthersToUpdate"), QuoteString("true"));               
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("allowOthersToDelete"), QuoteString("true"));
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("cacheOnDemand"), QuoteString("false"));
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("isCached"), QuoteString("false"));
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("ignoreCache"), QuoteString("true"));
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("useLocalCacheDir"), QuoteString("false"));
                //sBuilder.AppendFormat("{0}: {1},", QuoteString("clientCachingAllowed"), QuoteString("false"));


                sBuilder.AppendFormat("{0}: {1},", QuoteString("colormapToRGB"), QuoteString("false"));
                sBuilder.AppendFormat("{0}: {1},", QuoteString("returnJPGPNGAsJPG"), QuoteString("false"));
                sBuilder.AppendFormat("{0}: {1},", QuoteString("allowFunction"), QuoteString("true"));
                string rasterFunctions = "";
                sBuilder.AppendFormat("{0}: {1},", QuoteString("rasterFunctions"), QuoteString(rasterFunctions).Replace("\\", "\\\\"));
                string rasterTypes = "";
                sBuilder.AppendFormat("{0}: {1}", QuoteString("rasterTypes"), QuoteString(rasterTypes).Replace("\\", "\\\\"));

                sBuilder.Append("},");
                bool enableWCS = true;
                bool enableWMS = true;
                sBuilder.AppendFormat("{0}: {1}", QuoteString("extensions"), "[{\"typeName\":\"WCSServer\",\"enabled\":\"" + enableWCS + "\",\"capabilities\":null,\"properties\":{}},{\"typeName\":\"WMSServer\",\"enabled\":\"" + enableWMS + "\",\"capabilities\":null,\"properties\":{\"title\":\"WMS\",\"name\":\"WMS\",\"inheritLayerNames\":\"false\"}}");
                sBuilder.Append("],");
                sBuilder.AppendFormat("{0}: {1}", QuoteString("datasets"), "[]");
                sBuilder.Append("}");
                string postcontent = HttpUtility.UrlEncode(sBuilder.ToString());
                string token = GenerateAGSToken_RESTAdmin();
                postcontent = "service=" + postcontent + "&startAfterCreate=on&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();
                Console.WriteLine("create service:" + serviceName + " result:" + result);
                //wait for 5 seconds to reduce latency issue
                //System.Threading.Thread.Sleep(5000);
                return result.Contains("success");
            }
            catch (Exception exc) { Console.WriteLine(exc.Message); return false; }
        }