Esri / arcgis-toolkit-sl-wpf

Toolkit for the ArcGIS Runtime SDK for WPF and ArcGIS API for Silverlight
Microsoft Public License
23 stars 29 forks source link

WmtsLayer does not work with multi-dimensional WMTS Services #2

Closed mfrehner closed 9 years ago

mfrehner commented 10 years ago

Hi WMTS Services can be multi-dimensional. "In case of multi-dimensional data, the service metadata can describe their multi-dimensionality and tiles can be requested at specific values in these dimensions. Examples of dimensions are Time, Elevation and Band. Optional parameters in WMTS service metadata declare available values along one or more dimensional axes applicable to a Layer. GetTile and GetFeatureInfo requests for that layer should include parameters specifying dimensional value(s)." (http://www.opengeospatial.org/standards/wmts).

Unfortunately, the following XAML would normaly cause a Silverlight application to send incorrect requests to the specific WMTS:

<UserControl x:Class="SilverlightWMTS3.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:esri="http://schemas.esri.com/arcgis/client/2009" >

<Grid x:Name="LayoutRoot" Background="White">
    <esri:Map WrapAround="True" x:Name="MyMap" >
        <esri:Map.Layers>
            <esri:WmtsLayer 
             Url="http://wmts.geo.admin.ch" 
             ServiceMode="RESTful" 
             Layer="ch.swisstopo.pixelkarte-farbe"/>

        </esri:Map.Layers>
    </esri:Map>
</Grid>

The incorrect request being sent is: http://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/{Time}/21781/13/1/1.jpeg

In contrast, a correct request would be like the following: http://wmts.geo.admin.ch/1.0.0/ch.swisstopo.pixelkarte-farbe/default/20130903/21781/13/1/1.jpeg

The capabilities for the WMTS used above can be found here: http://wmts.geo.admin.ch/1.0.0/WMTSCapabilities.xml

My temporary fix that seems to work for my application is limited to the following line of code in Wmts.cs (Line 1730): url = url.Replace("{Time}", "20140106");

It would be great if somebody could fix this! Marcel

dbroux commented 10 years ago

@mfrehner Hi, I added a branch for WMTS multi dimensional support: https://github.com/Esri/arcgis-toolkit-sl-wpf/tree/dom/issue%232_multidimensional_wmts

If you set your layer without specifying any dimension, the default dimension value will be used automatically. Example that will use the default time (20140106):

    <esri:WmtsLayer ServiceMode="RESTFul" Url="http://wmts.geo.admin.ch" Layer="ch.swisstopo.pixelkarte-farbe" />

For using a specific dimension value, you can set it in XAML. For example:

    <esri:WmtsLayer ServiceMode="RESTFul" Url="http://wmts.geo.admin.ch" Layer="ch.swisstopo.pixelkarte-farbe"  >
            <esri:WmtsLayer.DimensionValues>
                <esri:WmtsDimensionValueCollection>
                    <esri:WmtsDimensionValue Identifier="Time" Value="20130903" />
                </esri:WmtsDimensionValueCollection>
            </esri:WmtsLayer.DimensionValues>
    </esri:WmtsLayer>

You can also set it by code after looking at all possible values advertised by the service: In XAML:

    <esri:WmtsLayer ServiceMode="RESTFul" Url="http://wmts.geo.admin.ch" Layer="ch.swisstopo.pixelkarte-farbe" Initialized="WmtsLayer_OnInitialized" />

In C#:

    private void WmtsLayer_OnInitialized(object sender, EventArgs e)
    {
        var wmtsLayer = sender as WmtsLayer;
        IEnumerable<WmtsLayer.WmtsLayerInfo> layerInfos = wmtsLayer.LayerInfos;
        WmtsLayer.WmtsLayerInfo layerInfo = layerInfos.FirstOrDefault(li => li.Identifier == wmtsLayer.Layer);
        if (layerInfo != null && layerInfo.DimensionInfos != null)
        {
            // Display infos about all dimensions
            foreach (var dimension in layerInfo.DimensionInfos)
            {
                string message = "Supports current keyword: " + dimension.SupportsCurrent;
                message += Environment.NewLine + "Default value: " + dimension.Default;
                message += Environment.NewLine + "Supported values: " + string.Join(", ", dimension.Values);
                MessageBox.Show(message, "Info about Dimension " + dimension.Identifier);
            }

            // Set last value of the first dimension for testing
            var dimension1 = layerInfo.DimensionInfos.First();
            var identifier = dimension1.Identifier;  // "Time"
            var value = dimension1.Values.Last();
            wmtsLayer.DimensionValues = new WmtsDimensionValueCollection { new WmtsDimensionValue(identifier, value) };
        }
    }

Result: wmtsdimensioninfo

Your service being protected, I am not able to display it, so it would be great if you had a chance to give a try and to let me know what you think about this implementation.

Thanks

Dominique

mfrehner commented 10 years ago

@dbroux Hi Dominique, I have tested your code successfully based on the three samples you provided. It works perfectly with the service from http://wmts.geo.admin.ch.

You mentioned that my service was protected. That is correct. Developers can, however, use it for testing by calling an application (Silverlight, JavaScript, Flex) through localhost. I.e. http://localhost/mySilverlightApp.

Thank you! I'll go ahead and close the issue.

Regards, Marcel

dotMorten commented 10 years ago

Reopening for possible future inclusion in the toolkit

stephmueller commented 10 years ago

Hi,

we've also tested the code from Dominique. Therewith our Silverlight is now capable of consuming these WMTS-Services (http://wmts.geo.admin.ch).

The crux is, that the service-consumation is only possible if the Silverlight application is started in one of the following browsers: Internet Explorer, Safari, Opera.

With Chrome or Firefox it does not work as before.

Which browser did you use for your tests? Do you have any guesses, why it might not work with Chrome and Firefox?

Many thanks and best regards Stephan

dbroux commented 10 years ago

Hi Stephan,

The new WMTS multidimentional support should not change anything about the access to the service depending on the browser.

My best bet is that your service is secured based on the request header referer. It turns out that Chrome and Firefox don't set any referer to the request sent from a SL app. That may explain your issue. I suggest you look with fiddler at requests sent to the server. That may give a clue.

stephmueller commented 10 years ago

Hi Dominique,

yes, exactly. The service is secured based on the request header referer. And fiddler shows that there is no referer in the get request in Firefox and Chrome. Too bad..

Thanks and regards, Stephan