ThinkGeo.com    |     Documentation    |     Premium Support

WmsOverlay DrawingExceptionMode Not Repercuted in WmsLayer

Hello,

I’m having issues with a uncaugth exception in WmsOverlay:

the exception is thrown :

==> in WmsLayer line 812

==> when the request “http://X.X.X.X:8080/geoserver/XXXXXX/wms?SERVICE=WMS&REQUEST=GetCapabilities” I get a 503 error:

‘System.Xml.XmlException’ in System.Private.Xml.dll
An unhandled exception of type ‘System.Xml.XmlException’ occurred in System.Private.Xml.dll
The ‘hr’ start tag on line 8 position 40 does not match the end tag of ‘body’. Line 9, position 3.

==> A simple code to imitate the exception:
using System.Xml;

Console.WriteLine("Hello, World!");
XmlDocument doc = new XmlDocument();
var test = """
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>Error 503 Service Unavailable</title>
    </head>
    <body><h2>HTTP ERROR 503</h2>
    <p>Problem accessing /geoserver/XXXXXX/wms. Reason:
    <pre>    Service Unavailable</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.4.18.v20190429</a><hr/>
    </body>
    </html>
    """;
doc.LoadXml(test);
Console.WriteLine(doc);

I get this exception while loading (RefreshAsync) the WmsOverlay;
In order not to catch it, I used the DrawingExceptionMode.DrawException, however, it is not repercuted to the WmsLayer (I check with debug, its exception is default).
It does not crash when I load it for the first time, but when I move in my view (zoom or go to a direction with the inherited buttons), it crashes.

Sadly, I cannot use the solution suggested in this post as i generate a plugin in another application, so I don’t have an hand on the main app.config…

How can I stop my Application from crashing when receiving this error ?

Hi Cecile,

Please check out the HowDoI sample here which shows you how to handle the exceptions:
samples/wpf/HowDoISample/Samples/Miscellaneous/HandleExceptions.xaml.cs · develop · ThinkGeo / Public / Desktop Maps · GitLab

You can see we need to set e.Handled = true in Overlay.ThrowingException event otherwise it will keep throwing that exception internally.

Let us know if you have any questions.

Thanks,
Ben

Thanks it works !

The main application no longer crashes.

Awesome! Let us know for more questions.

Hello,

Thought my app don’t crash anymore, my wmsLayer don’t seems to functions : i have a blank map.

Some context: I am upgrading ThinkGeo to the latest version.

In the former version, everythink worked fine, I could get my map from GeoServer displayed.
However it won’t work for the new version.

From What I could find, it seem to bug because I am using a group layer in geoserver. I found this post discussing about the subject but their are using a WmsRasterLayer.

(I checked, the url examples given on git are working fine)

Should I change my type of layer ? Or is there a way like in the linked post to solve the error ?

hi @Cecile_Morelle,

Could you let me know which version you upgraded from and to? And show me your code snippet or a sample if possible?

Regards,
Leo

previous version: ThinkGeo.MapSuite.WpfDesktopEdition & ThinkGeo.MapSuite.Core 7.0.0.0
newer version: ThinkGeo.Core & ThinkGeo.UI.Wpf 14.1.2

previous sample code:

/// <summary>
/// Initializes the background map.
/// </summary>
private void InitBackgroundMap()
{

    if (string.IsNullOrWhiteSpace(MapData.Url))
    {
        OpenStreetMapOverlay background = new OpenStreetMapOverlay
        {
            IsVisible = true,
            DrawingExceptionMode = DrawingExceptionMode.DrawException,

            // var cache = new FileBitmapTileCache(System.IO.Path.GetTempPath(), "MY-OSM");
            TileCache = new InMemoryBitmapTileCache()
        };

        MapControl.Overlays.Add("background", background);
        MapControl.Refresh(background);
    }
    else
    {
        var background = new LayerOverlay
        {
            TileHeight = 256,
            TileWidth = 256,
            LockLayerMode = LockLayerMode.DoNotLock,
            TransitionEffect = TransitionEffect.Stretch,

            IsVisible = true,
            DrawingExceptionMode = DrawingExceptionMode.DrawException
        };
        var cache = new InMemoryBitmapTileCache();
        background.TileCache = cache;


        WmsRasterLayer firstWmsLayer = new WmsRasterLayer(new Uri(MapData.Url))
        {
            Crs = string.Format("EPSG:{0}", MapData.SrsEPSG),
            OutputFormat = "image/png"
        };
        foreach (string layer in MapData.Layers)
        {
            firstWmsLayer.ActiveLayerNames.Add(layer);
        }
        background.Layers.Add("backlayer", firstWmsLayer);

        if (MapData.InitialExtend == null)
        {
            try
            {
                // try to get define initial extend from server.
                MapData.InitialExtend = firstWmsLayer.GetBoundingBox().ToMapRectangle();
            }
            catch (Exception error)
            {
                logger.Warn(error, "Fail to get BoudingBox");
            }

        }

        MapControl.Overlays.Add("background", background);
        MapControl.Refresh(background);
    }


}

current sample code (I tried different things so the code got a bit complicated)

private async Task _initBackgroundMap()
{

    // It is important to set the map unit first to either feet, meters or decimal degrees.
    map.MapUnit = GeographyUnit.Meter;

    map.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#6996AD"));

    // Create and Add the overlay to the map.
    GenerateBackgroundOverlay();

    // Set the current extent to a local area.
    SetMapCurrentExtent();

    // Refresh the map.
    await map.RefreshAsync();
}

private void GenerateBackgroundOverlay()
{
    // Clear out the overlays so we start fresh
    map.Overlays.Clear();

    // Create an overlay that we will add the layer to.
    var staticOverlay = new LayerOverlay
    {
        DrawingExceptionMode = DrawingExceptionMode.ThrowException,
        /*IsVisible = true,
        TileCache = new InMemoryRasterTileCache(),
        TileHeight = 256,
        TileWidth = 256,*/
    };
    staticOverlay.ThrowingException += (sender, e) =>
    {
        logger.Warn(e.Exception, "ThinkGeo exception : ");
        e.Handled = true;
    };
    map.Overlays.Add(staticOverlay);

    CustomWmsLayer custom = new CustomWmsLayer(new Uri(MapData.Url), $"EPSG:{MapData.SrsEPSG}");
    custom.ActiveLayerNames.Add("LAYERS", string.Join(",", MapData.Layers));
    custom.ActiveStyleNames.Add("");

    staticOverlay.Layers.Add("background", custom);

    /*
    var wmsOverlay = new WmsOverlay();
    wmsOverlay.AxisOrder = WmsAxisOrder.XY;
    wmsOverlay.Uri = new Uri(MapData.Url);
    wmsOverlay.Crs = $"EPSG:{MapData.SrsEPSG}";
    wmsOverlay.Parameters.Add("LAYERS", string.Join(",", MapData.Layers));
    wmsOverlay.Parameters.Add("VERSION", "1.3.0");
    map.Overlays.Add("background", wmsOverlay);*/

}

private void SetMapCurrentExtent()
{
    if (MapData.InitialExtend == null)
        SetExtentDefault();
    map.CurrentExtent = MapData.InitialExtend.ToShape();

    void SetExtentDefault()
    {
        //Hard coded lyon extent
        RectangleShape lyonRectangleShape = new RectangleShape(4.7649178, 45.7943508, 4.916865, 45.7527233);
        MapData.InitialExtend = lyonRectangleShape.ToMapRectangle();
    }
}


public class CustomWmsLayer : WmsLayer
{
    private WmsLayer firstLayer;
    private readonly Logger logger = LogManager.GetCurrentClassLogger();

    public CustomWmsLayer(Uri uri, string crs)
        : base(uri) 
    {
        DrawingExceptionMode = DrawingExceptionMode.ThrowException;
        Crs = crs;
    }

    protected override void DrawExceptionCore(GeoCanvas canvas, Exception e)
    {
        // customize the drawing exception. Here below we draw the error in red on orange canvas.
        logger.Error(e);
    }
}

hi @Cecile_Morelle,

Thanks for your code snippet. We’ve made some a lot of changes from 7.0 to 14.1.

Could you try the following code, use WmsAxisOrder.YX if it doesn’t work?

var wmsOverlay = new WmsOverlay(new Uri("MapData.Url"), $"EPSG:{MapData.SrsEPSG}", WmsAxisOrder.XY);
foreach (var layer in MapData.Layers)
{
    wmsOverlay.ActiveLayerNames.Add(layer);
}

Regards,
Leo

It works now !
I’m gonna try older versions but looks like the extent somehow changed…

Okay I tested it with the previous solution of a CustomWmsLayer (I still get something uncaugth errors).
This code don’t work.
Is there a way to have both ? The map (actual solution : a WmsOverlay) and that no uncaugth async errors kills my app (actual solution : a LayerOverlay containing a CustomWmsLayer).

tested code:

private void GenerateBackgroundOverlay()
{
    // Clear out the overlays so we start fresh
    map.Overlays.Clear();

    // Create an overlay that we will add the layer to.
    //----------------------------------------------
    var staticOverlay = new LayerOverlay
    {
        DrawingExceptionMode = DrawingExceptionMode.ThrowException,
        /*IsVisible = true,
        TileCache = new InMemoryRasterTileCache(),
        TileHeight = 256,
        TileWidth = 256,*/
    };
    staticOverlay.ThrowingException += (sender, e) =>
    {
        logger.Warn(e.Exception, "ThinkGeo exception : ");
        e.Handled = true;
    };
    map.Overlays.Add(staticOverlay);

    CustomWmsLayer custom = new CustomWmsLayer(new Uri(MapData.Url), $"EPSG:{MapData.SrsEPSG}");
    foreach (var layername in MapData.Layers)
        custom.ActiveLayerNames.Add(layername);

    staticOverlay.Layers.Add("background", custom);
}

custom layer:

public class CustomWmsLayer : WmsLayer
{
    private WmsLayer firstLayer;
    private readonly Logger logger = LogManager.GetCurrentClassLogger();

    public CustomWmsLayer(Uri uri, string crs)
        : base(uri) 
    {
        DrawingExceptionMode = DrawingExceptionMode.ThrowException;
        Crs = crs;
        AxisOrder = WmsAxisOrder.XY;
    }

    protected override void DrawExceptionCore(GeoCanvas canvas, Exception e)
    {
        // customize the drawing exception. Here below we draw the error in red on orange canvas.
        logger.Error(e);
    }
}

hi @Cecile_Morelle,

Are you saying that WmsOverlay works but CustomWmsLayer (which inherits from WmsLayer) doesn’t?

If so, that’s strange because WmsOverlay and WmsLayer have identical logic. Could you try using WmsLayer directly and see if it works?

var wmsLayer = new WmsLayer(new Uri("MapData.Url"), null, $"EPSG:{MapData.SrsEPSG}", WmsAxisOrder.XY);

Regards,
Leo

Hello,

I fixed using your example :

public class CustomWmsLayer : WmsLayer
{
    private readonly Logger logger = LogManager.GetCurrentClassLogger();

    public CustomWmsLayer(Uri uri, string crs)
        : base(uri, null, crs, WmsAxisOrder.XY)
    {
        DrawingExceptionMode = DrawingExceptionMode.ThrowException;
    }

    protected override void DrawExceptionCore(GeoCanvas canvas, Exception e)
    {
        // customize the drawing exception. Here below we draw the error in red on orange canvas.
        logger.Error(e);
    }
}

That’s great! Let me know if you have other questions. :slight_smile:

Regards,
Leo