ThinkGeo.com    |     Documentation    |     Premium Support

Pink Tiles

Hi,


I'm getting intermittent instances of Pink tiles when using a WMS layer in both cached and uncached [shape file] modes.


The Maps server is a Server 2008 machine with IIS 7 [tried Classic ASP and integrated mode]. Its the latest version [production] of WMS server edition and Web Edition.


The Web Client code is simply adding a WMS layer and the only thing of note is that the 114 shape files we have  are leaded in the plugin by looping through an XML file to get the files to load.


It actually works fine 70% of the time but seems to smell a demo a mile off :)



I have moved the WMS server to the development machine with no change really


Firstly, does a Pink tile mean that a tile was requested and not retrieved or that the request was not made.


Where is the best place to start debugging this. The code I have is simple and is based on the Display A Simple Map from the WMS server demo.


I have noted that the problem can get worse if zooming into the edge of the tiles with the result that the pink tiles end up filling the screen and I need a full refresh to partially resolve.


I have a dedicated website in IIS for the WMS and the settings are standard.


Of note is that the distortion does no show up in the minimap.


What does the presence of pink tiles mean? The tile was not requested or it was requested and not served.


How would I start to debug this issue.


Sometimes blank tiles appear in the background colour but this is not as common. 


Is it possible that we are dealing wit a timeout issue?


Thanks,


Liam



 


 


 



Hi, Liam


I don’t know how you consume the WMS Server, so that I have some suggestions for you firstly.
If you have been using TiledWmsLayer in WebEdition product, and I suggest you to use WmsOverlay instead of TiledWmsLayer, because it can improve your performance significantly and the TiledWmsLayer may cause timeout excpetion.
As far as I know, pink tiles are due to so many reasons. The most common one is that one exception throws on the server-side which is in charge of serving maps. If you have set the server uri right and not all tile images are pink and I think the tile requests have been sent but the server can’t give the proper response.
If the exception occurs on the server-side, by default, the exception message will be written to the Trace, so that you can get this error message through DebugView or other tools to check that. Or you can get any one pink tile URL through right clicking one pink tile and then choose property, then copy the url for this one pink tile as the screenshot below shows and then paste it to another tab, so you can get the xml format exception message or tile image, if it says “WMS Server Exception See Server Trace” that means you need to get the exception message through the DebugView or other tools.

Also you can override the GetMapCore method which will be called every request comes for this plugin and just call the GetMapCore method of base to see whether it generates the tile image or this method never be called.
Or you can use HttpWatch to see the request you sent and response that the server returns.
Please clear the browser cache before your test, that’s because the pink tiles maybe cached on your browser.
If you don’t mind, please send us the code of client and how you set up your plug-in. So that we can quickly find the reasons cause it.
Thanks,
Khalil

 Hi Khalil,


 


Thanks for the info and the advice. I had looked at the cache at the browser level already and cleared it.


 


Here is the code as requested, I have changed the servername and the plugin name before posting. There is additional code in the plugin thats irrelavent.


[code]


 


Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"));


Map1.CurrentExtent = new RectangleShape(-131.22, 55.05, -54.03, 16.91);


Map1.MapUnit = GeographyUnit.DecimalDegree;


 


OverlaySwitcherMapTool overLaySwitcher = new OverlaySwitcherMapTool();


overLaySwitcher.Enabled = true;


Map1.MapTools.OverlaySwitcher.Enabled = true;


 


Map1.MapTools.MouseCoordinate.Enabled = true;


Map1.MapTools.MouseCoordinate.MouseCoordinateType = MouseCoordinateType.LatitudeLongitude;


Map1.MapTools.MiniMap.Enabled = true;


Map1.MapTools.ScaleLine.Enabled = true;


 


WmsOverlay wmsOverlay = new WmsOverlay("WMS Overlay");


 


wmsOverlay.Parameters.Add("LAYERS", "OurPlugin");


wmsOverlay.Parameters.Add("STYLES", "DEFAULT");


wmsOverlay.ServerUris.Add(new Uri("servername:6160/WmsPluginService/WmsHandler.axd"));


Map1.CustomOverlays.Add(wmsOverlay);


----------------------------------------------------------------------------------------------------------------------------


 


using System;


using System.Collections.ObjectModel;


using System.IO;


using ThinkGeo.MapSuite.Core;


using ThinkGeo.MapSuite.WmsServerEdition;


 


using System.Xml.Linq;


 


namespace WmsPlugins


{


    public class AMCSTestPlugin : WmsLayerPlugin


    {


        // This method is only called once per style and crs.  In it you should create your


        // layers and add them to the MapConfiguration.  If you want to use tile caching you


        // can also specif that in the MapConfiguration under the TileCache property.


        // If you have setup multiple styles or projections this method will get called for


        // each unique combination


        protected override MapConfiguration GetMapConfigurationCore(string style, string crs)


        {


            try


            {


                #region Initial layers


                // Get the directory to the sample data


                string worldLayerFilePath = Directory.GetParent(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).FullName).FullName + "\\SampleData\\Countries02.shp";


                // Create the world layer from a shapefile and add a style to it


                ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(worldLayerFilePath);


                worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1;


                worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


 


                MapConfiguration mapConfiguration = new MapConfiguration();


                mapConfiguration.Layers.Add("WorldLayer", worldLayer);


                #endregion


 


                // LGK


                string mapFolderLocation = Directory.GetParent(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).FullName).FullName + "\\SampleData\\ShapeFileStore\\";


                #region Capital Layer


                ShapeFileFeatureLayer capitalLayer = new ShapeFileFeatureLayer(mapFolderLocation + "capital.shp");


 


                // We can customize our own Style. Here we passed in a color and a size.


                capitalLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.White, 7, GeoColor.StandardColors.Brown);


 


                // The Style we set here is available from ZoomLevel01 to ZoomLevel05. That means if we zoom in a bit more, the appearance we set here will not be visible anymore.


                capitalLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level05;


 


                capitalLayer.ZoomLevelSet.ZoomLevel06.DefaultPointStyle = PointStyles.Capital3;


 


                // The Style we set here is available from ZoomLevel06 to ZoomLevel20. 


                capitalLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


                #endregion


 


                #region Capital Label Layer


                ShapeFileFeatureLayer capitalLabelLayer = new ShapeFileFeatureLayer(mapFolderLocation + "capital.shp");


 


                // We can customize our own TextStyle. Here we passed in the font, the size, the style and the color.


                capitalLabelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.CreateSimpleTextStyle("CITY_NAME", "Arial", 8, DrawingFontStyles.Italic, GeoColor.StandardColors.Black, 3, 3);


 


                 capitalLabelLayer.ZoomLevelSet.ZoomLevel06.DefaultTextStyle = TextStyles.Capital3("CITY_NAME");


 


                // The TextStyle we set here is available from ZoomLevel06 to ZoomLevel20. 


                capitalLabelLayer.ZoomLevelSet.ZoomLevel06.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


                capitalLabelLayer.DrawingMarginPercentage = 50;


                #endregion


 


                // Set the cache directory


                string mapCacheFolder = string.Empty;


 


                mapCacheFolder = @"E:\Program Files (x86)\ThinkGeo\Map Suite WMS Server Evaluation Edition 4.0\HowDoISamples\CSharp Samples\SampleData\AMCSMapCache27Aug2010\";


 


                FileBitmapTileCache tileCache = new FileBitmapTileCache(mapCacheFolder);


 


                mapConfiguration.Layers.Add(capitalLayer);


 


                mapConfiguration.Layers.Add(capitalLabelLayer);


 


string mapConfigFile = mapFolderLocation + "Map.xml";


if (!File.Exists(mapConfigFile)) throw new Exception("Map.xml not found");


string shapeFileIndex = string.Empty;


 


string shapeFileName = string.Empty;


 


foreach (XElement level1Element in XElement.Load(mapConfigFile).Elements("Layers").Elements("Layer"))


{


 


shapeFileName = mapFolderLocation + level1Element.Element("ShapeFile").Attribute("Value").Value;


shapeFileIndex = shapeFileName.Replace(".shp", "") + ".idx";


ShapeFileFeatureLayer shapeFileMapLayer = new ShapeFileFeatureLayer();


if (readFromCache)


{


mapConfiguration.TileCache = tileCache;


mapConfiguration.TileCache.CacheId = Path.GetFileNameWithoutExtension(shapeFileName);


}


 


shapeFileMapLayer.ShapePathFileName = shapeFileName;


shapeFileMapLayer.IndexPathFileName = shapeFileIndex;


 


int upperExtent = int.Parse(level1Element.Element("UpperExtent").Attribute("Value").Value);


 


string penColour = level1Element.Element("PenColour").Attribute("Value").Value.Replace("-", "");


int penColourNumber = penColour.Length != 0 ? int.Parse(penColour) : 16581375;  // return white


 


// TODO: Check what happens if this is missing - XSD file should get a lot of it


string brushColour = level1Element.Element("BrushColour").Attribute("Value").Value.Replace("-", "");


int brushColourNumber = brushColour.Length != 0 ? int.Parse(brushColour) : 16581375;  // return white


 


SetZoomLevel(shapeFileMapLayer, upperExtent, penColourNumber, brushColourNumber, readFromCache);


 


mapConfiguration.Layers.Add(shapeFileMapLayer);


}


 


                return mapConfiguration;


            }


            catch (Exception ex)


            {


                throw new Exception("Exception - " + ex.ToString());


            }


        }


 


        private static void SetZoomLevel(ShapeFileFeatureLayer shapeFile, int upperZoomLevel, int brushColour, int penColour, bool readFromCache)


        {


            if (!readFromCache)


            {


                switch (upperZoomLevel)


                {


                    case 20:


                        // transparancy setting the colour pass the alpha coardinate alsos. This sets how transparent it is - try 0 for the brushe


                        shapeFile.ZoomLevelSet.ZoomLevel20.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


                        shapeFile.ZoomLevelSet.ZoomLevel20.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.SimpleColors.Transparent, GeoColor.FromArgb(100, GeoColor.SimpleColors.Green));


                        shapeFile.ZoomLevelSet.ZoomLevel20.DefaultAreaStyle.FillSolidBrush.Color = GeoColor.GeographicColors.Sand;


                        shapeFile.ZoomLevelSet.ZoomLevel20.DefaultAreaStyle.OutlinePen.Color = GeoColor.StandardColors.Blue;


                        shapeFile.ZoomLevelSet.ZoomLevel20.DefaultLineStyle.OuterPen = new GeoPen(GeoColor.SimpleColors.Black, 1);


                        shapeFile.ZoomLevelSet.ZoomLevel20.DefaultLineStyle.InnerPen = new GeoPen(GeoColor.GeographicColors.Road);


                        shapeFile.ZoomLevelSet.ZoomLevel20.DefaultPointStyle.SymbolPen = new GeoPen(GeoColor.FromArgb(255, GeoColor.StandardColors.Green), 8);


                        break;


                    case 19:


                        shapeFile.ZoomLevelSet.ZoomLevel19.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;


                        shapeFile.ZoomLevelSet.ZoomLevel19.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.SimpleColors.Transparent, GeoColor.FromArgb(100, GeoColor.SimpleColors.Green));


                        shapeFile.ZoomLevelSet.ZoomLevel19.DefaultAreaStyle.FillSolidBrush.Color = GeoColor.GeographicColors.Sand;


                        shapeFile.ZoomLevelSet.ZoomLevel19.DefaultAreaStyle.OutlinePen.Color = GeoColor.StandardColors.Blue;


                        shapeFile.ZoomLevelSet.ZoomLevel19.DefaultLineStyle.OuterPen = new GeoPen(GeoColor.SimpleColors.Black, 1);


                        shapeFile.ZoomLevelSet.ZoomLevel19.DefaultLineStyle.InnerPen = new GeoPen(GeoColor.GeographicColors.Road);


                        shapeFile.ZoomLevelSet.ZoomLevel19.DefaultPointStyle.SymbolPen = new GeoPen(GeoColor.FromArgb(255, GeoColor.StandardColors.Green), 8);



// etc



}


}


        }


 


        private ApplyUntilZoomLevel GetZoomLevel(int threshold)


        {


            // TODO: Change this for lower zoom levels


            switch (threshold)


            {


                case 20:


                    return ApplyUntilZoomLevel.Level20;


                case 19:


                    return ApplyUntilZoomLevel.Level19;


                case 18:


                    return ApplyUntilZoomLevel.Level18;


                case 17:


                    return ApplyUntilZoomLevel.Level17;


                case 16:


                    return ApplyUntilZoomLevel.Level16;


                case 15:


                    return ApplyUntilZoomLevel.Level15;


                case 14:


                    return ApplyUntilZoomLevel.Level14;


                case 13:


                    return ApplyUntilZoomLevel.Level13;


                case 12:


                    return ApplyUntilZoomLevel.Level12;


                case 11:


                    return ApplyUntilZoomLevel.Level11;


                case 10:


                    return ApplyUntilZoomLevel.Level10;


                case 9:


                    return ApplyUntilZoomLevel.Level09;


                case 8:


                    return ApplyUntilZoomLevel.Level08;


                case 7:


                    return ApplyUntilZoomLevel.Level07;


                case 6:


                    return ApplyUntilZoomLevel.Level06;


                case 5:


                    return ApplyUntilZoomLevel.Level05;


                case 4:


                    return ApplyUntilZoomLevel.Level04;


                case 3:


                    return ApplyUntilZoomLevel.Level03;


                case 2:


                    return ApplyUntilZoomLevel.Level02;


                case 1:


                    return ApplyUntilZoomLevel.Level01;


            }


 


            // default value


            return ApplyUntilZoomLevel.Level20;


        }


 


 


        // In this method you need to return the name of the Layer that WMS will expose.


        // You will use this name on the client to specify the layer you want to consume


        protected override string GetNameCore()


        {


            return "OurPlugin";


        }


 


        // In this method you need to return the projections that are supported by your data.


        // It is your responsability to project the data in the MapConfiguration for each projection


        // type you specify here.


        protected override Collection<string> GetProjectionsCore()


        {


            return new Collection<string> { "EPSG:4326" };


        }


 


        // In this method you need to return the bounding box of the layer.


        protected override RectangleShape GetBoundingBoxCore(string crs)


        {


            // TODO: there could be some issue here. Original example from the samples


            // return new RectangleShape(-126.826171875, 57.104766845702, -70.83984375, 18.960235595702);


 


            // I think that this is the world extent


            return new RectangleShape(-180, 90, 180, -90);


        }


 


        private Collection<zoomlevel> GetAllZoomLevels()


        {


            // We only add the top 5 ZoomLevels here for example. 


            // If you want to add more scales, you need to optimize the way generating tiles otherwise 


            // the bitmap we generated might be too big to be hold in memory.


            GoogleMapZoomLevelSet zoomLevelSet = new GoogleMapZoomLevelSet();


            Collection<zoomlevel> resultZoomLevels = new Collection<zoomlevel>();


            resultZoomLevels.Add(zoomLevelSet.ZoomLevel01);


            resultZoomLevels.Add(zoomLevelSet.ZoomLevel02);


            resultZoomLevels.Add(zoomLevelSet.ZoomLevel03);


            resultZoomLevels.Add(zoomLevelSet.ZoomLevel04);


            resultZoomLevels.Add(zoomLevelSet.ZoomLevel05);


            return resultZoomLevels;


        }


    }


}


 

 


 


 


 


 


Rgds,


Liam



Liam, 
  
 I can’t find any problems for your client-side codes. I guess the problem lies on the server-side. 
 Can you post the exception message or any pink tile url? Or the plug-in code? 
  
 Thanks, 
  
 Khalil

Liam, 
  
 Thanks for your updated information. I have reviewed your plugin code and the clien-side code and I can’t fingure out the problem. So I need to know what is the exception message? Can you provide me for that? 
  
 Thanks, 
  
 Khalil

 Hi Khalil,


On the image url I get the following 


500 - Internal server error.


At least its a solid fail.


I checked the URL of an image that had rendered fine and could browse to it but on refresh I got the 500 - Internal Server Error also.


I need to look at the server end closer and will let you know.


Thanks,


Liam



Hi, Liam


Any update on this post? Please let us know if you have any progress on it and so we can help you immediately.
Thanks,
Khalil

Hi Khalil,


I have been side tracked by another issue [see my post on the Desktop Edition - gis.thinkgeo.com/tabid/143/a...fault.aspx] and will return to this in a day or 2 and will let you know of any progress.


Thanks, Liam


 



Liam, 
  
 Thanks for your feedback. I look forward to your reponse on this problem. 
 Thanks, 
  
 Khalil

Hi Khalil,


I looked at the requests in Process Monitor and the only thing of note is the following file is requested on  the WMS remote server


[Full Path]\Map Suite WMS Server Evaluation Edition 4.0\HowDoISamples\CSharp Samples\WmsPluginService\WmsHandler.axd\web.config


[It returns a Path Not Found result]


I will investigate further in  the morning but it does seem unusual.


As above the client code is very simple.


Liam



Hi, Liam


It’s so weird. If you request the web.config file on the server-side, and the request filtering module is configured to deny a path in the URL that contains a hiddenSegment section, such as web.config. RequestFilteringModule module is in charge of that on IIS 7.0.
If you still encounter 500 internal server errors, please try to right click on the pink tile and click the “Show Picture” to see whether the image will be loaded. I guess there is some wrong with your server configuration. Or you can change the TileType on WmsOverlay to SingleTile and have a try for it.
 
Thanks,
Khalil

Hi Khalil,


Noted on the wierdness, however I have not had timefor the at week to invstigate properly. I'm on annual eave for a few weeks and will tend to this propery on my return.


Liam



Hi, Liam 
  
 Thanks for your feedback.  
 Ok, we can talk about it when you return. 
  
 Thanks, 
  
 Khalil