Loading Collections into Virtual Earth v6

Update: Keith from the VE team advised on the 17th November 2007 that this issue is now fixed. Closer to 3 weeks than the advised 3 days, but at least it’s resolved.

Microsoft launched version 6 of the Virtual Earth API last week. Keeping with the product’s tradition, they broke some core features too. In particular, the ability to load a collection from maps.live.com directly in to the map control.

We use this approach on a number of our sites (the latest being visitscandinavia.com.au) because it basically gives us the mapping CMS for free. The client can create pushpins with text and photos, draw lines and polygons, all in the maps.live.com interface. They then just copy-paste the collection ID into our web CMS.

The problem is that in V6, the load method doesn’t throw any errors but it also doesn’t load any pins. We tried rolling back to V5, but that just brought back old bugs (like the pushpin popups appearing in the wrong place if you actually use a proper CSS column layout instead of tables).

This is the workaround I came up with (inspired by http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2276610&SiteID=1).

Loading of GeoRSS feeds still work fine, and we can get to our collections as GeoRSS feeds (the UI is a bit convoluted, but you can do it). Of course, we can’t load the feed directly from maps.live.com though because that would be a cross-domain call.

The proxy to get around this is pretty simple – just a generic handler (ASHX) in ASP.NET:

namespace SqueezeCreative.Stb.WebUI
{
    public class VirtualEarthGeoRssLoader : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            string collectionId = context.Request[“cid”];
            string geoRssUrl = string.Format(“http://maps.live.com/GeoCommunity.asjx?action=retrieverss&mkt=en-us&cid={0}”, collectionId);

            WebRequest request = WebRequest.CreateDefault(new Uri(geoRssUrl));
            WebResponse response = request.GetResponse();

            string geoRssContent;
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                geoRssContent = reader.ReadToEnd();

            context.Response.ContentType = “text/xml”;
            context.Response.Write(geoRssContent);
        }

        public bool IsReusable
        {
            get { return false; }
        }
    }
}

We can then call this handler from out client-side JS like so (where B33D2318CB8C0158!227 is my collection ID):

var layer = new VEShapeLayer();
var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, ‘VirtualEarthGeoRssLoader.ashx?cid=B33D2318CB8C0158!227’, layer);
map.ImportShapeLayerData(veLayerSpec, function() {}, true);

Their ETA for fixing this was 3-5 days, but that seems to have gone out the window.

I hope this helps in the mean time!

One comment

Comments are closed.