How do I display the "root" layer in a WMS service using Runtime for .NET sdk? This layer does not have a name property in the xml capabilities so I'm not sure how to specify it for the Layers property on the WmsLayer. I can't seem to get any of the layers for this service to display.
I have tested with other services and they do seem to work when I specify the Layer's Name property, when every Layer in the WMS has a Name.
This is an example xml:
Only named layers hold data in a WMS service. Unnamed layers are only used for logical grouping and metadata. The WMS specification provides more details (section 7.2.4):
Conceptually, each Layer is a distinct entity. However, as a means of classifying and organizing layers, and as a means of reducing the size of the service metadata, a single parent Layer may enclose any number of additional layers, which may be hierarchically nested as desired.
<...>
If, and only if, a layer has a <Name>, then it is a map layer that can be requested by using that Name in the LAYERS parameter of a GetMap request. A Layer that contains a <Name> element is referred to as a “named layer” in this International Standard. If the layer has a Title but no Name, then that layer is only a category title for all the layers nested within. A server that advertises a Layer containing a Name element shall be able to accept that Name as the value of LAYERS argument in a GetMap request and return the corresponding map. A client shall not attempt to request a layer that has a Title but no Name.
Runtime's WMSLayer takes a flattened list of named layers to display, ordered bottom-to-top. For this particular service, displaying the "root" layer just means creating a WMSLayer from names "1", "2", "3", "5", "6", and "7".
For a more general solution, you can examine WMSLayerInfo and gather all of its named sublayers recursively, like so:
/// <summary>
/// Gathers a flat list of named layers for a given WMSLayerInfo, recursively.
/// </summary>
/// <param name="startingNode">Parent node to begin the search at.</param>
/// <param name="collector">A list to be populated with named WmsLayerInfo objects.</param>
void GetNamedLayers(WmsLayerInfo startingNode, List<WmsLayerInfo> collector)
{
if (!String.IsNullOrEmpty(startingNode.Name))
{
// Add this named layer to the list
collector.Add(startingNode);
}
else
{
// For category layers: look for named children
foreach (var sublayer in startingNode.LayerInfos)
{
GetNamedLayers(sublayer, collector);
}
}
}
Example usage:
// Load service metadata
var serviceUrl = new Uri("https://idpgis.ncep.noaa.gov/arcgis/services/NWS_Observations/NOHRSC_Snow_Analysis/MapServer/WmsServ...");
var service = new WmsService(serviceUrl);
await service.LoadAsync();
// Gather a list of all named WMSLayerInfos on this service
var list = new List<WmsLayerInfo>();
foreach (var layerInfo in service.ServiceInfo.LayerInfos)
{
GetNamedLayers(layerInfo, list);
}
// Create a layer containing ALL named sublayers from this service, in order of declaration.
// Note: First layer in the list will be drawn first (at the bottom),
// and last layer will be drawn last (on top of everything else).
var layer = new WmsLayer(list);
await layer.LoadAsync();