Select to view content in your preferred language

Refreshing WMS layers

2565
9
Jump to solution
08-29-2012 09:28 AM
CoreyAlix
Occasional Contributor
I'm really struggling with figuring out how to refresh a WMS layer.  There seems to be a few missing operations:


  • First, it would be nice if we could simply invoke refresh() to update the imagery.

  • Second, it would be nice if we could clone() a layer and add it to a map.  This would allow us to add a new layer like the one we want to refresh before removing the old layer.

  • Third, without the two options above it would be nice if we could manually override supressing the GetMap request when two layers resolve to the same url.


In the third case I'm adding two layers and only imagery for the first is attempted:

        function createWmsLayer()         {             var layer = new esri.layers.WMSLayer("http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer");             layer.setVisibleLayers([2]);             layer.setImageFormat("png");             return layer;         }          map.addLayer(createWmsLayer());         map.addLayer(createWmsLayer());


http activity:

http://localhost:55240/Proxy.ashx?http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?SERVICE=WMS&REQUEST=GetCapabilities  http://localhost:55240/Proxy.ashx?http://sampleserver1.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?SERVICE=WMS&REQUEST=GetCapabilities  http://sampleserver1a.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer?SERVICE=WMS&REQUEST=GetMap&FORMAT=image/png&TRANSPARENT=TRUE&STYLES=&VERSION=1.3.0&LAYERS=2&WIDTH=996&HEIGHT=630&CRS=EPSG:4326&BBOX=18.1801624186747,-125.192865,55.5544955813253,-66.105824


It seems the only way to force the imagery to reload is by adding another WMS layer exactly like the first but with a random query string value.  Is there a better way?

Related Post
http://gis.stackexchange.com/questions/32272/arcgis-javascript-api-refresh
0 Kudos
1 Solution

Accepted Solutions
__Rich_
Regular Contributor
The documentation for refresh() states, "Refreshes the map by making a new request to the server. In order to refresh the layer in this manner, setDisableClientCaching must be true. This ensures that map images are not cached on the client. (As of v1.2)" but setDisableClientCaching is defined for ArcGISDynamicMapServiceLayer and not DynamicMapServiceLayer.  Calling refresh on a WMSLayer instance has no affect.

Exactly.

So you will have to add the functionality for the WMS layer.

If you want to copy ESRI, then have a look at the requests sent for the AGS dynamic layer with the caching enabled/disabled - spot the difference.

You could also look at applying some cache control directives server-side if you can/want/need to.

View solution in original post

0 Kudos
9 Replies
JeffPace
MVP Alum
i was wondering if it is detecting a duplicate. 

Maybe you could get around by manually specifying an index

map.addLayer(layer, map.layerIds.length+1);
0 Kudos
__Rich_
Regular Contributor
i was wondering if it is detecting a duplicate.

No, it doesn't do anything like that.

If two requests have identical URIs then caching will kick-in, obviously subject to conditions e.g. caching is enabled, HTTP headers indicating that resources can/should be cached etc. etc.

The clue to how ESRI (from the client-side) force a refresh() to go back the server for other layer types is in the link I posted....and the OP has already identified the answer 😉  (although I'd be careful about the source for the value)
0 Kudos
CoreyAlix
Occasional Contributor
The documentation for refresh() states, "Refreshes the map by making a new request to the server. In order to refresh the layer in this manner, setDisableClientCaching must be true. This ensures that map images are not cached on the client. (As of v1.2)" but setDisableClientCaching is defined for ArcGISDynamicMapServiceLayer and not DynamicMapServiceLayer.  Calling refresh on a WMSLayer instance has no affect.
0 Kudos
__Rich_
Regular Contributor
The documentation for refresh() states, "Refreshes the map by making a new request to the server. In order to refresh the layer in this manner, setDisableClientCaching must be true. This ensures that map images are not cached on the client. (As of v1.2)" but setDisableClientCaching is defined for ArcGISDynamicMapServiceLayer and not DynamicMapServiceLayer.  Calling refresh on a WMSLayer instance has no affect.

Exactly.

So you will have to add the functionality for the WMS layer.

If you want to copy ESRI, then have a look at the requests sent for the AGS dynamic layer with the caching enabled/disabled - spot the difference.

You could also look at applying some cache control directives server-side if you can/want/need to.
0 Kudos
CoreyAlix
Occasional Contributor
Okay..I gave it a try and it certainly is better then adding/removing the layer from the map:

    layer = new esri.layers.WMSLayer("http://sampleserver1c.arcgisonline.com/ArcGIS/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/WMSServer", {
        visibleLayers: ['1', '2']
    });

    aspect.after ( layer, "onLoad", function () {
        var getImageUrl, tick;

        tick = 0;
        getImageUrl = layer.getImageUrl;
        layer.getImageUrl = function ( extent, width, height, callback )
        {
            var result = getImageUrl.call ( layer, extent, width, height, function (url) {
                callback.call ( layer, url + "&_c=" + tick++ );
            } );
            return result;
        };

        setInterval ( function () {
            layer.refresh ();
        }, 5000 );
    });
    
    map.addLayer(layer);


So...seems that this is the correct approach?
0 Kudos
__Rich_
Regular Contributor
Almost, I wouldn't go with the "tick" approach though, aside from slightly iffy scoping it has the potential not to be unique, don't forget that caches have the capacity to persist resources (and importantly use the URI that was used to retrieve them as the key) between sessions.

So a user visits your site, retrieves a map image with a &_c=1, then leaves the site.  They come back later (so your tick counter is reset to zero) then they retrieve the map image again same extent, same projection etc. and same &_c=1 i.e. the URI is the same as their last visit so the image is served from the cache, not the server - make sense?

ESRI use the number of milliseconds since the UNIX epoch or, in simple terms:

new Date().getTime()

or
new Date().valueOf()


https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date
0 Kudos
CoreyAlix
Occasional Contributor
Thanks geos_rfleet -- here's the result of your suggestions - not sure it's a generic solution but *should* work for layers derived from DynamicMapServiceLayer (does work for WMSLayer):

 function extendLayer(layer) {
     var getImageUrl;

     getImageUrl = layer.getImageUrl;

     layer.setDisableClientCaching = layer.setDisableClientCaching || function (disable) {
         layer.disableClientCaching = disable;
         if (disable) {
             layer.getImageUrl = function (extent, width, height, callback) {
                 var result = getImageUrl.call(layer, extent, width, height, function (url) {
                     callback.call ( layer, url + "&_c=" + ( new Date () ).getTime () );
                 });
                 return result;
             };
         }
         else {
             layer.getImageUrl = getImageUrl;
         }
     };
     return layer;
 }
AlessandroAssom
New Contributor II

Very useful! It works! I used your suggestion to refresh a service with both a wms from geoserver and a layer from arcgis server and everything is fine.

Thanks!

0 Kudos