ThinkGeo.com    |     Documentation    |     Premium Support

Deleting markers created in server from client side

 


Hi, 


I have created several markers in server side using the function below (removed some codes):


 


InMemoryMarkerOverlay markerOverlay = (InMemoryMarkerOverlay)Map1.CustomOverlays["MarkerOverlay"];


            foreach (GP)


            {


                Vertex vertex = new Vertex(GP.Longitude, GP.Latitude);


                markerOverlay.Features.Add(new Feature(vertex));


            }


 


and this in client side:


 


var OnMapCreated = function(map) {


            markers = map.getLayer('MarkerOverlay');


}


function Success(args, context) {


 


 


if (markers.markers != null) {


                 while (markers.markers.length > 0) {


                        markers.markers[0].destroy();


                        markers.removeMarker(markers.markers[0]);


                    }


            } 


}


 


They get deleted initially but displays again when zooming in or out of the map. How do I remove them permanently? The scenario is I load markers from the server on the initial request and use callback to update the location of the markers client side.


 


 


 


 


 



Allen,


You need to make client side and server side synchronized, I create a little sample to show how to implement synchronization.


PS: this way may not has good performance, but it might a only easy way to do it.


Thanks


James



8594_Delete_marker_sample.zip (2.61 KB)

 


Hi James,


Can you explain further how synchronization was achieved in the code you provided?


Does the function below removes the callback function? Because I need that to update the marker position after XX seconds.


 



var callbackscript = @"function removecallback(arg, context) {" +


        Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context") + "}";


        ScriptManager.RegisterStartupScript(this, this.GetType(), "callbackscript", callbackscript, true);



 


 


 


 



Allan, 
  
 So you want to update markers position after xx seconds, there is a sample “AutoRefreshOverlay” in our HowDoI samples is exactly what you want. MarkerOverlay provides a property AutoRefreshInterval to let user set timespan and hookup a event Tick, when the event fired, you can update the marker’s position. 
  
 Thanks, 
 James

 Hi James,


 
I looked into that and it uses a timer control to update the markers server side. But I prefer using the callback for fleet as it is more efficient.
 
This is the scenario:


        
  1. Add multiple markers with different images in a google map overlay server side at first load

  2.     
  3. After XX seconds (continuous), by implementing callback update the marker images and positions in client side

  4.     
  5. Marker must have popups

  6.     
  7. Marker must have labels

  8.     
  9. Marker will show from a certain zoom level onwards

  10.     
  11. Marker can be clustered at low zoom levels


So far, I got  1 and 2 but the problem is the markers created at server side doesn't disappear completely even when calling the code below using javascript. They reappear when zooming in/out of the map.



var OnMapCreated = function(map) {


           markers = map.getLayer('MarkerOverlay');


            webmap = map;


 


            var timer = window.setInterval(Function.createDelegate({ 'args': "args", 'context': document.getElementById('message') }, function(evt) {


                var args = this.args;


                var context = this.context;


                <%=Page.ClientScript.GetCallbackEventReference(this, "args", "Success", "context", "Error", true) %>;


            }), 5000);


        };


        


        function Success(args, context) {


 


            var vehicles = Sys.Serialization.JavaScriptSerializer.deserialize(args);


            if (markers.markers != null) {


                 while (markers.markers.length > 0) {


                        markers.markers[0].destroy();


                        markers.removeMarker(markers.markers[0]);


                    }


            } 


}



 



 Ok I managed to remove the markers created server side by calling this: 

 



public void RaiseCallbackEvent(String eventArgument) {


InMemoryMarkerOverlay markerOverlay = (InMemoryMarkerOverlay)Map1.CustomOverlays["MarkerOverlay"]; markerOverlay.Features.Clear();


//Serialize New Marker locations


m_result = serializer.Serialize(MarkerInfo);


}



 But the markers created client side are still disappearing when the map is being zoomed or panned. Is that expected behavior?



 



 



<eventargs>I tried using SimpleMarkerOverlay instead but after creating the markers on first load, markers doesnt get refreshed. 



server code: 

</eventargs>



<eventargs>

void pageload () { 

SimpleMarkerOverlay markerOverlay = new SimpleMarkerOverlay("MarkerOverlay"); 

markerOverlay.AutoRefreshInterval = TimeSpan.FromMilliseconds(10000); 

markerOverlay.Tick += new EventHandler<eventargs>(markerOverlay_Tick); 



foreach (marker) 

markerOverlay.Markers.Add(projectedMarker); 







void markerOverlay_Tick() { 

SimpleMarkerOverlay markerOverlay = (SimpleMarkerOverlay)Map1.CustomOverlays["MarkerOverlay"]; 

markerOverlay.Markers.Clear(); 



// markers already have different lat, long 

foreach (marker) 

markerOverlay.Markers.Add(projectedMarker); 





</eventargs> </eventargs>



 



 


Hi Allan,
I think there is a little misunderstanding about autorefresh, which indeed uses the ICallback and client side timer rather server side timer. So please don’t worry about the performance.
Regarding adding markers, just same to removing markers on client side, you still need synchronize the data on server side, because the map suite always generate the data on server side, and then create the markers with these data on the client.
We tried the same code that you posted just now, but it seems that there is no problem, please take a look at the attached demo.
 
Thanks,
Johnny

CreatingMarkers.zip (2.21 KB)


 Hi Johnny, 
  
 Just as I suspected, AutoRefreshInterval implements the CallBack interface internally. So right now I’m using simple marker overlay with autorefresh interval. 
  
 I noticed on the AutoRefresh sample that the map control was inside an update panel. That could be the reason why the markers were not updating positions. Then I tried that  but the map didnt load. Just white space. Just to note that the map control is in a Web User Control and this in turn is loaded dynamically in an Update Panel. So the map is actually rendered inside an Update Panel. I checked and the function markerOverlay_Tick() is being called and marker position values being changed. But still no update in the Map. 
  


 


Allan,
 
We have done a test depending on your description and everything is ok. I think maybe it’s a version issue. You can download the latest daily build and have a try. 
 
Here attached is a sample for you. You can send us a demo if there is still any problems, so we can understand it better.
 
Thanks,

James



Post8594.zip (8.02 KB)

Hi James, 
  
 I have downloaded the latest build and add a reference to it in the sample you just gave but it gives me this error: 
  
 
Could not load file or assembly ‘NetTopologySuite, Version=1.7.3.31740, Culture=neutral, PublicKeyToken=f580a05016ebada1’ or one of its dependencies. The system cannot find the file specified. 


I am now able to place the map control inside an update panel without it disappearing. It was the Map Height property which should not be set to a percentage value. Is this a bug? Outside an UpdatePanel percent height works fine. 


protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"));
            Map1.CurrentExtent = new RectangleShape(-95.31105, 38.98184, -95.20359, 38.92185);
            Map1.MapUnit = GeographyUnit.DecimalDegree;

            WorldMapKitWmsWebOverlay overlay = new WorldMapKitWmsWebOverlay();
            Map1.CustomOverlays.Add(overlay);

            SimpleMarkerOverlay markerOverlay = new SimpleMarkerOverlay("MarkerOverlay");
            markerOverlay.AutoRefreshInterval = TimeSpan.FromMilliseconds(3000);
            markerOverlay.Tick += new EventHandler<EventArgs>(markerOverlay_Tick);
            markerOverlay.Markers.Add(new Marker(-95.26095, 38.93926, new WebImage(21, 25, -10.5f, -25f)));
            markerOverlay.Markers.Add(new Marker(-95.26086, 38.96956, new WebImage(21, 25, -10.5f, -25f)));
            markerOverlay.Markers.Add(new Marker(-95.25919, 38.96758, new WebImage(21, 25, -10.5f, -25f)));
            markerOverlay.Markers.Add(new Marker(-95.29056, 38.95703, new WebImage(21, 25, -10.5f, -25f)));
            markerOverlay.Markers.Add(new Marker(-95.22653, 38.94278, new WebImage(21, 25, -10.5f, -25f)));
            markerOverlay.Markers.Add(new Marker(-95.26987, 38.93531, new WebImage(21, 25, -10.5f, -25f)));

            Map1.CustomOverlays.Add(markerOverlay);

        }
        
    }

void markerOverlay_Tick(object sender, EventArgs e)
    {
        SimpleMarkerOverlay markerOverlay = (SimpleMarkerOverlay)Map1.CustomOverlays["MarkerOverlay"];
        markerOverlay.Markers.Clear();

        for (int i = 0; i < 6; i++)
        {
            double lon = -95.26095 + new Random(Guid.NewGuid().GetHashCode()).Next(-12, 20) / 5000.0;
            double lat = 38.93926 + new Random(Guid.NewGuid().GetHashCode()).Next(-11, 26) / 5000.0;
            Marker marker = new Marker(lon, lat);

            markerOverlay.Markers.Add(marker);
        }

    }

.aspx:

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <cc1:Map ID="Map1" runat="server" Height="500" Width="100%"></cc1:Map>
            
</asp:UpdatePanel>


But after the markeroverlay_tick fires I get this error: 
Microsoft JScript runtime error: Sys.ArgumentException: Cannot deserialize. The data does not correspond to valid JSON.
Parameter name: data

 Here is the actual code files for the web user control:



003_002_001_MapSuiteControl.zip (4.68 KB)
MapSuiteControl.zip (4.68 KB)
001_MapSuiteControl.zip (4.68 KB)

got a lot of errors and I kept on retrying and ended up with multiple uploads…

 


Hi James,


I have narrowed down the problem a bit.


I have used the exact code from the AutoRefreshOverlay and was able to see the markers move around. I then used Google Map overlay and projected the markers in the same position. The markers didn't refreshed. I am guessing it is a Projection PLUS AutoRefreshInterval issue. Below is code used. Maybe I missed something.


 




protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"));
                Proj4Projection proj4 = new Proj4Projection();
                proj4.InternalProjectionParametersString = Proj4Projection.GetEpsgParametersString(4326);
                proj4.ExternalProjectionParametersString = Proj4Projection.GetGoogleMapParametersString();
                proj4.Open();

                PointShape position = new PointShape(-95.31105, 38.98184);
                PointShape projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;

                PointShape position2 = new PointShape(-95.20359, 38.92185);
                PointShape projectedPosition2 = proj4.ConvertToExternalProjection(position2) as PointShape;
                Map1.CurrentExtent = new RectangleShape(projectedPosition, projectedPosition2);

                Map1.MapUnit = GeographyUnit.Meter;

                GoogleOverlay google = new GoogleOverlay("Google Map");
                google.GoogleMapType = ThinkGeo.MapSuite.WebEdition.GoogleMapType.Normal;
                google.JavaScriptLibraryUri = new Uri("maps.google.com/maps?file=api&v=2&client=gme-astrataasia&sensor=true");
                Map1.CustomOverlays.Add(google);

                SimpleMarkerOverlay markerOverlay = new SimpleMarkerOverlay("MarkerOverlay");
                markerOverlay.AutoRefreshInterval = TimeSpan.FromMilliseconds(3000);
                markerOverlay.Tick += new EventHandler<EventArgs>(markerOverlay_Tick);


                position = new PointShape(-95.26095, 38.93926);
                projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;
                markerOverlay.Markers.Add(new Marker(projectedPosition, new WebImage(21, 25, -10.5f, -25f)));

                position = new PointShape(-95.26086, 38.96956);
                projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;
                markerOverlay.Markers.Add(new Marker(projectedPosition, new WebImage(21, 25, -10.5f, -25f)));

                position = new PointShape(-95.25919, 38.96758);
                projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;
                markerOverlay.Markers.Add(new Marker(projectedPosition, new WebImage(21, 25, -10.5f, -25f)));

                position = new PointShape(-95.29056, 38.95703);
                projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;
                markerOverlay.Markers.Add(new Marker(projectedPosition, new WebImage(21, 25, -10.5f, -25f)));

                position = new PointShape(-95.22653, 38.94278);
                projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;
                markerOverlay.Markers.Add(new Marker(projectedPosition, new WebImage(21, 25, -10.5f, -25f)));

                position = new PointShape(-95.26987, 38.93531);
                projectedPosition = proj4.ConvertToExternalProjection(position) as PointShape;
                markerOverlay.Markers.Add(new Marker(projectedPosition, new WebImage(21, 25, -10.5f, -25f)));

                Map1.CustomOverlays.Add(markerOverlay);



            }
        }

        void markerOverlay_Tick(object sender, EventArgs e)
        {
            SimpleMarkerOverlay markerOverlay = (SimpleMarkerOverlay)Map1.CustomOverlays["MarkerOverlay"];
            foreach (Marker marker in markerOverlay.Markers)
            {
                double lon = marker.Position.X + new Random(Guid.NewGuid().GetHashCode()).Next(-12, 20) / 50.0;
                double lat = marker.Position.Y + new Random(Guid.NewGuid().GetHashCode()).Next(-11, 26) / 50.0;
                marker.Position = new PointShape(lon, lat);
            }
        }



 


Allan,
 
The sample “Post8594” which refers to WebEdition4.5.78.0 works fine on my machine. You may check your WebEdition version.  NetTopologySuite.dll is in the folder “ThinkGeo\Map Suite Web Full Edition 4.5\Developer Reference\Web Edition”, you can find it easily.
 
The percent height property is not a bug. All the asp.net control have the same problem. It caused by DOCTYPE. So just remove “w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">” from your page and it can be fixed.
 
UpdatePanel control requires a ScriptManager on the page and the ScriptManager must appear before any controls that need it. Just like the following code:
 
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="updatePanel1" runat="server">
    <ContentTemplate>
        <cc1:Map ID="Map1" runat="server" Height="480px" Width="640px">
        </cc1:Map>
    </ContentTemplate>
</asp:UpdatePanel>
 
The error “Sys.ArgumentException: Cannot deserialize” is a known bug, We have fixed it in the WebEdition4.5.78.0.
 
It’s not an issue. Because the offset is too small, so you don’t feel they are moving around apparently. You can update your code to the following:
 
double lon = marker.Position.X + new Random(Guid.NewGuid().GetHashCode()).Next(-12, 20) / 0.5;
double lat = marker.Position.Y + new Random(Guid.NewGuid().GetHashCode()).Next(-11, 26) / 0.5;
 
Thanks,

James



You are right. Its the small delta because of different projection. Thanks for your help James.

 


Hi James,


I was able to have the markers refresh their location in the map. Here are the issues that I encountered:



        
  1. marker not refreshing without map.extent value or having map_extentchanged event

  2.     
  3. Marker projectedMarker = new Marker(projectedPosition, new WebImage(MarkerIconPath, 44, 44, 22f, 22f) gives error the Sys.ArgumentException: Cannot deserialize. It will work if the no custom image is used. (using WebEdition 4.5.78.0)

  4.     
  5. adding webImage.Text = MarkerName removes the default marker images. (shows the missing image with red X)


 


 

 


Allan,
 
Here are the answers for your questions:
1.       Map.CurrentExtent is an important property, you must give it a value. We have done a test, the markers are still refreshing even if map have extentchanged event.
2.       We can’t recreate your problem, everything goes smoothly. Is MarkerIcoPath a virtual path? WebImage only support virtual path.
3.       The text will be drawn on the marker image on the server side, so it doesn’t support the path start with “..”, you could use “~”. For example, WebImage webImage = new WebImage("~/theme/default/img/red.png", 44, 44, 22f, 22f). And the marker without text won’t be drawn on the server side, so the path should be a virtual path. For example, WebImage webImage = new WebImage("../../theme/default/img/red.png", 44, 44, 22f, 22f).
 
Thanks,

James