Tag: Rasters

What's new in the 9.3.1 .NET Web ADF

Here’s a brief look at what’s new in the ArcGIS Server .NET Web ADF at 9.3.1. This information comes from the What’s new in ArcGIS 9.3.1 PDF where you can read about new features in all areas of the product. If you have questions about any of the new features, please leave a comment to this post.

Customizing the look and feel of MapTips

The Web ADF JavaScript Library has been enhanced to provide greater control over customizing the look and feel of MapTips. New examples have been added to the MapTips sample that demonstrate how to leverage this new capability. In addition, a new MapTips custom control template is also available from the ArcGIS Server Resource Center .NET code gallery that enables drag-and-drop configuration of the new customization endpoints.

User control task

A new User Control task has been added to the available Web controls in the Web ADF. This new task is based on the User Control task sample available in the software developer kit (SDK). In addition, you can configure custom User Control tasks in ArcGIS Server Manager and include them in Web mapping applications.

Print task templates

In ArcGIS 9.3.1, a new property called LayoutTemplateFile is available that allows you to define the contents of your printed maps. This file, located at your Web site’s default root directory/aspnet_client/ESRI/WebADF/PrintTaskLayoutTemplates/default.htm, is customizable.

The Print task will generate a map layout based on your template. By default, at 9.3.1, this new map template includes the map title, map, and legend information. Task results and copyright text can also be included in the printed map.

Posted in Services | Tagged , , , , | 1 Comment

Questions and answers about ArcGIS Server 9.3.1 map services

In a previous post Design patterns for Web maps, we talked about strategies and challenges for displaying different types of map layers on the Web for the best performance. Caching is the fastest way to serve Web maps, but requires an initial time investment for cache creation. Also, datasets that change often and cover a broad extent cannot be cached and require a (typically slower) dynamically drawn service. Continue reading

Posted in Services | Tagged , , , | 25 Comments

Querying points and lines on click with the ArcGIS JavaScript API

Many of the existing ArcGIS JavaScript API samples for the Query task show how to query polygon features. This post explains one way to query points and lines with a mouse click on the map.

Querying a point or a line is a little more difficult than querying a polygon because the mouse click is required to fall directly on the line or point in order for a result to be returned. To makes things easier for your users, you can build a “tolerance” envelope around the clicked point.

       var centerPoint = new esri.geometry.Point
        var mapWidth = map.extent.getWidth();

        //Divide width in map units by width in pixels
        var pixelWidth = mapWidth/map.width;

        //Calculate a 10 pixel envelope width (5 pixel tolerance on each side)
        var tolerance = 10 * pixelWidth;

        //Build tolerance envelope and set it as the query geometry
        var queryExtent = new esri.geometry.Extent
        query.geometry = queryExtent.centerAt(centerPoint);

In the above code, you figure out the width of one pixel in map units given the current scale. You then multiply this by the total tolerance width in pixels. So if you want a tolerance of 5 pixels on each side, you multiply by 10. This gives you the width of your tolerance envelope in map units.

You then use one of the esri.geometry.Extent constructors to make the square tolerance envelope. Any feature that intersects the envelope will be returned as a query result.

Building a rectangular tolerance around the clicked point

It’s worth noting that the Identify task has a built-in tolerance that you can easily modify using IdentifyParameters. However, the Identify task does not allow you the flexibility to determine which fields are returned. The Query task lets you narrow the fields.

Contributed by Sterling Quinn and Jeremy Bartley of the ArcGIS Server development team

Posted in Services | Tagged , , | 4 Comments

Geoprocessing parameter types in the ArcGIS JavaScript API

Every geoprocessing task has a set of input parameters, which represent values or datasets that the model takes in. You need to supply the parameters correctly in order to run the task. In this post we’ll look at how you find out the parameter types and supply them in your code when working with the ArcGIS JavaScript API.

One important thing to remember about geoprocessing tasks is that they have a limited set of input and output data types when compared with tools that you work with in ArcGIS Desktop. This makes it a little easier to work with parameters because you only have to learn a handful of object types.

To find out the parameter data types for any geoprocessing task, use the Services Directory. For example, take a look at the Services Directory page for this ClipAndShip task. There are two parameters here:

  • Area_To_Zip, which is of data type GPFeatureRecordSetLayer
  • Email_Zip_To, which is of data type GPString

You can tell the above parameters are both inputs since their Direction is listed as “esriGPParameterDirectionInput”.

You may be wondering how you create those parameters in your JavaScript code, especially because there’s no object in the API with a name resembling “GPFeatureRecordSetLayer”. At this point you need to use the Parameter Type table in the Supplying parameters for the Geoprocessor help topic to understand which JavaScript object corresponds to your parameter type. That table is copied in below:

Parameter type Corresponding JavaScript object
GPBoolean boolean
GPDataFile DataFile
GPDate Date
GPDouble number
GPFeatureRecordSetLayer FeatureSet
GPLinearUnit LinearUnit
GPLong number
GPRasterData RasterData
GPRasterLayer RasterData
GPRecordSet FeatureSet
GPString string

This table shows that the corresponding JavaScript object for a GPFeatureRecordSetLayer is the FeatureSet. This is an array of graphic features that can contain geometry and/or attributes.

For the GPString parameter, you just need to create a JavaScript string.

Once you have all the input parameters, you need to list them in JavaScript Object Notation (JSON) and pass them to the Geoprocessor. Your code might look like the following:

var params = { "Area_To_Zip":myFeatureSet, "Email_Zip_To":email };

If there are output parameters, you’ll have access to a ParameterValue array after the job completes. The number and types of objects in the array will vary according to the number and types of output parameters used by the task. However, the mappings between parameter types and JavaScript objects will still follow the table above.

To learn more about input and output parameters, see:

Contributed by Sterling Quinn of the ArcGIS Server software development team

Posted in Services | Tagged , , , | Leave a comment

Customizing the map progress bar in the 9.3 Web ADF (.NET)

The Web ADF includes a progress bar that displays when the map is loading map images or tiles. It makes the user aware that the site is processing the user’s request. You may wish to customize the progress bar, either to modify it or to replace it with your own progress indicator. An earlier blog post described how to do this at the 9.2 version. Things have changed for the 9.3 version, and this post gives some tips on customizing the progress bar for 9.3.

We will cover two options for customizing the progress indicator. First, you can set some of the properties of the existing progress bar. Second, you can completely replace the progress bar with your own custom progress indicator. The second option involves working with custom progress events, which we will discuss before we get to the actual replacement of the default progress indicator.

Setting progress bar properties

At the 9.3 release, two public properties are exposed that you can set for the standard progress bar. These properties are the alignment, or location, of the progress bar on the map; and whether to enable or disable the progress bar. More properties may be exposed at future service packs or versions. We will use the enable/disable property later in this article, when we replace the progress bar. Let us look now at setting the alignment property, which will introduce a client-side approach we will use throughout this article.

The alignment property may be set using the Web ADF JavaScript Library. The Web ADF contains both code that runs on the server and code that runs on the client. The server-side code uses an ASP.NET language (C# or VB). The client-side code uses JavaScript, so we use that language to customize how the client code works. You can find documentation on the Web ADF JavaScript Library in the ArcGIS Server Developer Help, available either installed on your development computer, or online at the ESRI Resource Center. See the topic Web ADF JavaScript Library under the heading Developing Web applications using the Web ADF.

The progress bar properties are on the Map, since the bar is tied to the Map. Most of the properties and methods for the Map class are actually on the MapBase class, which the Map class extends. If you look on the class properties for MapBase, you will find the progressBarAlignment property. You will notice that, like most other properties, the documentation actually shows two methods associated with this property: get_progressBarAlignment() and set_progressBarAlignment(). As you will see in the code, we use these methods rather than the property per se when setting the propery.

The set_progressBarAlignment() method takes one argument when you call it: a ContentAlignment setting. For information on this enumeration, you can click on the ContentAlignment link on the progressBarAlignment page in the help, or find it under the ESRI.ADF.System namespace in the Web ADF JavaScript Library documentation. The ContentAlignment enumeration has nine values, corresponding to nine positions on the map. They include TopLeft, MiddleCenter, and BottomRight (the default).

Now we have the information we need to set the progress bar’s alignment. To demonstrate, we will set the progress bar alignment to the MiddleCenter of the map. To do this, we add some JavaScript code into the .aspx page for our application, typically the Default.aspx page. Near the bottom of the page, just before the closing </body> tag, add a JavaScript function that will be called when the page starts up. We can do this using the ASP.NET AJAX add_init function, which guarantees our function will run after the page completely loads. We pass to add_init the name of the function (setupProgressIndicator) that will be called on startup.

In the setupProgressIndicator function, we get a reference to the JavaScript component for the map, using the ASP.NET AJAX $find function. Then we set the progress bar alignment using the ContentAlignment value we want. The resulting code would go into your .aspx page, just before the closing </body> tag.

<script language="javascript" type="text/javascript">

// Have our custom function called when the user starts the application

function setupProgressIndicator() {

// Get the JavaScript map component
var map = $find('Map1');

// Set the location of the progress bar


Custom progress events

If you want to do more than set the alignment of the built-in progress bar, you can have custom code that runs when the map is loading images or tiles. You can use this approach to supplement the standard progress bar, or completely replace it with your own indicator. The map’s onProgress event enables us to run custom code. This and other map events are discussed in the Web ADF JavaScript Library section of the Developer Help. In this section, we will use this event to display the number of pending tiles on the progress bar. Later we will replace the progress bar with a custom indicator.

To show custom content when the map is loading images or tiles, we can use the onProgress event on the map client. This event is new at 9.3, and replaces multiple events that were used at 9.2 (onRequestsPending, etc.). When a function is attached to the onProgress event, it gets called each time the number of pending tiles changes. The custom function takes two arguments: the sender of the event, which is the map component; and the number of pending tiles. You can check the second argument to determine what to display to the user.

In the code sample below, we attach to the onProgress event by calling the map’s add_onProgress method. We pass it the function to be called when the number of pending tiles changes. In this function, showProgress, we examine the number of tiles as given in the args value. If the number is greater than zero, then we display the number of tiles in the browser’s status bar. If the number of tiles is zero (i.e., the map is finished loading tiles), then we hide the status bar message.

<script language="javascript" type="text/javascript">


function setupProgressIndicator() {

// Get the JavaScript map component
var map = $find('Map1');

// Set the location of the progress bar

// Add the custom progress function

// Custom progress function
// sender = map component, args = number of pending tiles
function showProgress(sender, args) {

// If tiles pending, display number in status bar
if (args > 0) {
window.status = "Pending map tiles: " + args.toString();
} else {
// All tiles loaded - hide status bar message
window.status = "";


Custom progress indicator

Finally, we look at how to completely replace the existing progress bar with a custom indicator. The steps are: (1) turn the standard progress bar off; (2) create our custom progress indicator; and (3) turn on and off our custom indicator using the onProgress event described earlier.

The best way to turn off the standard progress bar is to use the EnableProgressBar property on the ASP.NET Web control. You can set this in Visual Studio by switching the page to Design view, selecting the Map control, and setting EnableProgressBar to False in the Properties window. Or, you can scroll up in the Source view to the Map control and add the EnableProgressBar property there, like this:

<esri:Map ID="Map1" runat="server" Height="423px"  
MapResourceManager="MapResourceManager1" Width="554px"
EnableProgressBar="False" >

Second, we’ll create our custom progress indicator. This indicator can be as simple or complex as you wish. An animated GIF image is common, but you could write a custom indicator similar to the built-in progress bar, which uses multiple divs and styles to create an animation. For our example, we will use the ajax-loader-circle.gif image, which is included with several samples in the Web ADF developer samples, such as ArcGIS_Spatial_Query_SOE. We copied this gif into our Web application folder and added it into the .aspx page within a div. We set the style position of the div so that it is approximately centered on the map control. Of course you could add code to dynamically position the progress indicator over the map, such as by getting the map’s offsetLeft/offsetTop and setting the progress indicator’s style position (see the zip file for the sample for an example of this).

<div id="progressImageDiv" style="position:absolute;left:250px;top:320px;">
<img id="progressImg" src="ajax-loader-circle.gif" alt="Loading..." />

Third, to show and hide our custom progress indicator, we use the same approach with the onProgress event as above. If tiles are pending (args > 0), then we show the progress indicator; otherwise we hide the indicator. To show/hide the indicator, we could add code to get the indicator div and set its style.display property. But the Web ADF has built-in functions to show or hide a div section, which we will use instead: showLayer and hideLayer. The complete code, with both the custom progress indicator and status bar text, is shown below.

<div id="progressImageDiv" style="position:absolute;left:250px;top:320px;">
<img id="progressImg" src="ajax-loader-circle.gif" alt="Loading..." />

<script language="javascript" type="text/javascript">


function setupProgressIndicator() {

// Get the JavaScript map component
var map = $find('Map1');

// Add the custom progress function

// Custom progress function
// sender = map component, args = number of pending tiles
function showProgress(sender, args) {

var progressImageDiv = $get("progressImageDiv");

// If tiles pending, display progress indicator and tile number in status bar
if (args > 0) {
window.status = "Pending map tiles: " + args.toString();
progressImageDiv.style.display = "block";
} else {
// All tiles loaded - hide progress indicator and status bar message
window.status = "";
progressImageDiv.style.display = "none";


The code produces something like this when the progress indicator is displaying:

Customized progress bar

The complete code for this sample is available in this zip file. The code includes a few enhancements to the code above, such as an option to recenter the custom progress indicator if the map is resized, which may occur with the Web Mapping Application template. You can also try out this sample with the link provided.


We have seen how to customize the progress indicator for the map, both by setting properties of the standard progress bar and by adding our own custom event handling to display information or even a custom progress image. The map has other events and properties that you could use for performing custom handling on the client. See the Web ADF JavaScript Library reference in the Developer Help for further information.

Try the example application

Get the code

Contributed by Bryan Baker of the ArcGIS Server .NET software development team.

Posted in Services | Tagged , , , , | 5 Comments

Creating a DHTML scale bar with the .NET Web ADF

At the 9.3 release, the .Net Web ADF’s JavaScript library exposes a lot of logic to the client side, allowing you to create a more responsive UI without the need for making calls back to the server. You can get the Web ADF JavaScript library help on the ArcGIS Server Resource Center. This post will show you how to use the JavaScript library to create a pure client-side scale bar using the Microsoft AJAX Client Library patterns.

The Web ADF’s scale bar is generated by the primary map resource using a dynamically generated image. Since the scale potentially can change on every pan, the scale bar image has to be updated frequently, adding additional overhead to the server requests for rendering and fetching these images. Furthermore, if the primary map resource doesn’t support rendering a scale bar, no scale bar is available at all. ArcIMS ArcMap Services don’t support rendering a scale bar. The approach described in this post is the recommended pattern for displaying a scale bar for ArcIMS ArcMap Services.

We can scale a standard <div> box dynamically on the client using JavaScript, and completely eliminate the extra callback, because the map control allows you to listen for and get the current extent of the map. We simply add a handler to the Map’s ‘extentChanged’ event. To do this, we first get a reference to the map object using the $find method parsing in the ClientID of the map as a parameter:

var map = $find('Map1');

Next we add the handler which will be executed every time the extent of the map has changed:


However, we need to ensure that this handler is not created until the Map has been instantiated on the client. The Microsoft AJAX framework also exposes several life-cycle events, for listening when the page has been fully loaded. So we wrap the above code in an application init event handler and place it right before the </body> tag. Notice how the pattern for adding event handlers is similar to adding handlers to the map. The full example could look something like this:

<script type="text/javascript" language="javascript" >
	function myExtentChangedHandler(sender, args) {
		   alert(sender.get_id() + ' changed extent to: ' + args.current.toString());
	Sys.Application.add_init(function() {
		   var map = $find('Map1');

Every time you pan the map, you will see a popup window like this:

Message that appears on pan

This gives us the framework for creating a simple scale bar. The next step is to place a box on the page that we can use as a scale bar by changing the width as the pixel size changes.

<div><div id="scalebar" style="background-color: #000000; width: 200px; height: 10px;"></div><span id="scalebarText">100 units</span></div>

<script type="text/javascript" language="javascript" >

function resizeScalebar(sender, args) { //resize event handler
  var pixelSize = sender.get_pixelSize(); //Gets the size on one pixel in map units
  var scalebarWidthInMapUnits = 0.001; //The initial size of the scalebar in map units
  //width in pixels of a scalebar with the current
  //scalebarWidthInMapUnits value and map's pixelsize
  var width = scalebarWidthInMapUnits / pixelSize;
  while(width<20) {
    //keep increasing scalebar size until we have a reasonable and visible size
    scalebarWidthInMapUnits *= 10;
    width = scalebarWidthInMapUnits / pixelSize;
  $get('scalebar').style.width = width + 'px';
  $get('scalebarText').innerHTML = scalebarWidthInMapUnits + ' units';
//Hook up the handlers during init
Sys.Application.add_init(function() {
  var map = $find('Map1');
  map.add_extentChanged(resizeScalebar); //fired when extent has changed
  map.add_extentChanging(resizeScalebar); //fired while map is zooming/panning
  resizeScalebar(map,null); //Force initial update of scalebar


This will generate a very simple scale bar that looks something like this:

Simple scale bar

It will automatically adjust its width between 20 and 200 px and show the corresponding width in map units next to it.

The next step is to componentize this into a real client side control that can easily be reused. The Microsoft AJAX Client Library already has a framework in place for creating controls that can inherit from each other and be extended.

A component requires a constructor, and a prototype. In the constructor you define the default properties of the control, and in the prototype you define the properties and methods, including initialize and dispose. Lastly you register the control and optionally the type you derive from, in this case Sys.UI.Control.


ADF.Samples.DhtmlScaleBar = function(element) {
  ADF.Samples.DhtmlScaleBar.initializeBase(this, [element]);
  this._map = null; //Reference to the map
  this._minWidth = 20; //minimum width of the bar before changing units
ADF.Samples.DhtmlScaleBar.prototype = {
  initialize : function () {
    ADF.Samples.DhtmlScaleBar.callBaseMethod(this, 'initialize'); //Call base initialize
    if(this._map === null) { throw Error.argumentNull('map'); }
    this._extentChangedHandler = Function.createDelegate(this,this._updateScalebar);
    //Add listener for when the map is animating its extent
    //Add listener for when the map has changed its extent
    this._createBars(); // Creates the bar and text elements
    this._updateScalebar(this._map); //Update the scalebar now
  dispose : function() {
    ADF.Samples.DhtmlScaleBar.callBaseMethod(this, 'dispose');
    if(this._extentChangedHandler && this._map) {
    if(this._scaleBar) { this.get_element().removeNode(this._scaleBar);}
    if(this._scaleBarText) { this.get_element().removeNode(this._scaleBarText); }
    this._extentChangedHandler = null;
    this._map = null;
    this._scaleBar = null;
    this._scaleBarText = null;
  _createBars : function() { //Create the bar and text
    this._scaleBar = document.createElement('div');
    this._scaleBar.style.backgroundColor = '#000000';
    this._scaleBar.style.float = 'left';
    this._scaleBarText = document.createElement('span');
    this._scaleBarText.style.float = 'left';
  _updateScalebar : function(sender,args) {
    var pixelSize = sender.get_pixelSize(); //Gets the size of one pixel in map units
    var scalebarWidthInMapUnits = 0.001; //The initial size of the scalebar in map units
    //width in pixels of a scalebar with the current
    //scalebarWidthInMapUnits value and map's pixelsize
    var width = scalebarWidthInMapUnits / pixelSize;
    while(width<this._minWidth) {
      //keep increasing scalebar size until we have a reasonable and visible size
      scalebarWidthInMapUnits *= 10;
      width = scalebarWidthInMapUnits / pixelSize;
    this._scaleBar.style.width = width + 'px';
    this._scaleBarText.innerHTML = scalebarWidthInMapUnits + ' units';
  get_map : function() { return this._map; },
  set_map : function(value) { this._map = value; },
  get_minWidth : function() { return this._minWidth; },
  set_minWidth : function(value) { this._minWidth = value; }
//Register class:
ADF.Samples.DhtmlScaleBar.registerClass('ADF.Samples.DhtmlScaleBar', Sys.UI.Control);

If we add this script to the page, we can now simply create a scale bar using the $create method. The parameters are:

  • Type
  • Object list of properties
  • Object list of event handlers (we don’t have any events here so we use null)
  • Object list of component properties. In our case the map – this ensures that the scale bar is not initialized until the map has been initialized.


<div id="bar"></div>
<script type="text/javascript" language="javascript" >
Sys.Application.add_init(function() {

At our code gallery you can download the scale bar control. It has been expanded to look a little better than just a black bar, and it also has a server-side web control that renders the above script to the page. It will analyze the primary map resource and fetch the unit of the map, and allow you to convert it to any display unit you would like on the fly. Finally, there’s some extra logic which will get the scale bar to attempt to use some nice rounded intervals. The final result will look something like below, and will even resize while the zoom animation plays or while you pan toward the poles where the scale changes. You can style the control using the web control style properties like background color, border, font-size etc.

Final scale bar

Click here to get the source code from the Code Gallery

Click here to view a demo of the scale bar

Contributed by Morten Nielsen of the ArcGIS Server .NET software development team

Posted in Services | Tagged , , , | 1 Comment

Using Gears in a .NET Web ADF application

HTML 5 introduces offline storage support which allows the browser to serve up web pages and other data locally without having to access the Internet. Some newer browser versions (Safari 3.1/Firefox 3) offer built-in support for offline storage while other browsers can use Gears to enable local storage and access of code and data without Internet access. Originally released by Google, Gears is an open-source browser plug-in that supports Internet Explorer, Firefox and Safari. A growing number of online service providers offer web applications that leverage Gears to support offline functionality using a local data store, The list of providers and applications includes Google Docs, Google Reader, Zoho, Remember The Milk, and others.

In a web mapping application, leveraging offline storage may enable you to improve application performance. In almost every case, utilizing a local client data store is faster than retrieving data from a remote server. There are, however, limitations and synchronization issues which we’ll highlight later in this post.

The 9.3 .Net Web ADF JavaScript Library provides an extensibility point for leveraging offline storage capabilities with components such as the Map control.

The content of a basic web application can be categorized into two distinct areas:

  1. Application Framework – includes the web page hosting the controls, client side code (JavaScript runtime) and supporting media such as images and style sheets
  2. Data – information passed to and from the server and the client. This includes image tiles from a cached map service that are stored on the client.

In order to use an application offline, both the framework and relevant data need to be cached and available on the client.

The remainder of this post presents an overview of the steps involved in leveraging offline capabilities with a web application that contains Web ADF controls and accesses ArcGIS Server cached services. There are two important points to consider before proceeding:

  1. The web application needs a programmatic framework on the client to utilize offline storage. The Dojo Toolkit library offers a nice abstraction layer for browsers which do and do not have built-in support for offline storage. For example, when you access a web application in Firefox 3 the toolkit will use the native storage capabilities of the browser. However, if you access the same web application using Firefox 2 the toolkit will use the Gears plug-in (if installed) or degrade gracefully.
  2. Offline access to data is limited. For example, only data provided by the host server (e.g. URL from the same source as the application) can be cached locally. In the context of a web mapping application, you would be unable to cache a local copy of image tiles from a remote cached map service, such as ArcGIS Online. In order to work around this limitation you can use a server proxy. This workaround is discussed below.


Use the following steps to leverage offline storage with Web ADF controls and ArcGIS Server map services:

  1. Add a Map and a MapResourceManager control to the web page. Add one or more cached map service resources. Optionally add buddy controls such as the ZoomLevel, Navigation, Toolbar to the web page.
  2. Add the Dojo Toolkit script library to your website and add a script reference to dojo.js in your web page.

    <script type="text/javascript" src="javascript/dojotoolkit/dojo/dojo.js"></script>
  3. The Web ADF JavaScript Library defines a set of layer types which can be used to access map images. One such layer type is AdfTileDirectAccess which enables the client browser to access pre-generated, cached map tiles via a URL. Use client-side JavaScript to override the getTileUrl method on the AdfTileDirectAccess component, to change how it accesses cached map tiles. Add the following script block at the bottom of the page, after the closing form tag (</form>):

    function getTileUrlAndCacheLocally (column,row,level,handler) {            
    var func = this.get_tileUrlGeneratorFunction();
    var serverUrl = this.get_serverUrl();
    var url = func(level, column, row, serverUrl);
    try {
    ESRI.ADF.Layers.AdfTileDirectAccess.prototype.getTileUrl = getTileUrlAndCacheLocally;

    In a nutshell, the above code intercepts a call to a function that generates a URL to a map image tile, caches the resource locally using the Dojo Toolkit’s offline API, then delegates to the handler.

  4. Capture all files of the Application Framework into local storage when the application loads. To achieve this, define a list of necessary files and add all scripts and images on the page to the list. Then use the Dojo Toolkit to store these files for offline access.

    var filesToCapture = [ location.pathname,   'images/backward_disabled.png', 'images/forward_disabled.png' ];

    var scripts = document.getElementsByTagName("script");
    for(var i=0; i < scripts.length; i++) {
    if(scripts[i].src.length > 0 && scripts[i].src != '//:') {
    Array.add(filesToCapture, scripts[i].src);
    var images = document.getElementsByTagName("img");
    for(var j=0; j < images.length; j++) {
    Array.add(filesToCapture, images[j].src);

    dojo.forEach(filesToCapture, function(item) {

    Note: Since the Dojo Toolkit uses a dynamic loader for downloading scripts on demand, scripts that may be loaded while using the web application will need to be cached locally as well. This can be achieved by adding the known paths/URL to the filesToCapture variable.

Thus far the JavaScript customizations to client-side code present an offline solution that works for caching resources (data, scripts, etc.) from the same originating server. If map image tiles reside on a remote server, a server proxy should be used. As the name suggests, the purpose of the server proxy (tileserverproxy.ashx) is to intercept requests to remote servers from the client, change the request to the same server on which the web application resides, and return map tile content.

The handler would receive a set of input request parameters (server URL, tile level, column and row) and then forms a URL for the map tile based on ArcGIS Server tiling conventions. It then issues a web request for the tile and streams it back to the browser.

A set of changes are also required in JavaScript on the client. A check is made to see if the tile URL being requested is from the originating server or not. If the URL is from a different server, the request is passed to the tileserverproxy instead. In essence, this changes how the getTileUrl method operates on an AdfTileDirectAccess component.

if(isSameOrigin(serverUrl)) {
url = func(level, column, row, serverUrl, imgFormat);
else {
url = getServerProxyUrl(level, column, row, imgFormat, serverUrl);


After connecting to the website and browsing some tiles by navigating the map (zoom/pan), set your browser to work offline. In Internet Explorer or Firefox, you do this by navigating to File > Work Offline. (Note that if you disconnect from the network, you must still explicitly set your browser to work offline.) Now try accessing the same web page. You will notice a fully functioning page and you’ll be able to navigate to tiles that are already present in your local cache.


Any time there are multiple copies of data, synchronization issues will exist. In this case, the client machine has a local copy of the application and map tiles. This makes pushing updates to the client more difficult since the browser works with its local copy and does not query the online site for updates. If the application or map tiles do not change often, this may not pose a problem. However, if you regularly update the application functionality or map tiles, you will likely need to devise an update solution.

Some options include:

  1. Periodic polling to check for updates.
  2. Notify the client to clear the cache when updates are available.
  3. Add UI elements to explicitly clear the local cache


Contributed by Nikhil Shampur of the ArcGIS Server .Net software development team

Posted in Services | Tagged , , , | Leave a comment

Creating an ArcGIS Server Java custom security store

ArcGIS Server at 9.3 introduces Role Based Access Control (RBAC) to secure
capabilities published by the GIS Server. ArcGIS Server comes with a default
embedded database system to maintain all user and role information. ArcGIS
Server for Java provides the ability to customize the security system to manage
user and roles that exist in other Relational Databases or Directory Services
(LDAP or Active Directory) as well as an API to extend the security system.
Extending the system through the Principle Store API allows you to build a
custom Java class which reads and writes security parameters to and from a
custom data store. In this example we will create a Java class which reads and
writes users and roles to and from an XML file, from which your ArcGIS security
mechanism will consume the user and role information. There are four steps
involved in this process which we will step you through.

  1. Create a custom security store class which implements SecurityStore. The SecurityStore
    interface is located in the com.esri.adf.security.store package inside
    the arcgis_securityapi.jar file. It includes methods to work with users and
    roles in your custom RBAC as well as the ability to test your connection to the
    data store. We will use the Eclipse developer environment to stub out our class
    with the appropriate methods. From within Eclipse, create a package called demo.

    Demo package

    Inside the demo package, create a class called FileStore which
    inherits the interface com.esri.adf.security.store.SecurityStore. Be
    sure the ‘Inherited abstract methods’ box is checked.

    New class FileStore

    This will stub out the appropriate methods for our new class of which we can
    implement to support our custom security store. Let’s discuss some of the
    methods that we implemented in the full source included in the
    Code Gallery

    init(): The init method initializes the SecurityStore implementation.
    This is where we work with the file store by first checking to see if the file
    exists, creating it if it does not, and then getting any users and roles which
    already exist.

    addUser(), deleteUser(), modifyUser(), getUser(), getAllUsers(): These
    methods take in an ArcGISSecurityUser class parameter and allows us to
    manipulate these users within the security store.

    addRole() addUsersToRoll(), deleteRole(), deleteAllRolesForUsers(),
    deleteAllUsersForRolls(), deleteRolesFromUser(), deleteUsersFromRole(),
    modifyRole(), getRole(), getAllRolls(), getRolesForUser(), getUsersForRole()
    These methods allow us to manipulate the roles, and users assigned to specific
    roles, within our security store.

    validateUser(): Here we can check the users credentials from the security
    store. The method returns a Boolean value of true when the user credentials
    match the information in the security store.

    We also created two helper methods:

    createFileStore(): This method gets called in the init method if the file
    store does not exist. It will then create the initial file store as an xml file
    and create the required elements.

    updateFileStore(): This methods gets called from within our add/delete
    user/role methods we inherited and allows us to write a document memory object
    back to our file store.

    Please implement the full source code from the
    class provided in the ArcGIS code gallery.

  2. Create a custom security.xml file to configure the custom SecurityStore implementation
    we created in step 1. This file is located in the
    ‘%ARCGISHOME%javamanagerservicelib’ folder and by default contains the
    information for the internal data store.

    To use our custom implementation, we need to replace the required connection

    parameter and add a user defined parameter <FS_FilePath> which points to
    the file based XML file we are using to store our data store:

    <entry key="UserStore">demo.FileStore</entry>		 
    <entry key="FS_FilePath">filestore.xml</entry>

    We have included a simplified
    file in the ArcGIS code gallery which assumes security has
    not already been configured and enabled on your GIS server.

  3. Create a jar file with our custom SecurityStore implementation and hot
    deploy it to the ‘%ARCGISHOME%javamanagerconfigsecuritylib’ directory.
    This is easy to do from within Eclipse. (Alternatively you can create a jar
    from the command line with the
    Java jar tool
    .) Return back to our class in Eclipse, right click on the
    class file, and select ‘Export’ from the menu:

    Export option on the context menu

    Select Java->Jar file from the Export wizard:

    Export wizard

    Ensure that only the classes you want to export are selected, in this example
    the demo.FileStore class:

    Defining resources for export

    Select an appropriate export destination and click Finish to accept the
    remaining defaults and generate a jar file for deployment. Copy the resulting
    jar file containing the custom SecurityStore implementation to the
    ‘%ARCGISHOME%javamanagerconfigsecuritylib’ directory.

  4. Once our custom SecurityStore implementation jar file is in place and
    our security.xml file is properly configured, we are ready to begin using our
    custom security implementation. To reload the security configuration used in
    our custom SecurityStore implementation, restart the ArcGIS Server Manager

Now let’s test our custom security configuration through Manager. ArcGIS Server
9.3 includes a new ‘Security’ menu where we can configure and setup our custom
Principle Store to manage users and roles. The ‘Roles link, under the
‘Security’ menu, lists all the Web GIS Roles currently configured on the
system. To add a new role, click the ‘Add Role’ button, fill in the ‘Rolename’,
and optionally a ‘Description’ for the new role:

Adding a role in Manager

Now that we have a role defined, let’s add a new user by clicking the ‘Users’
link under the ‘Security’ menu. To add a new Web GIS User, click the ‘Add User’
button and fill in the required fields and add the newly created ‘Editor’ role
defined in the previous step.

Adding a user in Manager

Now let’s take a look at the XML data store that our custom Security Store uses
to maintain users and roles to confirm that our custom implementation is
working as expected. Navigate your operating systems file browser to the
‘%ARCGISHOME%javamanagerservicelib’ directory and open the newly created
filestore.xml in your favorite text/xml editor. The contents should look
similar to the following:

<?xml version="1.0" encoding="UTF-8"?>
<user name="spatial" password="cdb36c370b737074c455bf1ee75a2f56"/>
<role description="Allows write access" name="Editor"/>

This file will now manage your users and roles as you continue to configure them
through Manager.


Custom Security Store source code for this article


the Principal Store API

API documentation

Contributed by Dan O’Neill of the ArcGIS Server Java software development team

Posted in Services | Tagged , , , , | 1 Comment

Working with custom renderers in the .NET Web ADF

Custom 2.5D renderer for Washington DCThe Web ADF allows you to go beyond the default symbols for graphics layers by creating custom renderers. This post will show how to create custom renderers and apply them to FeatureGraphicsLayers using the IRenderer interface. The IRenderer interface allows you to take full control of how a specific feature is rendered on the map by using .NET’s System.Drawing classes.

The IRenderer interface consists of five methods, but if you can do without support for the Table of Contents (TOC) control, only one of them is really needed, and you can use some very simple implementations of the remaining four methods.

The five methods are:

  • GenerateSwatches – Generates swatches for this renderer for display in a table of contents
  • GetAllSymbols – Returns all FeatureSymbols used by this object, if any
  • GetMaxSwatchDimensions – Gets the maximum dimensions of the swatches generated by this renderer
  • Clone – Returns a clone of this renderer
  • Render – Draws the specified geometry to the specified graphics

For the simplest renderer, the following is sufficient for the first four methods:

public SwatchCollection GenerateSwatches(SwatchInfo swatchInfo, string fileName, string minScale, string maxScale)
return new SwatchCollection();
public void GetAllSymbols(List< FeatureSymbol> symbols) { }
public void GetMaxSwatchDimensions(ref int width, ref int height) { }
public object Clone() { return this.MemberwiseClone(); }

This implementation will not support swatches, but we will later get back to how to also support this.

The main method we need to look at is “Render”. As input you get three parameters: The row with attributes you are rendering, a reference to the graphics instance that you should render to, and the name of the column in the datarow that contains the geometry data. The geometry data that is parsed in here is not in map units, but has already been converted to screen coordinates, so you don’t have to worry about translating your feature to the screen.

So the very first thing we do in our renderer is to fetch the geometry that we want to render. In most cases the first few lines of a renderer will look something like this:

public override void Render(DataRow row, Graphics graphics, DataColumn geometryColumn)
if (row == null || graphics == null || geometryColumn == null)
Geometry geometry = row[geometryColumn] as Geometry;

In this first part, we will only support rendering points, so the next stop would be to limit by geometry type:

if (geometry == null || !geometry is ESRI.ArcGIS.ADF.Web.Geometry.Point)

Next we can use System.Drawing classes to draw an image at the point, which completes our very simple point renderer:

ESRI.ArcGIS.ADF.Web.Geometry.Point p = geometry as ESRI.ArcGIS.ADF.Web.Geometry.Point;
using(System.Drawing.Image img = System.Drawing.Image.FromFile(@"C:inetpubwwwrootmyAppimagesicon.png"))

Here’s the complete renderer implementation:

using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.ADF.Web.Geometry;
using ESRI.ArcGIS.ADF.Web.Display.Swatch;
using ESRI.ArcGIS.ADF.Web.Display.Symbol;

namespace WebADF.Datasources.Renderers
public class SimplePointRenderer : ESRI.ArcGIS.ADF.Web.Display.Renderer.IRenderer
public SwatchCollection GenerateSwatches(SwatchInfo swatchInfo, string fileName,
string minScale, string maxScale)
return new SwatchCollection();
public void GetAllSymbols(List<FeatureSymbol> symbols) { }

public void GetMaxSwatchDimensions(ref int width, ref int height) { }

public void Render(System.Data.DataRow row, System.Drawing.Graphics graphics,
System.Data.DataColumn geometryColumn)
if (row == null || graphics == null || geometryColumn == null)
Geometry geometry = row[geometryColumn] as Geometry;
if (geometry == null || !(geometry is ESRI.ArcGIS.ADF.Web.Geometry.Point))

ESRI.ArcGIS.ADF.Web.Geometry.Point p = geometry as ESRI.ArcGIS.ADF.Web.Geometry.Point;
using (System.Drawing.Image img = System.Drawing.Image.FromFile(ImageIcon))
graphics.DrawImageUnscaled(img, Convert.ToInt32(p.X – img.Width/2),
Convert.ToInt32(p.Y) - img.Height/2);

public object Clone() { return this.MemberwiseClone(); }

private string imageIcon = @"C:inetpubwwwrootmyAppimagesicon.png";

public string ImageIcon
get { return imageIcon; }
set { imageIcon = value; }

If you create a graphics dataset, you can now apply this renderer to your individual FeatureGraphicsLayers. You can easily extend it to use any of the existing attributes in the DataRow to determine which image icon to use, making it a simple thematic map renderer.

Points are simple to render, but it gets slightly trickier with lines and polygons. We will have to convert these to a System.Drawing.GraphicsPath instance that the graphics object knows how to render. This is fairly straightforward, but to save you the trouble here are the methods needed to perform this conversion:

public static GraphicsPath PolygonToPath(Polygon polygon)
GraphicsPath path = new GraphicsPath();
foreach (Ring p in polygon.Rings)
foreach (Hole ring in p.Holes)
return path;

public static GraphicsPath PolylineToPath(Polyline polyline)
GraphicsPath path = new GraphicsPath();
foreach (Path line in polyline.Paths)
return path;

private static Point[] pointCollectionToPointArray(PointCollection points)
Point[] pointArr = new Point[points.Count];
for (int i = 0; i < points.Count; i++)
pointArr[i] = new Point(Convert.ToInt32(points[i].X), Convert.ToInt32(points[i].Y));
return pointArr;

This is essentially all we need to make a renderer supporting all geometry types. Example:

using (GraphicsPath path = PolygonToPath(polygon)); //or PolylinetoPath for polylines
using (Pen pen = new Pen(System.Drawing.Colors.Black,1))
graphics.DrawPath(pen, path);

If you want to show the feature with a fill, remember to also use FillPath prior to drawing the outline as shown above:

using (SolidBrush brush = new SolidBrush(System.Drawing.Colors.Red))
graphics.FillPath(brush, path);

Using the principles described in this article, I’ve created a 2.5D renderer that can extrude polygons and lines based on a numeric attribute. The effect is very much like what you might have seen Google Maps using to show simple building outlines in metropolitan areas. You can indeed use it for this, or you can choose to extrude polygons based on for instance population density or whatever you want to show. I won’t go through the details of the code here, but most of the code is used for building a 3D-like mesh of a polygon and figuring out how to shade it depending on the direction of an imaginary light-source.

Adding support for legends

As mentioned in the beginning, we skipped implementing support for the table of contents control, and in many use cases of custom renderers (like displaying results) this is not needed. However adding support for TOC is fairly straightforward.

We can reuse existing functionality in the ADF to render our symbols. Let’s say we have a point layer using three image symbols, 1.gif, 2.gif and 3.gif. We use the RasterMarkerSymbol and the SwatchUtility to render our swatches.

SwatchCollection GenerateSwatches(SwatchInfo swatchInfo, string fileName, string minScale, string maxScale) {
swatches = new SwatchCollection(); SwatchUtility
swatchUtil = new SwatchUtility(swatchInfo); for(int
i= 1;i<=3;i++) {
CartoImage img = swatchUtil.DrawNewSwatch(new RasterMarkerSymbol(
Server.MapPath(string.Format("~/images/{0}.gif", i))), null);
swatches.Add(new Swatch(img, "Marker #" + i.ToString(), null, null));
return swatches;

This will return a collection of 3 images to use for the legend. When adding a TOC to the page, you’ll see something like the following:

Swatch images in TOC

Get the Custom Renderer sample from the Code Gallery

Contributed by Morten Nielsen of the ArcGIS Server .NET software development team.

Posted in Services | Tagged , , | 2 Comments

ArcGIS Server 9.3 Nationwide Seminar Series occurring now

ESRI has been working on two, half-day
ArcGIS Server 9.3 Seminars
. These seminars started September 23rd and
are taking place through November within the U.S. This is a great opportunity
to see how to implement ArcGIS Server to its fullest capabilities.

The first seminar, which takes place during the morning, is “Tips and Tricks”.
It was derived by gathering the most common questions people have when
implementing ArcGIS Server and best practices. There are three main sections:
configuration and management, caching, and geoprocessing. This seminar provides
useful tips for configuring ArcGIS Server and understanding architecture, how
you can set up caching strategies and workflows for high performing web
applications and how to author and publish geoprocessing services for advanced
analysis over the web.

The second seminar, which takes place during the afternoon, is titled “Creating
Mashups Using the ArcGIS API for JavaScript”. The ArcGIS Server API for
JavaScript is new at 9.3 and provides html and JavaScript developers a quick
path for making great web mapping applications. This seminar covers the basics
and getting started with the API for JavaScript. In addition to creating
mashups, discussion on query tasks, geoprocessing, geocoding and other topics
are covered so you can see how GIS analysis can be done over this easy to use
API. You can take a quick glance of the demos that will be discussed by
downloading the sample code from the ArcGIS JavaScript API
Code Gallery

Both seminars provide a great resource for maximizing the potential of ArcGIS
Server. The seminars also provide workbooks to attendees so they can revisit
the useful tips back in the office. Sign up online to attend an
ArcGIS Server 9.3 Seminar

The ESRI technical staff hope to see you at a seminar in a city near you!

Contributed by Jeremiah Lindemann, co-designer of the “Creating Mashups Using the
ArcGIS API for JavaScript” seminar.

Posted in Services | Tagged , , , , , , | 2 Comments