Vishful thinking…

One overlooked feature that is coming in ArcGIS Server 10

Posted in ArcGIS, ESRI, GIS by viswaug on March 29, 2010

At the ESRI devsummit last week, there were a lot of new features in ArcGIS Server (AGS) version 10 that were getting a lot of attention. There was a lot of fan-dare around geodatabase editing over the web with the new Feature Service in AGS 10 and the flashy demos with all the new RIA clients for editing with the REST API. There are also a lot of articles & blog posts that have been written to cover those features in details. So, I thought I would stay off the beaten path and direct your attention towards a new feature in AGS 10 that is getting little to no attention. That new feature in AGS v10 is support for exporting PNG32 (32 bit PNG) map images from the REST API and other APIs offered by AGS. This should provide the complete support 8-bit transparency in PNGs and should help us avoid issues like the ones here. Printing maps functionality should also benefit from this new feature both in terms of quality and to avoid transparency issues when layering images.

Just check out the ‘Image Format’ drop-down here for proof of 32 bit PNG support . And as you can see here, AGS 9.3.1 only supported PNG24. Hope that helps someone… 🙂

Advertisements

Working with ESRI token secure services

Posted in ArcGIS, ESRI, GIS, Uncategorized, Web by viswaug on March 29, 2010

At the ESRI developer summit this past week, I ran into some people that were either having a hard time with using the ESRI token authentication or were leaving their systems vulnerable to hacks given their use/abuse of long lived tokens. I thought it might be useful to share one way that we have been using ESRI token secured services in our web mapping applications.

Token secure services require the client to request a token with their username & password which should then be used/included in all other future requests to access the services. The token provided to the user by AGS is also valid only for the time period requested by the user. The AGS server also applies a upper limit to how long the token can be valid.

One of the main reasons for troubles with using such token secure services in a web mapping application is that the user logs into the web application that he is using and not actually the AGS server(s) that the web application is using map services from. So, in order to use the map services in the web application, the user has to log-in (again) to the AGS server also. Having the user log in again after they have already logged into the web application is highly undesirable. To prevent the user from having to enter in the credentials to access AGS services again, some may decide to use a long lived token and hard-code the token into the web application or hard-code the username & password to access AGS services in the mapping client application. I don’t think I need to explain why hard-coding the username & password in the client web mapping application is dangerous. But this still leaves the application highly vulnerable to hacks since anybody who can read the URL being used to access the services have access to the long-lived token. Using the long-lived token, anybody can obtain access to the AGS services since the only defense is the ClientID (or the HTTP Referrer header) and that can be spoofed easily since it is never verified. Also, the long-lived token doesn’t expire often and leaves the hackers a lot of time to get the token and access the secure AGS services

To get around this, there is an easy way to setup the web application to use and better secure the AGS services. We might have two main ways of sharing username & password between the web application and the web application. The first way is to have AGS and the web application share the membership/permission/roles datastore. In this case, the web application can use the same username & password combination to obtain a token from the AGS server. The second way is to have all users of the web application use the same name username & password to access the AGS services. The second way could work because the user has already been authenticated by the web application and so he can be trusted to access the AGS services also. In this case, the username & password that will be used to log-in all web application authenticated users can be stored in the web application configuration file (web.config). This credential can be used to obtain a token from AGS. This is generally how Bing map services are also handled. The Bing credentials are stored in the web.config and used to obtain a Bing token when the page with the map is loaded.

So, once the user logs into the web application, the username & password from the shared datastore/web.config can be used to make a request to the AGS ‘GetToken’ URL endpoint and obtain a short-lived token for AGS access. This token can then be sent down to the client as a part of the HTML / ASPX page. Another technique is to write a HTTPHandler that accepts a GET request without a username & password and uses credentials from the shared datastore/web.config to obtain a token to access AGS services and sends the token down to the web application client. Is method is secure because the HTTPHandler itself can be secured by either windows/forms authentication of the host web application.

Another thing to note about AGS tokens is that AGS does NOT require a ‘Referrer’ (IP address/ Site URL) to generate a short-lived token (long-lived tokens do require them). If you are generating a token from the AGS web page to generate a token, you will have an option to not specify the ‘Referrer’ (ClientID), but if you are just making a HTTP request to the GetTokens endpoint, you can obtain a short-lived token without the ClientID. When using short-lived tokens obtained without the ClientID, AGS does NOT enforce checks on where the calls are originating from. Actually, this is the reason why Silverlight clients are currently able to consume token secure map / AGS services. Silverlight 3 & under clients do not include the ‘Referrer’ HTTP Header for all outgoing HTTP requests, so ClientID origin checks are not enforced on Silverlight API clients. This issue has been fixed in Silverlight 4.

Unfortunately, the authentication tokens generated by ASP.NET to secure web applications and the ones generated by AGS are generated using different techniques. The key used to generate the token is different, ASP.NET uses the machineKey from web.config and AGS token uses a key from the AGS configuration file. If this wasn’t the case, we could technically have the ASP.NET web application and AGS share the same token…

Quick lesson learnt implementing continuous zoom operations for the ESRI Silverlight API

Posted in ArcGIS, ESRI, GIS, Uncategorized by viswaug on February 1, 2010

One of the nicer navigation features that enhance suser experience on mapping applications is the continuous zoom in & out and pan operations. Also, users that use Google and Bing maps frequently expect the continuous zoom and pan experience in all the mapping applications 🙂 The ESRI Silverlight API Toolkit does not include support for continuous zoom and pan operations. But implementing the continuous navigation operations for the ESRI Silverlight API is real easy with the DispatcherTimer class that was introduced with Silverlight version 2.0. The DispatcherTimer class calls the ‘Tick’ event listeners on the UI thread so developers don’t have to worry about accessing UI controls from across threads. Implementing it is as simple as setting the map’s extent very frequently with new extent calculated for zoom in/out/pan operations. To provide a good experience, I had to reset the map’s extent every 10 milliseconds.

I had initially overlooked the fact that every time I reset the map’s extent every 10 milliseconds a map image request was being made for every DynamicLayer that was loaded on the map. The problem doesn’t occur with the TiledMapServiceLayer because requests for tile images only occur after the zoom/pan operation has caused the map’s extent to exceed the extent of the tile map images already loaded on to the map and the browser also caches the tiles client-side. The excessive number of map image requests (1 request every 10 milliseconds) generated by the continuous zoom operation would bring any GIS server (and did bring our server) to its knees pretty soon. There is no perfect solution to the problem here in my humble opinion. But an acceptable solution to the problem is to hide (change visibility to false) all the DynamicLayer(s) on the map when the continuous navigation operation begins and to reset the layers back to their previous state when the continuous navigation operation ends. Since the base map layers are TiledMapServiceLayer(s), they don’t pose the problem with the excessive number of requests and we can leave them visible. This actually provides an acceptable user experience during the continuous navigation operations.

The code snippet below illustrates the implementation of a sample continuous zoom in & out operations.

Note – In Silverlight any control that inherits from ButtonBase like Button, CheckBox, RadioButton etc will not raise the ‘MouseLeftButtonDown’ and ‘MouseLeftButtonUp’ events even though the events are available on the classes.

public partial class MainPage : UserControl

{

    private DispatcherTimer _timer;

    Dictionary<Layer, bool> _mapLayersVisibilityState = null;

 

    public MainPage()

    {

        InitializeComponent();

 

        IDisposable subscription = null;

        subscription = myMap.Layers.GetLayersLoadCompleted().Subscribe

            (

                ( args ) =>

                {

                    txtStatus.Text = "All layers have loaded.";

                    subscription.Dispose();

                }

            );

        txtStatus.Text = "Loading Layers onto map …";

    }

 

    void zoomOut_MouseLeftButtonUp( object sender, MouseButtonEventArgs e )

    {

        if( _timer != null )

            _timer.Stop();

        EndContinuousOperation();

    }

 

    void zoomOut_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )

    {

        BeginContinuousOperation();

        _timer = new DispatcherTimer();

        _timer.Interval = new TimeSpan( 0, 0, 0, 0, 10 );

        _timer.Tick += _zoomOutTimer_Tick;

        _timer.Start();

    }

 

    void zoomIn_MouseLeftButtonUp( object sender, MouseButtonEventArgs e )

    {

        if( _timer != null )

            _timer.Stop();

        EndContinuousOperation();

    }

 

    void zoomIn_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )

    {

        BeginContinuousOperation();

        _timer = new DispatcherTimer();

        _timer.Interval = new TimeSpan( 0, 0, 0, 0, 10 );

        _timer.Tick += _zoomInTimer_Tick;

        _timer.Start();

    }

 

    void _zoomInTimer_Tick( object sender, EventArgs e )

    {

        ZoomMapByFactor( 0.99 );

    }

 

 

    void _zoomOutTimer_Tick( object sender, EventArgs e )

    {

        ZoomMapByFactor( 1.01 );

    }

 

    private void BeginContinuousOperation()

    {

        _mapLayersVisibilityState = GetMapLayersVisibilityState();

        HideAllDynamicMapLayers();

    }

 

    private void EndContinuousOperation()

    {

        SetMapLayersVisibilityState( _mapLayersVisibilityState );

    }

 

    private Dictionary<Layer, bool> GetMapLayersVisibilityState()

    {

        Dictionary<Layer, bool> visibilityStates = new Dictionary<Layer, bool>();

        myMap.Layers.ForEach<Layer>( lyr => visibilityStates.Add( lyr, lyr.Visible ) );

        return visibilityStates;

    }

 

    private void SetMapLayersVisibilityState( Dictionary<Layer, bool> visibilityStates )

    {

        if( visibilityStates == null )

            return;

 

        foreach( var entry in visibilityStates )

        {

            entry.Key.Visible = entry.Value;

        }

    }

 

    private void HideAllDynamicMapLayers()

    {

        myMap.Layers.ForEach<Layer>( lyr =>

        {

            if( lyr is DynamicLayer )

                lyr.Visible = false;

        } );

    }

 

    void ZoomMapByFactor( double factor )

    {

        if( myMap != null )

        {

            Envelope env = myMap.Extent;

            env.Expand( factor, myMap.RenderSize );

            myMap.Extent = env;

        }

    }

}

The code above makes use of the ‘Expand’ extension method for the ‘Envelope’ type provided below.

public static void Expand( this Envelope extent, double factor, Size mapSize )

{

 

    if( extent == null )

        throw new ArgumentNullException( "extent" );

    if( mapSize.Width <= 0 )

        throw new ArgumentOutOfRangeException( "mapSize.Width" );

    if( mapSize.Height <= 0 )

        throw new ArgumentOutOfRangeException( "mapSize.Height" );

 

    if( extent.XMax == extent.XMin )

    {

        double resolution = extent.Width / mapSize.Width;

        double xVal = extent.XMin;

        //using a 10 pixel buffer

        extent.XMin = xVal 10 * resolution;

        extent.XMax = xVal + 10 * resolution;

    }

 

    if( extent.YMax == extent.YMin )

    {

        double resolution = extent.Height / mapSize.Height;

        double yVal = extent.YMin;

        extent.YMin = yVal 10 * resolution;

        extent.YMax = yVal + 10 * resolution;

    }

 

    MapPoint center = extent.GetCenter();

    double dX = ( extent.Width / 2 ) * factor;

    double dY = ( extent.Height / 2 ) * factor;

 

    extent.XMin = center.X dX;

    extent.XMax = center.X + dX;

    extent.YMin = center.Y dY;

    extent.YMax = center.Y + dY;

}

GeoJSON & GPX support added to the ESRI Silverlight API Contrib

Posted in ArcGIS, ESRI, GIS, Silverlight by viswaug on August 18, 2009

I’ve added support for the GeoJSON and GPX layer types to the ESRI Silverlight API Contrib project on CodePlex. Adding GeoJSON or GPX layer to the ESRI Silverlight API map is real easy and you would add it just like adding a FeatureLayer to the map.

Adding a GeoJSON layer to the map

<esri:Map x:Name="MyMap" Grid.Row="1">
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"
Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/>
                <slContrib:GeoJSONLayer ID="geoJSONLayer"
                     URL="http://localhost/SLMaps.Web/Data/JSON.txt" />
            </esri:Map.Layers>
</esri:Map>

Adding a GPX layer to the map

<esri:Map x:Name="MyMap" Grid.Row="1">
            <esri:Map.Layers>
                <esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"
Url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer"/>
                <slContrib:GPXLayer ID="gpxLayer"
                 URL="http://localhost/SLMaps.Web/Data/fells_loop.txt" />
            </esri:Map.Layers>
</esri:Map>

This adds to the GeoRSS layer support already present in the library.

Other than just adding these data sources as layers to the map, The GeoJSONReader & GPXReader classes can also be used to just parse the data source and obtain the geometry and attribute values of the features in the data source if/as required. This should allow for the users to upload GeoJSON & GPX data from their GPS units directly from their computers to the Silverlight map control without the need to upload files to the server. Allowing the workflow to be smoother, faster and simple both on the server-side & client-side.

Exploring/Exploiting the query operation in the ArcGIS REST API

Posted in ArcGIS, ESRI, GIS by viswaug on July 9, 2009

I was starting to look harder at the query operation in the ArcGIS Server REST API today to figure if I can leverage it to get specific results I needed instead of building my own REST services. The scenario I was looking at was to be able to get the records corresponding to the minimum and the maximum values in a given field. To provide an example, let’s say you have a ‘States’ layer with a field called ‘POP2008’ that contains population numbers for the year 2008. In this case, I want to obtain the state records with the minimum and the maximum population for the year 2008. At the outset, there didn’t seem to be a way to do it. After spending some time investigating the possibilities with the REST API query operation, I found that the above was in fact possible. Assuming that the FeatureClass name of the ‘States’ layer is ‘States_DTL’, the query below will produce the desired results.

POP2008 = (SELECT MIN(POP2008) from States_DTL) OR POP2008 = (SELECT MAX(POP2008) from States_DTL)

I was surprised to find out that I was able to use the name of a FeatureClass in the query. Agreed, the user of the REST API will/might not know the name of the FeatureClass. But the user could get lucky and be able to guess the name of the FetaureClass after ‘n’ tries. The FeatureClass / Table being used doesn’t even need to be a part of the MapService. I am not yet sure about how far this behavior can be exploited. Nevertheless, I found that this behavior was a little more than interesting.

Silverlight databinding limitations

Posted in ESRI, GIS, Silverlight by viswaug on April 14, 2009

Target of databinding in Silverlight “HAS” to be a “FrameworkElement” and not just a “DependencyObject” like in WPF. I am not sure that there is a reason why databinding to “DependencyObject”s in Silverlight is explicitly omitted by Microsoft. Seems like it might be an oversight. But even after many people have complained about it in the forums, the databinding to “DependencyObject”s feature doesn’t seem to be included in the beta version of the latest Silverlight 3 library.

So, what does that mean"? Where does it really become a limitation? Well, it really does limit our options when trying to databind values to the “Transform” classes like the “RotateTransform”, “ScaleTransform”, “SkewTransform”, “TranslateTransform” etc. Let’s say that you are symbolizing your points as an Ellipse or a Rectangle, and you want to be able to size your symbols based on some value in the Attributes collection of your Graphic. The best way to do this would be to apply a ScaleTransform on the Ellipse or Rectangle (on the RenderTransform property) and databind the attribute values to the ScaleX and the ScaleY dependency properties of the ScaleTransform. But since the ScaleTransform is only a DependencyObject and not a FrameworkElement, we cannot bind to the ScaleX and ScaleY properties of the ScaleTransform. This scenario can easily be solved by binding to the Width and Height property of the Rectangle or Ellipse. But there are a lot of other scenarios that cannot be overcome as easily. Like for example, you will not be able to label along a line by databinding to a RotateTransform on a TextBlock for example. Also in the ESRI Silverlight API, we cannot apply a TextSymbol to a polyline or polygon geometry.

GIS Standards gone crazy (EPSG especially)

Posted in GIS by viswaug on April 1, 2009

A couple of weeks ago I had written about how the different axis ordering that can be defined in EPSG coordinate system standards makes the lives of any GIS software provider that wants to implement these standards a whole lot harder. Today, I came across some information that really doesn’t make any sense to me. Previously Morten had written about EPSG finally getting around to adding the web mercator to their standards with the EPSG code “3785”. But in February, EPSG decided to change the EPSG code from “3785” to “3857”. Look at the change request info in the image below. That information can be obtained at http://www.epsg-registry.org.

EPSG3857

 

Also, as you might have already heard, OGC had accepted KML as an OGC standard sometime last year. The KML standard includes its own method of defining styles/symbology for 2D & 3D features along with other things. But OGC in fact already had its own existing standards for defining 2D feature styles/symbology in map layers called the Styled Layer Descriptor (SLD).

Now, the OGC has two standards to define features styles in XML which really kind of makes it a double standard.

Now, from what I read, the OGC is working on combining both those standards into one. Which is going to be a tough job since there are so many overlaps between KML and other existing OGC standards.

Lack of good transparency support in Silverlight and what it means to online mapping apps

Posted in ESRI, GIS, Silverlight by viswaug on April 1, 2009

The support for transparency in PNG images in Silverlight is to say the least really bad. Here is what the Microsoft docs says about PNG transparency support in Silverlight

Silverlight does not support all possible color depths that are included in the PNG specification. The following are the PNG color depths supported in Silverlight:

  • Indexed color: 1-bit, 4-bit, or 8-bit color depth (per channel).
  • Truecolor: 24-bit color depth, or 32-bit color depth (per channel) for truecolor plus alpha.

Notably, gray scale (with or without alpha), and 64-bit truecolor, are not supported in Silverlight.

Note that they don’t mention anything about the support for 1, 2, 4 and 8 bit PNGs. This creates some problems when using the ESRI Silverlight API and you might what to keep your eye out for it and pay good attention to how your map caches are being generated. Look at the results when I overlay ArcGIS Online’s Transportation layer on top of the Imagery layer in the ESRI Silverlight maps.

<esri:Map x:Name=“MyMap” Grid.Row=“1” Grid.Column=“2”>

<esri:Map.Layers>

<esri:ArcGISTiledMapServiceLayer

ID=“StreetMapLayer”

Url=http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_Imagery_World_2D/MapServer&#8221;/>

<esri:ArcGISTiledMapServiceLayer

ID=“mapLayerTransportation”

Url=http://server.arcgisonline.com/ArcGIS/rest/services/Reference/ESRI_Transportation_World_2D/MapServer&#8221;/>

</esri:Map.Layers>

</esri:Map>

And here it what the map look like. As you can see, the the tile areas outside the continental US are grayed out.

Transportation3

Also, check out this Silverlight forum post where Morten schools Microsoft about the issue mentioned above.

Reversed co-ordinate axis order for EPSG:4326 vs CRS:84 when requesting WMS 1.3.0 images

Posted in ArcGIS, ESRI, GIS by viswaug on March 15, 2009

I spent quite a bit of time last week over this and thought it might help others who might encounter the same thing as I did. I was requesting images from the WMS service version 1.3.0 in ArcGIS Server and everything was fine as long I was requesting images with the “CRS:84” value for the co-ordinate reference system. According to the GetCapabilities document returned from the WMS Server, both the “CRS:84” and the “EPSG:4326” values are suported by the WMS server.

http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?VERSION=1.3.0&REQUEST=GetCapabilities

But when I started requesting images with “EPSG:4326”, I was seeing some really weird behaviour. I spent quite a bit of time trying to figure out what was going on without luck. The OGC team at ESRI helped me out and pointed out that when using WMS 1.3.0, the co-ordinate axis order in reversed for CRS:84 and EPSG:4326. So, when requesting images in CRS:84 use the coordiate axis order of (long, lat) and when using EPSG:4326 use the (lat, long) order.

http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?VERSION=1.3.0&REQUEST=GetMap&CRS=CRS:84&BBOX=-178.217598,18.924782,-66.969271,71.406235&WIDTH=765&HEIGHT=360&LAYERS=0,1,2&STYLES=,,pointSymbolizer&EXCEPTIONS=application/vnd.ogc.se_xml&FORMAT=image/png&BGCOLOR=0xFFFFFF&TRANSPARENT=TRUE&SLD=http://sampleserver1.arcgisonline.com/arcgis/wms/slds/point_pointSymbolizer.xml

http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG:4326&BBOX=18.924782,-178.217598,71.406235,-66.969271&WIDTH=765&HEIGHT=360&LAYERS=0,1,2&STYLES=,,pointSymbolizer&EXCEPTIONS=application/vnd.ogc.se_xml&FORMAT=image/png&BGCOLOR=0xFFFFFF&TRANSPARENT=TRUE&SLD=http://sampleserver1.arcgisonline.com/arcgis/wms/slds/point_pointSymbolizer.xml

But when requesting images from WMS Server version 1.1.1 with EPSG:4326, we should still use the coordinate axis order of (long, lat)

http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG:4326&BBOX=-178.217598,18.924782,-66.969271,71.406235&WIDTH=765&HEIGHT=360&LAYERS=0,1,2&STYLES=,,pointSymbolizer&EXCEPTIONS=application/vnd.ogc.se_xml&FORMAT=image/png&BGCOLOR=0xFFFFFF&TRANSPARENT=TRUE&SLD=http://sampleserver1.arcgisonline.com/arcgis/wms/slds/point_pointSymbolizer.xml

Do these standards really help when the standards are not really STANDARD?

Then comes the issue of versioning of these standards, especially the OGC standards. The OGC standards are so reliant on one another that the different versions that exist in each standard actually adds a lot more complexity to systems that actually use them. For example, the SLD 1.1.0 standard (Styled Layer Descriptor) depends on the FE 1.1.0 standard (Filter Encoding), the SE 1.1.0 standard (Symbology Encoding) and the GML 3.1.1 standard (Geography Markup Language). As and when the standards evolve and higher versions are created, the versions of the standards they in-turn depend on change making a big mess for the systems that actually have to implement these standards.

Options for solving the problem of a graphics layer for the web

Posted in ArcGIS, ESRI, GIS by viswaug on March 5, 2009

I realize that most people developing web mapping applications have already solved this problem one way or the other. But some solutions are better than others for certain scenarios and needs to be paid attention to. I also want to mention that there are numerous other ways that this can be accomplished, but I am going to limit this post to the ones that I think are the good ones. The graphics layer can really be maintained at three different tiers the client (browser), web server, ArcGIS Server. Here are some notes and observations on each

Client(Browser) – When the graphics layer is maintained on the client-tier, it is drawn by the browser as VML/SVG depending on if you are using Internet Explorer / FireFox etc. In the case of the Flex and the upcoming Silverlight mapping controls, the graphics would be drawn as the corresponding framework’s graphic elements. The geometries of all the graphics are pulled from the ArcGIS Server to the browser (REST API).

Pros:

  • To identify any feature on the graphics layer, a round trip to the Web or the ArcGIS Server is not required.
  • The feature symbology/styles can be changed without a round trip to the server.
  • The graphics layer can be more interactive, like highlight feature on mouse over etc.

Cons:

  • The drawing performance can be slow when trying to draw large number of features in the graphics laye. The performance in the case of Flex and Silverlight controls will be better than the drawing performance of SVG/VML DOM elements.
  • You could be drawing only a few features (ploygons/polylines), but each of those features might have a large number of vertices. Imagine drawing county boundaries with thousands of vertices.
  • When drawing large number of features, large amounts of data (relatively) is pulled in by the client (browser).

Web Server – When the graphics layer is maintained on the Web server, it is drawn by the ElementGraphicsLayer or the FeatureGraphicsLayer classes in the Web ADF. These classes use GDI internally to create the graphic layer map images. These classes create images that are then sent down to the browser to be overlaid on top of the map element. Non-ESRI solutions can use the SharpMap project to create the graphic layer map images.

Pros:

  • Can draw large number of features relatively fast. Again drawing exorbitantly large number of feature can still make it slower.
  • Features can be organized into layers and easily styled using the available renderers like UniqueValueRenderer etc.

Cons:

  • Less interactive since highlighting features on mouse over will need a trip back to the web server.
  • Identify operations will need a trip back to the web server.
  • Style changes need trip back to web server.
  • The web server’s session storage and thus the memory could get overloaded.

ArcGIS server – There are many ways by which you could have the ArcGIS Server handle the drawing of the graphic features for you. But I am only going to discuss the cleanest of them all. In this case, when the graphics layer is drawn on/by the ArcGIS Server, the features and their symbology are passed onto the ArcGIS Server to be drawn using the ExportMapImage method in the SOAP API. The MapDescription argument of this method contains an array of GraphicElements that will be drawn by the ArcGIS Server.

Pros:

  • The graphic layer is embedded on the map image itself and doesn’t need to be pulled in as a separate image thus saving a little bit (very little) of bandwidth.
  • A good solution when it comes to printing/generating print map images with the graphics layer.

Cons:

  • Potentially large amounts of data is pushed between the web server and the ArcGIS Server.
  • The graphic layer’s features will need to be maintained on the web server’s session.

One thing to keep in mind is that none of the above solutions is a great solution (even thought they can be workable) for labeling features on the graphics layer.