Bing To Mapbox: Part 1

Recently I worked on a fun (fun for me, that is) project for my company, SST Software, in which I swapped out the web mapping API and tiles provider from Bing to Mapbox/Leaflet. Overall it was a good experience and it gave me a chance to compare and contrast Bing Map with Mapbox/Leaflet API. Before I started the migration, I searched for resources on this very topic but couldn’t find much. Mapbox.com website has an article on migrating from Google to Mapbox, but nothing on Bing to Mapbox. So I figured it might be helpful to the community to blog about what I learned from this experience.

bing_logo_header          

Topics to cover

  1. Why are we migrating?
  2. Mapbox.js vs. Leaflet.js.
  3. The process I went through.
  4. How I implemented the “flip-a-switch” solution.
  5. The result.
  6. Up next: What’s in Part 2?

Why are we migrating?

Simply put, it all comes down to two words: cost savings.

I don’t remember the exact numbers that Bing Map license cost us, but I have confirmed with my company that the cost savings we will get from moving to Mapbox is the primary, if not the only, reason that I was tasked to migrate our app from Bing to Mapbox. Bing map was working just fine for our web app from a technical perspective, except in a few cases where our custom tiles wouldn’t load completely. I also know for a fact that for us, the cost savings were very significant. With Mapbox we would only need to pay for a fraction of what we would for Bing map.

So for us, saving money was the main reason. But for you working on another project, there might be totally non-money related, legitimate reasons to move from Bing to Mapbox. Since Mapbox.js and Leaflet.js are open source, perhaps your organization wants to move away from a proprietary to an open-source solution? Perhaps you want to take advantage of some of the free Leaflet plugins? Feel free to share your experience in the comments section below.

Mapbox.js VS. Leaflet.js

First of all, I just want to say a quick word about Mapbox.js and Leaflet.js. Like me when I started on this project, you may or may not be clear on the difference between the two. In a nutshell, both are open source JavaScript libraries/APIs for web mapping, but Mapbox.js is built on top of Leaflet.js, and is a superset of Leaflet, and also a Leaflet plugin. The company, Mapbox, develops Mapbox.js, which makes it simple to integrate with their services and technologies. Mapbox also supports Leaflet development, since Leaflet’s creator/maintainer (Vladimir Agafonkin) works there.

Also, to quote Mapbox employee Tom MacWright, “You can use Mapbox.js without using Mapbox tiles, and use Leaflet with Mapbox tiles – they’re entirely mix-and-matchable. Mapbox.js’s additions, like TileJSON and UTFGrid support, make it easier to integrate with Mapbox maps, but don’t change the existing behavior of Leaflet.” You can find the StackOverflow page about it here.

So if I were to write a web app that uses Mapbox for its services such as loading tiles, it definitely makes more sense to use Mapbox.js, as it will make you life easier. But depending on the project, you might prefer Leaflet.js just so you don’t have to mess with Mapbox stuff. In the remainder of this post, I will use Mapbox.js to refer to both Mapbox.js and Leaflet.js for brevity purpose.

The process I went through

Before I delve into the details, let me give you an idea of the whole process I went through to migrate our web app from Bing to Mapbox. That way you will have a general idea of what to expect if you were to take on a migration project like this.

I was not the developer who wrote our app in the first place, nor was I very familiar with the app features. So I knew the first thing I had to do was getting a good understanding of what the app DOES. I am a firm believer in gaining a deep understanding of business requirements in order to produce quality software. In this case, I knew in order for this migration project to be successful, the new API (Mapbox) implementation will have to at least REPLACE ALL the functionalities of the existing API (Bing map) used in our app, if not enhance them. With that in mind, I spent some time playing with the app, and also got with some business folks and they helped bring me up to speed.

With a good understanding of what the app does, the next thing I needed to do was digging into the code and figure out where and how the Bing map API was being used. First of all, let me point out that both Bing Map and Mapbox offer several types of mapping APIs that target different platforms. Bing Map offers APIs for web (Bing Maps AJAX Control v7.0), Windows Store apps,  REST services, Spatial Data Services, and WPF. Mapbox offers APIs for web (Mapbox.js), iOS, Android, vector maps (Mapbox GL) and web services. In this post, when I’m talking about Bing map and Mapbox API, I am specifically talking about the Bing map web API (Bing Maps AJAX Control v7.0) and Mapbox.js.

With the Bing map API, all the classes were prefaced with the namespace “Microsoft.Maps”. For eg, the “Location” class was “Microsoft.Maps.Location”. So in my code editor, which is Visual Studio, I did a “Ctrl-F” scoped to my ASP.NET MVC project to find all the references to “Microsoft.Maps”, and that gave me a great starting point to find where Bing map API was being used. Originally I had hoped that the JavaScript files that contained the “Microsoft.Maps” string were the ONLY files that used Bing map API, but it turned out it wasn’t that simple.

There were lots of custom JavaScript objects that wrapped around Bing map objects, and these custom objects directly exposed Bing map API to the consuming code. (What I mean by consuming code is code that uses Bing map API to fulfill a user feature such as putting a marker on the map, versus code that just wraps around it.) A lot of the consuming code were used in files that didn’t explicitly reference “Microsoft.Maps”. Since I wasn’t the developer who created the project in the first place, this became a little tricky. I had to meticulously figure out where else the Bing map API was being used in files that didn’t explicitly specify the “Microsoft.Maps” string. But I shouldn’t have been too surprised by the fact that custom  objects were directly exposing some Bing map properties/methods b/c the alternative would be creating a one-to-one wrapper mapping for each Bing map object/property/method, which would have been a big undertaking of its own.

Another tricky part of this project was that I couldn’t really test the app as I went along b/c the code was a mix of Bing map and Mapbox API. It’s not like a Bing map marker would show up on a Mapbox map! So I realized I could only start testing the app once I had made a full sweep of the code, replacing Bing with Mapbox. So I didn’t look at the app UI for a while, and just buried my head down in my IDE. Unsurprisingly, the app did NOT run after I thought I had replaced all the Bing map code. It would have been a true miracle if it did. But after only a few trial and error runs, I was actually able to get the map to show using Mapbox! That was a great milestone for me b/c it meant from that point on, I just needed to get all the other Mapbox objects to show and behave correctly on the map.

In order to have some kind of order and organization in the way I replaced the Bing map code, instead of totally ad-hoc, I decided to do this by class and by feature. So for e.g., the class that is used to create a marker on Bing map is called “Pushpin”, whereas in Mapbox it’s called “Marker”. The API between these 2 classes were remarkably similar, which was super helpful for me. There were actually quite a few matching classes between the two APIs that were kind of like “Pushpin” vs “Marker”, so it made sense for me to start from there. I will make a full list of these classes with similar API in the second part of this blog series. Stay tuned 😉 When I couldn’t find similar classes, such as the Geolocation API, that’s when I took the approach of rewriting the code to replace the geolocate feature in the app. So taking these 2 approaches gave me a way to track my progress and which classes and features have been replaced.

So once I have replaced most of the Bing map code with Mapbox, the app was somewhat functioning, with bugs of course, but at least I was able to start testing the app. Being able to see and interact with the app was great b/c it allowed me to debug and tweak the code to my heart’s content. At that point it was just a matter of time to get everything working like how I wanted it.

So there you have it. That’s roughly the process I went through. I hope this gives you a good idea of what it’s like to swap out the mapping API. I am certain if you ever need to tackle a project like this in the future, it won’t be exactly like mine, but I hope you can glean some info here that might be helpful to you.

How I implemented the “flip-a-switch” solution

Here I’d like to dedicate a short section to describe how I implemented the “flip-a-switch” solution to go between Bing and Mapbox within our app. This approach turned out to be very helpful for testing and comparing the behaviors between the two APIs, along with the fact that it will make switching back to Bing map very easy if it ever comes to that someday, but I doubt it.

The web app is an ASP.NET MVC 3 app. So it has been around for a few years. Fortunately the front end of the app is architected fairly well, in my opinion, given the technologies available at the time. All the JavaScript files needed to run the relevant part of the app, including the mapping, are explicitly referenced in just one file: Index.cshtml (under a certain folder in the Views root folder, but this is not important).

B/c of this, I realized that it would be possible and desirable for me to create a “flip-a-switch” solution that enables swapping Bing with Mapbox and vice versa, by creating a brand new “Index.cshtml” file within the same folder. Obviously the original Index.cshtml file would have to be renamed to, say, Index-bing.cshtml. The new Index.cshtml file would be identical to the old one except it replaces old JavaScript file references using Bing map with the newly created JavaScript files that use Mapbox. In other words, for each JavaScript file that was using Bing map API, I would create a corresponding JavaScript file that replaces that same functionality accomplished in Bing map using Mapbox API.

So for e.g., suppose there was a JavaScript file called “pushpins.js” that puts pushpins on the map using Bing map, then I would create a corresponding “mapbox.pushpins.js” file that does the same thing using Mapbox. Then in the new “Index.cshtml” file intended for Mapbox implementation, it would reference the “mapbox.pushpins.js” file. So when I do this to ALL the JavaScript files that use Bing map, then the new “Index.cshtml” file will load all the same resources as the old “Index.cshtml” except the new JavaScript files. This will effectively make our app do the same thing, except now all the mapping functionalities are implemented using Mapbox.

I chose this approach b/c it seemed to be the most mentally straightforward, and it would be super easy to switch back to Bing map if we ever needed to. I also had to remind myself that my task was NOT to change anything else, but only to change out the MAPPING API. This was very important to keep in mind in order to stay on task and not introduce new and unnecessary bugs, knowing that I would probably encounter non-mapping things that can be improved.

The result

The mapping aspect of our app behaves beautifully without any issues using the new Mapbox API. The UIs of the map tiles and objects on the map (markers, labels, tooltip box, etc) are somewhat different, but they look just as good as Bing map, if not better. And yes, Mapbox API allowed me to replace 100% of the functionalities offered by Bing map, in case you are wondering. Not only that, it actually improved a feature where our app creates and loads custom tiles. In Bing map, these tiles didn’t always load completely for whatever reason, but in Mapbox they always load completely without any missing.

As far as the project duration, it took me about 12 man days, or about 100 man hours. Of course these numbers are only for our app (which I consider a fairly large mapping app) and maybe totally meaningless to you, but I wanted to give you an idea anyway on the duration. Overall, both my manager and myself are fairly happy with the length of time it took me, and were very glad it didn’t take months.

Up next: What’s in Part 2?

I decided to split this blog post into at least 2 parts for a couple of reasons:

  1. In the second part of this blog series, I will be doing a detailed comparison and contrast of all the similar JavaScript classes/properties/methods between the two mapping APIs used in our app. It’s gonna be pretty long. So If I didn’t split this blog post, it would be a really long post and might be overwhelming to some folks.
  2. I wanted to discuss separately the process and approach I took to tackle this project, versus the technical details. Once I gained enough familiarity and understanding of our custom app and the two APIs, I was able to come up with a plan, and after that point, the technical details were the easier part. So it made sense to split it.

In the second part, I will also talk about how to do the following in Bing map and Mapbox API:

  1. referencing JavaScript and CSS resources
  2. entering access tokens
  3. using the coordinate systems
  4. handling events

I hope you’ve found this post helpful to you. Stay tuned for Bing to Mapbox: Part 2. It’s coming soon!

2 Comments

  1. I work on the Bing Maps team and have worked with a lot of Bing Maps customers and former MapBox customers. When implementing Bing Maps properly, it ends up being significantly cheaper than MapBox. In Bing Maps you generate a billable transaction when a map is loaded, you can pan and zoom and load as many tiles as needed which can often be in the hundreds per user experience, and there is no additional transactions generated. Where as in MapBox, a “MapView” is generated for every 15 tiles loaded.

    Also make sure to take advantage of sessions keys when using an interactive map in Bing Maps. They make all service related transactions non-billable like geocoding and routing.

    Reply

    1. Hi Ricky, thank you for leaving a comment about this. You have brought up a very good topic that I haven’t looked into that much, which I will now. If it is indeed as you said, then I can see how in many scenarios Bing maps can be cheaper than Mapbox. I will forward your message to my team and talk it over with them. It will be good to have this conversation about the different pricing models offered by different map providers such as Bing and Mapbox regardless.

      So that begs me to ask you this question: our web app initially loads the map with the max extent of all the user’s geospatial data, which typically is a large portion of the world. Are you saying that with Bing Maps, no matter how much the user zooms or pans after that point within the max extent, it’s all included within the same billable transaction generated by the initial map load?

      Thanks.
      Chuck

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *