(以下针对于windows操作系统.net开发环境)

 

        ArcGIS Server是ESRI公司最新推出的服务器端品,主要可以实现两大功能:

        1、强大的Web GIS系统的开发;

     2、分布式GIS系统的开发;

  ArcGIS Server其内核与ArcGIS Desktop和ArcGIS Engine一样,都是ArcObjects库。其所谓的Web GIS,其实无非就是用Web技术来封装ArcObjects而已;而分布式的开发则是通过DCOM来实现的。

 

  小弟前几个月搞了一下ArcIMS,发觉开发起来确实痛苦啊,整天就是折腾javascript+arcxml,郁闷死了,听闻有ArcGIS Server这种好东西,稍稍了解一下,便向老板建议转向ArcGIS Server,老板居然同意了。于是便开发学习了。网上四下里找了一下,发现可用的资源非常少,只好自己琢磨。从零开始真不容易啊,这不,刚上手就碰到了两个问题,好在都已经解决,现在写下来,希望对和我一样的新手有所帮助。

 

  ArcGIS Server的安装非常简单,先安装ArcGIS Server,然后安装DotNet ADF,最后用ArcCatelog添加一个Server,然后再添加一个ServerObject,这样就可以进行开发了。这里的ServerObject与ArcIMS中的Service很像,其实应该是一个概念上的东西吧。添加一个ServerObject需要一个mxd或pmf文件,用来保存和管理需要发布的数据。

 

  好了,现在可以开始开发了。

  打开Visual Studio 2003,打开新建项目对话框,发现ESRI公司已经为我们准备好了一些ArcGIS Server Projects的模板,包括Map Viewer Web Application,Page Layout Web Applicaiton等等,我们就建一个Map Viewer Web Application吧,选中它,输入项目名称,然后点击“确定”按钮,我们发现一个已经包含了基本数据浏览和查询功能的Web GIS程序已经建好了。

  好,打开Default.aspx文件,发现网页包含一个Map组件,一个Toolbar组件,一个TOC组件,一个OverviewMap组件等等。看来与C/S开发模式下很像嘛,爽啊。其中Map组件和OverviewMap组件有两个必填属性:Host和ServerObject,就分别对应着我们在ArcCatelog中添加的的Server和ServerObject,输入它。然后设置TOC组件和Toolbar组件的Buddy属性,OK,大功告成!

 

  运行!咦,发生错误,定睛一看,原来是访问拒绝,这是怎么回事呢?记得以前看到一篇文章,说在Asp.net中使用COM组件,经常由于权限原因,产生访问拒绝,而ArcGIS Server本身就是对ArcObjects这些COM组件的再封装,看来就是这么回事了。找出这篇文章来,原来要在Web.config中加入一行就可以了:

       

<identity impersonate="true" userName="Administrator" password="123456"/>

  再运行,哇塞,酷毙了,一个漂亮的WebGIS展现在眼前。可以浏览,查询,图层管理,鹰眼导航,还有指北针...

   (后来发现页面上还一个组件叫impersonation没用上,看了一下它的属性,只有一个identity,点击它,你会发现...呵呵,原来这个组件就是用来干这个事的,晕,又浪费了我两个小时的宝贵时间...)

 

  一行代码都不用写,爽。可是又很失落,心里没有底,这个Web GIS究竟是怎样实现的呢?

 

  待续


 

  我们知道,.net adf提供的map组件、toc组件等都是标准的asp.net组件。这些组件在运行时,会生成相应的html代码,将自己展现出来。一般还会通过ViewState来保存状态,并生成_doPostBack(javascript)函数,在必要的时候,通过javascript来调用该函数,将客户端数据返回来服务器端,从而激发服务器的响应。总之,我们通过分析生成的html页面,应该可以大致窥见asp.net组件是怎么运行的。

  好,我们现在按F5运行首页,然后在浏览器中查看网页的源代码,赶快看下一吧:

  

  1、首先会看到ID,MapIdClick,start等javascript函数,这些函数是模板为我们生成的,在default.aspx文件中定义的。ID函数中有两行:

var iddiv = document.getElementById("MapDiv_Map1");
 if (iddiv!=null) iddiv.onmousedown = MapIdClick;

 

  可以看到,这几个函数的作用是对地图的Identify(点击查询)作出处理。

  为什么要放在这里呢,为什么单单只有点击查询的javascript要在这里定义呢,其它如放大、缩小、平移为什么不在这里处理?这是因为Toolbar组件对放大、缩小、平移等提供了默认的处理方式,而identify没有,这样可以更方便进行扩展。在后面的代码中有一行<esri:Tool ToolTip="Identify" DefaultImage="Images/identify.gif" ClientToolAction="ID()" Name="Identify"...>,可以看到,这个调用是模板为我们生成的(并且这个调用是可以修改的)。待会我们在进一步分析中可以看到这一点。

 

  2、再向下,是几个隐藏域,其中包含__VIEWSTATE隐藏域,还有__doPostBack函数,这些是asp.net组件生成的,作用是向服务器提交数据,从而与服务器进行交互。

 

  3、往下我们看到了一些引入js脚本文件的代码:

 

<script language="Javascript" src="/aspnet_client/esri_arcgis_server_webcontrols/9_1/JavaScript/common.js"></script>
  <script language="Javascript" src="/aspnet_client/esri_arcgis_server_webcontrols/9_1/JavaScript/map_functions.js"></script>
  <script language="Javascript" src="/aspnet_client/esri_arcgis_server_webcontrols/9_1/JavaScript/overview_functions.js"></script>
  <script language="Javascript" src="/aspnet_client/esri_arcgis_server_webcontrols/9_1/JavaScript/toolbar_functions.js"></script>

  可以看到,共引入了四个js脚本文件,这些文件的地址也比较奇怪,不是与当前网站在同一个虚拟目录下,而是在http://localhost//aspnet_client/esri_arcgis_server_webcontrols/9_1/JavaScript目录下。在c:/inetpub/webroot/aspnet_client/esri_arcgis_server_webcontrols/9_1/JavaScript/文件夹下可以找到这些文件。原来,为了重用的方便,在安装Arcgis Server时,安装程序就已经建立了一个虚拟目录,用于提供这些共享的资源。在这个文件夹上一级目录中,还可以看到images和treeimages两个子目录,以及treeview.htc文件。

  知道了这些javascript文件的藏身之所,各位可以把这些javascript文件逐个看一遍,可以发现其作用主要是与浏览器进行交互。

 

 4、再往下,是TOC组件的Html代码,代码片断如下:

 

<tvns:treenode Expanded="False" DefaultStyle="color:silver;" ImageUrl="/aspnet_client/esri_arcgis_server_webcontrols/9_1/images/outscale.gif" CheckBox="False">
   道路注记<tvns:treenode Expanded="True" ImageUrl="ESRI.Web.Controls.MIMEImage.aspx?ImgID=Default.aspx_Toc1_0_1_0_0&NoCache=true"></tvns:treenode>

  这一段代码有一个特别之处就是ImageUrl="ESRI.Web.Controls.MIMEImage.aspx...",这个ESRI.Web.Controls.MIMEImage.aspx是什么东东,是一个网页吗?在机器里找一下,发现根本就不存在这个网页,那它又是何方神圣,竟然可以作为一个图片的地址?我们先往下看看。

 

 5、

<div id='OverviewMap1backdrop' style = 'position: absolute; left: 16px; top: 400px; width:204px; height:124px;  
 
Z-INDEX:104; border-color:LightSteelBlue; border-width:3px; border-style:Solid; overflow:hidden;'>
<table cellspacing=0 cellpadding=0 style = 'width:198px; height:118px; overflow:hidden;'><tr><td id=OVCell_OverviewMap1></td></tr></table>
</div>

  是鹰眼导航图的代码。怎么只有一个空的Div层和一个空的表格呢?唉,比较简单,我懒得分析了,同志们自己去找吧~

 

 6、再往下是Toolbar组件的代码,没什么特别的:

<td nowrap width="29" height ="32" align='Center'
  id="Toolbar1ZoomIn"
  onMouseDown="ToolbarMouseDown( 'Toolbar1', 'ZoomIn', 'Tool', event);"
  onMouseOver="ToolbarMouseOver('Toolbar1', 'ZoomIn');"
  onMouseOut="ToolbarMouseOut( 'Toolbar1', 'ZoomIn');"
  style="background-color:LightSteelBlue;font-family:Arial;font-size:Smaller;font-weight:bold;"
  ><img id="Toolbar1ZoomInImage" alt="Zoom In" src="Images/zoominD.gif"  align="absMiddle"></td>

 

 7、再下面是生成地图组件的代码:

<script language="JavaScript" id="cs_dynamic_Map1">
Maps[mapCounter] = new MapCreation('Map1',0,mapCounter,0,0,502,378,'MapDiv_Map1','Black',2);
mapURL[mapCounter] = "ESRI.Web.Controls.MIMEImage.aspx?ImgID=Default.aspx-Map1&ct=5";
MakeMapDiv(mapCounter, 'Map1','ESRI.Web.Controls.MIMEImage.aspx?ImgID=Default.aspx-Map1&ct=5', 'MapCell_Map1','');
mapCounter++;
MapDragRectangle('Map1','ZoomIn', true);
</script>

  又看到了MIMEImage这个东东!它究竟是什么东东呢?

  如果对asp.net不是很熟悉的话,要破解这个秘密可能确实比较困难。

  在asp.net中,所有的请求,都是通过httpHandler来进行处理的。那httphandler又是什么东东呢?其实只要实现在IHttpHandler接口的类,都可以作为一个HttpHandler。在web.config或machine.config文件中,可以定义哪些请求可以由哪个httphandler来处理。查看一下web.config文件,没有这些声明。那就看一下mapchine.config文件吧,这个文件在WINDOWS/Microsoft.NET/Framework/v1.1.4322目录下,用记事本打开它,查找ESRI.Web.Controls.MIMEImage.aspx,好家伙,果然在这里啊!

 

<httpHandlers>
  <add verb="*" path="ESRI.Web.Controls.MIMEImage.aspx" type="ESRI.ArcGIS.Server.WebControls.ImageHandler, ESRI.ArcGIS.Server.WebControls, Version= 
    
      9.1.0 
    .722, Culture=neutral, PublicKeyToken=8fc3cc631e44ad86"/>

  原来ESRI.Web.Controls.MIMEImage.aspx请求是能过ESRI.ArcGIS.Server.WebControls.ImageHandler来处理的。在Visual Studio中,使用对像浏览器查看一下esri.arcgis.server.webcontrols.dll文件,可以看到ImageHandler类,果然实现了IHttpHandler接口。呵呵,其实很简单嘛,我们也完全可以自己写一个类,来执行自定义的请求。

  

  又写累了,就到这里吧。

 

  待续

ArcGis Server开发Web GIS新手体验(三)

接(二)

  在(二)中我们分析了HTML代码,也就基本弄清了.net adf怎样封装客户端的交互,以及客户端怎样与服务器端进行交互。下面我们再看一看服务器端的开发方式是怎样的,实际是就是进入了比较简单的实战。用其它工作开发Web GIS的朋友如果能够了解一下AGS的实现,一定会有很的大启发,你会在其中学到一些封装客户端、服务器端以及两者交互的技巧,怎样做到既封装一些常用的功能,又不妨碍我们进行功能的扩充。

        好了,废话少说,开始我们新的体验吧。
  在(一)中我们已经说了,.net adf提供了一系列的模板,这些模板又根据不同的需要,封装了一些常用的功能。我们的开发一般是从这些模板开始的。如果我们对这些模板生成的程序已经很熟了,当然也可以不需要这些模板,但如果你是新手,请从模板开始,这样可以避免走很多弯路。

        首先,我们启动Visual Studio 2003,新建一个项目,在新建对话框中,在“项目类型”中可以看到ArcGIS Server Projects这一项,选择语言Visual C#,在右边的模板列表中可以看到有七种模板可供选择,每种模板可用于新建不同用途的应用,如下图所示:


  我们先新建一个Map Viewer Web Application,也就是地图浏览程序。我们待会通过分析可以看到这个地图浏览程序是怎样实现的,以及怎样扩充自己的功能。
     新建了一个Map Viewer Web Application之后,界面如下图所示。可以看到,.net为我们新建了一个asp.net web工程。工程包括三个页面,default.aspx,errorpage.aspx和identify.aspx。其中,default.aspx是主界面,errorpage.aspx用于出错信息的显示,identify用于点击查询操作的结果的显示。下面我们主要分析default.aspx这个网页。



     这个网页的的上部分是一个banner,不用管。下部分由七个asp.net组件构成。这七个组件分别是:
  1、Map组件:地图组件。有两个关键属性:Host和ServerObject,不用我说,也知道这是什么意思。
  2、Toc组件:图层控件组件(table of contents)。有一个关键属性BuddyControl,即与哪个Map组件相关联。
        3、Toolbar组件:工具条组件。有一个关键属性BuddyControls,表示可以绑定多个Map组件或PageLayout组件。
        4、OverviewMap组件:导航图组件。有三个关键属性Host,ServerObject和BuddyControl。
  5、Impersonation组件:身份验证组件。有一个关键属性identity,用于设计怎么登录到服务器,拥有操作的权限。
  6、NorthArrow组件:指北针
  7、ScaleBar组件:比例尺组件,有一个关键属性BuddyControl。BarFont属性好像有Bug,怎么设置也不起效,字体总是很小,不知为什么,哪位朋友也帮俺一个忙,看看怎么回事?

  这七个组件中,显然Map组件最为重要,因为它负责地图显示并与用户交互。我们看一下Map组件有的事件,只有MapChanged的事件包含代码,仔细看一下,是与视图(地图范围)保存相关的代码。那Map组件与用户交互以及服务器端的处理代码,如缩放地图,在哪里呢?

        再看一看Toolbar组件,共包含七个按钮,分别是放大,缩小,平移,全图,上一视图,下一视图和点选。点开它的ToolbarItems属性看一下,原来工具条按钮的定义都在这里面。
        工具条按钮有两种类型:Tool和Command
        Tool:工具按钮。表示点击后并不立即执行某项功能,而是需要用户与地图进行交互再执行。所以需要保存它的状态。并且同时需要有相应的客户端代码(javascript)和服务器端代码。放大、缩小、平移和点选属于这种类型。
  Command:命令按钮。立即执行某项操作,不需要有户交互,所以不需要何存状态。全图、上一视图、下一视图属于这种类型。
        我们在ToolbarItems的定制界面中,选中identify,看一下它的属性,包括五部份:
        1、Appearance Images组:定义按钮显示的图片。这些设置会转化成HTML代码。
        2、Appearance Text组:有两个子项。Text表示在按钮中显示的文字,也就是说按钮可以由图片和文字两部份组成。ToolTip,即鼠标放在按钮上面时显示的提示信息。
  3、Client-side Action组:这组只有一个属性,就是ClientToolAction,这里就是与客户端交互的javascript代码了。内容是ID()。我们打开defaut.aspx,查看HTML,可以看到ID函数的内容。这里交互比较简单的情况,交互比较复杂,如放大时需要拉框,怎么封装?原来,Cient-side Action实际上只是javascript中onmousedown的执行函数,拉框所需的onmousemove和omnouseup去哪里找?其实只是一个小技巧而已,在onmousedown中动态地给onmousemove和onmouseup赋值不就可以了吗?事实上,.net adf封装zoomin等操作就是这要样做的。 
        Client-side Action属性有一个下拉选项,包含的是DragImage,DragRectangle,Point,Line,PolyLine,Polygon,Circle,Oval,none,Custom。不用解释,相信大家也明白了,是Toolbar组件封装了各种不同类型的客户端操作。这些与客户端交互的javascript在哪里呢?(二)中已经介绍了,这里就省略啦。
        4、General组。包括Disabled,Name,ShowLoading三个属性。
        5、Server-side Action组:有两个属性,ServerToolActionAssembly和ServerToolActionClass,用于定义服务器端要执行的功能。在.net adf中,每个被封闭的服务端操作,都是由一个类来实现的,ServerToolActionAssembly表示这个类在哪个程序集中,ServerToolActionClass就是这个类的名称。我们在ServerToolActionAssembly中选择ESRI.ArcGIS.Server.WebControls,可以清楚的看到该程序集中定义了四个这种类:MapCenterAt,MapPan,MapZoomin,MapZoomout。事件上,我们也可以定义自己的处理类,只要实现ESRI.ArcGIS.Server.WebControls.Tools.IMapServerToolAction接口就可以了。

        关于扩展:
        1、客户端交互:即Client-side Action组,adf封装了DragImage,DragRectangle,Point,Line,PolyLine,Polygon,Circle,Oval这几种操作,相信已经能够应付我们绝大部份的应用了。如果还不行,别忘了最后还有一项custom,选中它,自己写javascript就可以了。记得是onmousedown的javascript哦。在交互完毕后的代码中,如果需要返回到服务器端的话,记得执行_doPostback函数。
        2、服务器端功能实现:即Server-side Action组。Map组件针对客户端封装的每种行为,都提供了一个事件,表示客户端交互完毕后,立即执行该事件中的代码。这些事件有Oval,Line,Point,Polygon等。如果客户端操作是自己写的javascript,并最后提交了操作到服务器的话,可以在Page_Load中处理你自己的操作。

        上面介始的是Tool类型的工具条按钮。至于Command类型的就简单多了,我们可以选中FullExtent看一下,它的属性少了Client-side Action组和Server-side Action组。它的实现代码就直接到Toolbar组件的CommandClick事件中。自己去看吧。
       其它组件就不介绍了。
  
  说了这么多,相信您对用.net adf开发Web GIS已经有一个大致的了解,也基本明白了.net adf的封装方式,您已经可以开始偿试修改已有的功能,或者进行一些简单的扩展了。下一节我就再介绍一下怎样进行简单的功能扩展。

  待续

 ArcGis Server开发Web GIS新手体验(四)

 

接(三)

 

这一节主要贴代码算了,通过代码看一下一些简单功能的实现。偶快要放假了,静不下心来写了,写得也不好。说不定贴代码效果更好。

 

1、获取所有图层

 

ESRI.ArcGIS.Server.WebControls.WebMap webmap= Map1.CreateWebMap(); 
   
    try 
   
    { 
   
     ESRI.ArcGIS.Carto.IMapDescription descr = webmap.MapDescription;   
     ddlLayers.Items.Clear(); 
   
     int id; 
   
     for (int i=0;i<= descr.LayerDescriptions.Count-1;i++) 
   
     { 
   
      id = descr.LayerDescriptions.get_Element(i).ID; 
   
      ddlLayers.Items.Add(id.ToString() + "," + webmap.LayerNameFromID(id));    //ddlLayers是一个DropDownList控件 
  
     } 
   
     if (ddlLayers.Items.Count>0) 
   
     { 
   
      ddlLayers.SelectedIndex=0; 
   
     } 
   
             
    } 
   
    finally 
   
    { 
   
     webmap.Dispose(); 
   
    }

 

2、通过图层的ID获取图层对象

 

 

private IFeatureLayer GetFeatureLayer(int lyid) 
   
  { 
   
   WebMap webmap = Map1.CreateWebMap(); 
   
   try 
   
   { 
   
    ILayer layer = (webmap.MapServer as IMapServerObjects).get_Layer(webmap.DataFrame,lyid); 
   
    if (layer==null) 
   
     return null; 
   
    else 
   
    { 
   
     return (layer as IFeatureLayer); 
   
    } 
   
   } 
   
   finally 
   
   { 
   
    webmap.Dispose(); 
   
   } 
   
      
  }

 

3、新建一个多边形

 

 

 

private void Map1_Polygon(object sender, ESRI.ArcGIS.Server.WebControls.PolygonEventArgs args) 
   
  { 
   
   if (args.ToolName == "newpolygon") 
   
   { 
   
    IFeatureLayer flayer = GetCurFeatureLayer();        //获取当前活动图层了函数,这里就不贴了,就是调用GetFeatureLayer(int lyid)函数 
  
    if (flayer == null) return; 
   
    
    if (flayer.FeatureClass.ShapeType != ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon) 
   
    { 
   
     string sc; 
   
     sc = "<script language=javascript>alert('当前图层何类型不对!')</script>"; 
   
     Page.RegisterClientScriptBlock("ShapeTypeError",sc); 
   
     return; 
   
    } 
   
 
    //生成多边形 
  
    ESRI.ArcGIS.Server.IServerContext context; 
   
    ESRI.ArcGIS.Server.WebControls.WebMap webmap = Map1.CreateWebMap(); 
   
    webmap.ManageLifetime(flayer); 
   
    context = webmap.ServerContext; 
   
    ESRI.ArcGIS.Geometry.IPolygon poly = context.CreateObject("esriGeometry.Polygon") as ESRI.ArcGIS.Geometry.IPolygon; //'new ag.PolygonClass(); 
   
    webmap.ManageLifetime(poly); 
   
    ESRI.ArcGIS.Geometry.IPoint pt; 
   
    ESRI.ArcGIS.Geometry.IGeometryCollection ringcol = context.CreateObject("esriGeometry.Polygon") as ESRI.ArcGIS.Geometry.IGeometryCollection;// new  PolygonClass(); 
   
    webmap.ManageLifetime(ringcol); 
   
    ESRI.ArcGIS.Geometry.IPointCollection ptcol =context.CreateObject("esriGeometry.Ring") as ESRI.ArcGIS.Geometry.IPointCollection;// new RingClass(); 
   
    webmap.ManageLifetime(ptcol); 
   
    object obj=Type.Missing; 
   
    for (int i=0;i<=args.Vectors.Length-1;i++) 
   
    { 
   
     pt = webmap.ToMapPoint(args.Vectors[i].X,args.Vectors[i].Y); 
   
     ptcol.AddPoint(pt,ref obj,ref obj); 
   
    } 
   
    ringcol.AddGeometry(ptcol as IGeometry,ref obj,ref obj);    
    poly = ringcol as IPolygon;    
 
    //将多边形写入到图层中 
  
    ESRI.ArcGIS.Geodatabase.IFeature feature =  flayer.FeatureClass.CreateFeature(); 
   
    feature.Shape = poly as IGeometry; 
   
    feature.Store(); 
   
    webmap.Refresh(); 
   
 
    webmap.Dispose(); 
   
   } 
   
  }

 

 

 

4、矩形选择,获得选择集,并在地图上显示选中的对象。(这个功能花费了偶一天多的时间。)

 

 

 

private void Map1_DragRectangle(object sender, ESRI.ArcGIS.Server.WebControls.ToolEventArgs args) 
   
  { 
   
   string strTool = args.ToolName.ToLower(); 
   
   if (strTool=="rectsel") 
   
   { 
   
    //取得当前层 
  
    if (ddlLayers.SelectedValue=="") 
   
     return; 
   
    IFeatureLayer flayer = GetCurFeatureLayer(); 
   
    if (flayer == null) return; 
   
    
    //获得选择集 
  
    int t1=Environment.TickCount; 
   
    ESRI.ArcGIS.Server.WebControls.WebMap webmap = Map1.CreateWebMap(); 
   
    ESRI.ArcGIS.Server.IServerContext ctx = webmap.ServerContext; 
   
    webmap.ManageLifetime(ctx); 
   
    ESRI.ArcGIS.Geodatabase.IWorkspace ws = (flayer.FeatureClass as ESRI.ArcGIS.Geodatabase.IDataset).Workspace; 
   
    ESRI.ArcGIS.Geometry.IEnvelope env = ctx.CreateObject("esriGeometry.Envelope") as ESRI.ArcGIS.Geometry.IEnvelope; 
   
    webmap.ManageLifetime(ws); 
   
    webmap.ManageLifetime(env); 
   
    IPoint pt = webmap.ToMapPoint(Convert.ToInt32(Request.Params.Get("maxx")),Convert.ToInt32(Request.Params.Get("maxy"))); 
   
    env.XMax = pt.X; 
   
    env.YMin = pt.Y; 
   
    pt = webmap.ToMapPoint(Convert.ToInt32(Request.Params.Get("minx")),Convert.ToInt32(Request.Params.Get("miny"))); 
   
    env.XMin= pt.X; 
   
    env.YMax = pt.Y;    
    ESRI.ArcGIS.Geodatabase.ISpatialFilter filter = ctx.CreateObject("esriGeodatabase.SpatialFilter") as ESRI.ArcGIS.Geodatabase.ISpatialFilter; 
   
    webmap.ManageLifetime(filter); 
   
    filter.SpatialRel = ESRI.ArcGIS.Geodatabase.esriSpatialRelEnum.esriSpatialRelIntersects; 
   
    filter.Geometry = env as ESRI.ArcGIS.Geometry.IGeometry; 
   
    filter.GeometryField = flayer.FeatureClass.ShapeFieldName; 
   
    ESRI.ArcGIS.Geodatabase.ISelectionSet sset = flayer.FeatureClass.Select(filter,ESRI.ArcGIS.Geodatabase.esriSelectionType.esriSelectionTypeSnapshot,ESRI.ArcGIS.Geodatabase.esriSelectionOption.esriSelectionOptionNormal,ws); 
   
    
  
    int t2=Environment.TickCount; 
   
    int t3=t2-t1;    //t3是查询响应的时间,可以用来测试一下性能,呵呵    
 
    //显示选择集     
    int id; 
   
    ESRI.ArcGIS.Geodatabase.IEnumIDs ids; 
   
    ids = sset.IDs; 
   
    webmap.ManageLifetime(ids); 
   
    ids.Reset(); 
   
    ESRI.ArcGIS.Geodatabase.IFIDSet fidset = ctx.CreateObject("esriGeodatabase.FIDSet") as ESRI.ArcGIS.Geodatabase.IFIDSet;    
    id = ids.Next(); 
   
    while (id>=0) 
   
    { 
   
     fidset.Add(id); 
   
     id =ids.Next(); 
   
    } 
   
    IMapDescription desc = webmap.MapDescription as IMapDescription; 
   
    webmap.ManageLifetime(desc); 
   
    ILayerDescription ldesc = desc.LayerDescriptions.get_Element(flyid); 
   
    webmap.ManageLifetime(ldesc); 
   
    ldesc.SelectionFeatures = fidset; 
   
 
    //将选择信息保存在session中 
  
    Session["selection"] = sset; 
   
    Session["layerid"] = flyid; 
   
 
    webmap.Refresh(); 
   
 
    webmap.Dispose(); 
   
     
   } 
   
 
  }

 

 

 

5、删除选中的对象

 

 

 

private void DeleteSel() 
   
  { 
   
   if (Session["layerid"]==null) return; 
   
   if (Session["selection"] == null) return; 
   
 
   int layerid = (int)Session["layerid"]; 
   
   if (layerid == -1) return; 
   
   ESRI.ArcGIS.Geodatabase.ISelectionSet sset = Session["selection"] as ESRI.ArcGIS.Geodatabase.ISelectionSet; 
   
   if (sset == null) return; 
   
 
   WebMap webmap = Map1.CreateWebMap(); 
   
   IFeatureLayer layer = GetFeatureLayer(layerid); 
   
   if (layer==null) return; 
   
   webmap.ManageLifetime(layer); 
   
   webmap.ManageLifetime(sset); 
   
   ESRI.ArcGIS.Geodatabase.IEnumIDs ids = sset.IDs; 
   
   webmap.ManageLifetime(ids); 
   
   ids.Reset(); 
   
   int id; 
   
   id = ids.Next(); 
   
   ESRI.ArcGIS.Geodatabase.IFeature feature; 
   
   ESRI.ArcGIS.Server.IServerContext ctx = webmap.ServerContext; 
   
   webmap.ManageLifetime(ctx); 
   
   //将selectionset转化为featurecursor对象 
  
   ESRI.ArcGIS.Geodatabase.IFeatureCursor fcursor; 
   
   ESRI.ArcGIS.Geodatabase.ICursor cursor; 
   
   sset.Search(null,false,out cursor); 
   
   fcursor =  cursor as ESRI.ArcGIS.Geodatabase.IFeatureCursor; 
   
   ESRI.ArcGIS.esriSystem.ISet pDeleteSet = ctx.CreateObject("esriSystem.Set") as ESRI.ArcGIS.esriSystem.Set; 
   
   webmap.ManageLifetime(pDeleteSet); 
   
 
   //设置ISet对象 
  
   feature = fcursor.NextFeature(); 
   
   while (feature != null) 
   
   { 
   
    pDeleteSet.Add(feature); 
   
    feature = fcursor.NextFeature(); 
   
   } 
   
 
   ESRI.ArcGIS.Geodatabase.IFeatureEdit fedit; 
   
   pDeleteSet.Reset(); 
   
   fedit = pDeleteSet.Next() as ESRI.ArcGIS.Geodatabase.IFeatureEdit; 
   
   while (fedit != null) 
   
   { 
   
    fedit.DeleteSet(pDeleteSet); 
   
    fedit = pDeleteSet.Next() as ESRI.ArcGIS.Geodatabase.IFeatureEdit; 
   
   } 
   
 
   Session.Remove("layerid"); 
   
   Session.Remove("selection"); 
   
 
   webmap.Refresh(); 
   
 
   webmap.Dispose(); 
   
  }