Getting WMTS content in Runtime 100.1

1294
4
10-11-2017 11:33 AM
PhilScovis
New Contributor III

I am trying to consume WMTS content using ArcGIS Runtime 100.1, and can't get it to work when the server only supports KVP service mode.  There was a way in 10.2 to set the service mode on the layer object, but I don't see it in the 100.1 API.  

For example, a public service with this problem is:

http://opencache.statkart.no/gatekeeper/gk/gk.open_wmts?Version=1.0.0&service=wmts&request=getcapabi...

My code is something like this:

   WmtsService service = new WmtsService(_TiledUri);
   await service.LoadAsync();
   WmtsServiceInfo info = service.ServiceInfo;
   _TiledLayer = new WmtsLayer(info.LayerInfos.ToArray()[0]);

   _MapView.Map.Basemap.BaseLayers.Add(_TiledLayer);

   _TiledLayer.IsVisible = true;
   await _TiledLayer.LoadAsync();

 

The service metadata loads just fine.  However the layer itself does not display.  In fact, there is no further web traffic to fetch the tiles at all.

The GetCapabilities call on the above uri contains:

<ows:Operation name="GetTile">
<ows:DCP>
    <ows:HTTP>
       <ows:Get xlink:href="http://opencache.statkart.no/gatekeeper/gk/gk.open_wmts?">
          <ows:Constraint name="GetEncoding">
             <ows:AllowedValues>
                <ows:Value>KVP</ows:Value>
             </ows:AllowedValues>
          </ows:Constraint>
       </ows:Get>
    </ows:HTTP>
</ows:DCP>
</ows:Operation>

I suspect that since RESTful is not supported, this is the problem.  10.2 would allow you to set the service mode on the layer, and would also automatically try KVP if RESTful failed.  How can a similar thing be done in 100.1?

Tags (1)
0 Kudos
4 Replies
MatveiStefarov
Esri Contributor

Thanks for taking time to report this! I was able to reproduce the issue with the information you provided.

The new API does not provide a way to switch between KVP and RESTful modes. However, the layer in your example fails to load for a different reason. You are running into a known compatibility issue in Runtime's new WMTS implementation: by default we're asking for image tiles in "image/jpg" format, but this particular server only recognizes "image/jpeg".

As a workaround, you can configure the layer to use a different supported tile format (such as PNG). Here is the modified code:

WmtsService service = new WmtsService(_TiledUri);
await service.LoadAsync();
WmtsServiceInfo info = service.ServiceInfo;
_TiledLayer = new WmtsLayer(info.LayerInfos.ToArray()[0], TileImageFormat.Png);
_MapView.Map.Basemap.BaseLayers.Add(_TiledLayer);
_TiledLayer.IsVisible = true;
await _TiledLayer.LoadAsync();

With this modification I was able to display the layer from your example:

We hope to fix this jpg-jpeg compatibility issue in a future update. But for now, I hope that this workaround solves your problem.

0 Kudos
PhilScovis
New Contributor III

Thanks for looking into this.  

I modified my code to explicitly request PNG from the layer, and still, no imagery.  Again, there is no web traffic even attempting to get the tiles in any format.  The GetCapabilities works just fine, but no subsequent requests are made when displaying the map control.

One thing I did notice was that the URI in the Service Info continues to have the REQUEST=GetCapabilities query on it.  I don't know if this is messing it up, but all of my working examples assume this query by default, and all of my non-working examples require it.  (Omitting it causes a 400 error from this particular server).

But I see that you have it working, with the lovely Norwegian coast displaying.  Are you putting in the full URI with the GetCapabilities into the WmtsService constructor?

0 Kudos
MatveiStefarov
Esri Contributor

Yes, WmtsService and WmtsLayer constructors expect a direct URL to the GetCapabilities resource.

Here's a little self-contained WPF program that loads and displays the Norwegian coast service: MiniWmtsProgram.cs (GitHub).

I thought of one more possible cause for your layer not displaying: spatial reference mismatch. You can detect these kinds of problems by listening for GeoView.LayerViewStateChanged Event — or simply by comparing Map.SpatialReference Property and Layer.SpatialReference Property.

When a Map is loaded, the spatial reference of its first Layer is used for the entire map (unless you've already specified a spatial reference in Map's constructor). When each Layer is loaded, it will try to match its Map's spatial reference. But if a Layer is loaded before it's associated with a Map — or if it's configured to use a service in a different spatial reference — then you'll end up with mismatched spatial references. WmtsLayer cannot reproject tiles on the fly, so it will fail to draw.

If it turns out that you do have mismatched spatial references, try calling LoadAsync() on your WmtsLayer after adding it to the Map — or using a TileMatrixSet with a different spatial reference. For example, that Norwegian service provides options for EPSG:4326 (WGS84/Plate Carrée), EPSG:3857 (WebMercator), and a few others.

Let me know if this helps!

0 Kudos
PhilScovis
New Contributor III

The problem was the spatial reference mismatch. Thank you for your help, Matvei!

0 Kudos