Recent Blog Posts RSS
ViaWindowsLive on Via Virtual Earth Blog
The new ViaWindowsLive community site has launched and features not only a definitive set of resources on all Live Services from Microsoft but also a special section on Virtual Earth including a new site gallery for you to upload your sites, new articles on Version 6, including getting started guide, an interactive quick guide, location finder and more. Subscribe to the VWL aggregated blog to stay in touch with everything Live Services related. Find all the great content from this site and much, much more. Explore how other Live Services can compliment Virtual Earth and your applications.
Version 5 URL changed - Error: 'VEMap' is undefined on Via Virtual Earth Blog
It has been reported that the old url to access the Version5 javascript for Virtual Earth no longer works. This is effecting sites worldwide.
The correct way to reference the Version 5 javascript is:
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5"></script>
If you have been effected a forum thread has been started here
Silverlight Virtual Earth viewer on Via Virtual Earth Blog
With the launch of silverlight yesterday I was digging around and found this viewer for Virtual Earth by Greg Schechter. It does use the 1.1 alpha of silverlight. It gives some interesting ideas for where Virtual Earth could be headed. Certainly the demo of the performance of silverlight compared to javascript for processing showed a significant increase. This could be very useful.
And of course on the gamer front check this out by Andy Beaulieu and shoot down some UFO's over Birdseye images.
John.
So much new Virtual Earth Imagery Worldwide. on Via Virtual Earth Blog
I subscribe to all the VE blogs and recently the posts about updated imagery has been more and more frequent.
The latest is here and for myself downunder we saw three updates, Canberra, Newcastle and Uluru:


Derek Chan posts 3 Articles in a month! on Via Virtual Earth Blog
A big thank you to the efforts of Derek Chan who posted his third VE article today (he actually had it ready weeks ago but had to wait for Mr Bottleneck here at VVE ;) )
The 3 articles are all relivant to Version 5 of Virtual Earth and deal with the Mini Map, debugging javascript and now custom pins in routes.
All these can now be found in our articles section.
If you have something to contribute send us an email.
John (The bottleneck)
Integrating Virtual Earth and Ruby on Rails RSS
This article is written for an old version of the Virtual Earth platform. While still available for reference purposes, it is unlikely to work if implemented.
It's time to once again visit Microsoft's MapSearchControl. This time, we'll be integrating the control into the current darling of the "Web 2.0" movement - Ruby on Rails (aka RoR).
If you are unfamiliar with the basic setup of the MapSearchControl, you must read about our ASP.NET implementation and our PHP implementation. Our Ruby on Rails implementation will not break any new ground with MapSearchControl, so I will focus more on the Ruby and Rails side.
Ruby, and Ruby on Rails.
Ruby is a brilliant little language initially created by Yukihiro Matsumoto. It has gained a cult following due to its concise and elegant syntax, object orientation, and extensive standard library.
However, Ruby didn't really hit the big time until the Ruby On Rails framework came about. RoR is billed as a "full stack, open source web framework." What this boils down to is that it's a very well put together MVC framework, with a truckload of code generators that enable you to churn out code at an alarming rate.
Getting started with RoR
If you are completely unfamiliar with Ruby and RoR, I would suggest starting with one of the many tutorials available on the RoR documentation website. One of the quickest will be this O'Reilly OnLamp article.
InstantRails is a great way to get started quickly.
The rest of this tutorial will assume that you have, at bare minimum, installed Ruby, RoR, and worked through at least one basic tutorial.
Our Virtual Earth RoR application.
The first thing we must do is create our RoR framework for our Virtual Earth application. In RoR we achieve this by running the command:
rails virtualearth
This creates a directory called 'virtualearth'. The contents of this folder are covered in most basic RoR tutorials; we assume you have a passing familiarity with them.
Overview of controllers and views
Recall that RoR takes HTTP requests and initially maps these to a controller, which is simply a Ruby class. RoR automatically determines what class method must be called for a particular request.
The controller method then has an opportunity to perform business logic and instantiate variables, before RoR passes the request on to the corresponding view. The view is a HTML page with embedded Ruby instructions, and may access certain variables created by the controller.
For our Virtual Earth page, we will need to generate a basic controller and then provide three methods: index, what, and ads. 'index' will serve up our basic HTML page, and 'what' and 'ads' will proxy search requests to MSN as we did in our ASP.NET and PHP examples.
Creating the controller.
To create the empty template for this controller, we must again use RoR's code generator scripts. Note that in this RoR app we have no need to generate a model, as we are not accessing any data source.
We will create a controller simply called 've'. From inside the virtualearth directory, we issue the command:
./script/generate controller ve
Or from within an InstantRails installation:
ruby script\generate controller ve
RoR automatically creates a variety of template files that we can begin to edit. The main controller is located at "app/controllers/ve_controller.rb".
Our RoR controller
Let's dive right in and look at the completed controller. Feel free to cut & paste this code into ve_controller.rb. We'll soon step through this code in more detail to discuss some of Ruby's syntactic idiosyncracies.
class VeController < ApplicationController
public
def index
end
def what
expectedArgs = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'i', 'r' ]
render :text => queryMsnSearch(expectedArgs, "http://virtualearth.msn.com/search.ashx")
end
def ads
expectedArgs = [ 'a', 'b', 'c', 'd' ]
render :text => queryMsnSearch(expectedArgs, "http://virtualearth.msn.com/Ads.ashx")
end
private
def queryMsnSearch(expectedArgs, searchUrl)
foundItems = Array.new
uri = URI.parse(searchUrl)
expectedArgs.each do |arg|
if @params.has_key?(arg)
foundItems << "#{arg}=#{@params[arg]}"
end
end
Net::HTTP.start(uri.host, uri.port) do |http|
response = http.post(uri.path, foundItems.join("&"))
return response.body
end
end
end
end
The Index method
We have deliberately defined an empty 'index' method on our class. 'index' will be called as the default page when users access our controller. Since there is no logic behind serving the simple index page, we can go straight to creating the view. In a more complex view, we might access or render some variables instantiated in our controller class method.
The corresponding view for method 'index' on class 've' will be located at "app/views/ve/index.rhtml" relative to the virtualearth directory.
Create this file and edit it. This file will look very similar to our ASP.NET and PHP versions, except for changes to the location of the what and ads pages.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Sample 1</title>
<link href="http://dev.virtualearth.net/commercial/v1/VE_MapSearchControl.css" type="text/css" rel="stylesheet"/>
<script src="http://dev.virtualearth.net/commercial/v1/VE_MapSearchControl.js">
</script>
</head>
<script>
var map = null;
function MyOnLoad()
{
map = VE_MapSearchControl.Create(
47.6, -122.33, 12, 'r', "absolute",
10, 10, 600, 500,
"/ve/what",
"/ve/ads");
document.getElementById("contents").appendChild(map.element);
}
</script>
<body onLoad="MyOnLoad()">
<div id="contents" style="font-size:10pt">
</div>
</body>
</html>
Fire up!
At this point you can actually fire up the RoR built in web server and verify that what we've done works. Issue the following command:
./script/server
Or from within an InstantRails installation:
ruby script\server
Now visit http://localhost:3000/ve/. You should see our familiar Virtual Earth map, and be able to search as per normal.
If you are anything like me, you'll be quite impressed by the succinctness of Ruby and the elegance of the Ruby on Rails framework. Alternatively, you might be perplexed by Ruby's syntax - in which case read on for a more detailed discussion.
About the 'what' and 'ads' methods
While writing this part of the article I got pretty excited about Ruby. I love languages that are terse, but easy to understand. After writing a few methods, I started to guess the required syntax rather than constantly consult the reference documentation - and was very satisfied to find my guesses almost always worked! Ruby truly follows the Principal of Least Surprise - once you start writing Ruby you won't be unpleasantly surprised by interface inconsistency.
def what
expectedArgs = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'i', 'r' ]
render :text => queryMsnSearch(expectedArgs, "http://virtualearth.msn.com/search.ashx")
end
def ads
expectedArgs = [ 'a', 'b', 'c', 'd' ]
render :text => queryMsnSearch(expectedArgs, "http://virtualearth.msn.com/Ads.ashx")
end
As in our PHP example, we have factored out the guts of these methods into a function called queryMsnSearch. The only thing that changes between the two is the expectedArgs array and the URL which we're querying.
Something to note is that rather than letting the method fall through into a 'view' template as we did with 'index', we have instead rendered some output directly to the browser. In most circumstances you would avoid this as it violates the principal of the MVC, but it makes sense in this scenario as we're just proxying a page.
To read up more on the render method, see the RoR documentation for ActionController::Base.
Creating the queryMsnSearch helper function
private
def queryMsnSearch(expectedArgs, searchUrl)
foundItems = Array.new
uri = URI.parse(searchUrl)
expectedArgs.each do |arg|
if @params.has_key?(arg)
foundItems << "#{arg}=#{@params[arg]}"
end
end
Net::HTTP.start(uri.host, uri.port) do |http|
response = http.post(uri.path, foundItems.join("&"))
return response.body
end
end
Again, this is not dissimilar from how we implemented this routine in PHP. Remember, the purpose of this routine is to pass a series of HTTP arguments on to another URL, but only the ones listed in expectedArgs.
Firstly, note that we're creating queryMsnSearch as a private method of the class. This means that attempts to access /ve/queryMsnSearch via HTTP will fail.
uri = URI.parse(searchUrl)
Ruby is an object oriented language. URI is a standard library object that helps us manipulate URIs. Once we have parsed the URI we can do neat things with it, such as extract the path, the host, and the port.
expectedArgs.each do |arg|
...
end
This is essentially the equivalent of a foreach block. What we're doing here is calling method 'each' on array expectedArgs. As an argument to 'each', we're passing a block, denoted by do ... end. This will called for every element of the array, and inside that method the current array element will be called 'arg'.
'each' is a method that's part of the Array class, which is documented in the Core API documentation
if @params.has_key?(arg)
foundItems << "#{arg}=#{@params[arg]}"
end
The first line reads pretty easily. It says "if params has a key named arg". Note that '@' in Ruby denotes an instance variable of a class. @params is automatically provided to our class because we're a child of class ActionController. Also note that we can tell has_key can be used in a boolean context because of the trailing '?' in the method signature.
If the test returned true, we push a value on to foundItems. This is done with the << syntax. All we're actually pushing into foundItems is a string. In a Ruby string, the #{something} construct is interpolated to whatever the value of 'something' is. In our case, it's the variable arg, followed by, "=", followed by the value of the matching key inside the hash @params.
Remember that everything is an object in Ruby, so if we did:
foundItems << "#{arg}=#{@params[arg]}".length
We would actually push the length of that string into foundItems instead. Cool.
Net::HTTP.start(uri.host, uri.port) do |http|
response = http.post(uri.path, foundItems.join("&"))
return response.body
end
This neat construct uses a few concepts we've already come across, so we won't delve too deeply. We call the Net::HTTP.start method, passing the host and port that we parsed out of the URI earlier.
The 'start' method accepts a block with a single argument, 'http'. Why a block? Because at the end of this block, Net::HTTP will conveniently close the socket on our behalf.
Inside the block we simply call the post method against the URI's path. We also pass the result of foundItems.join, which is a string made from joining the elements of foundItems with the specified character, in this case "&".
The HTTP response is collected, and we return the body to the caller.
In summary
It should be pretty clear from this article that Ruby on Rails is an excellent platform from which you can leverage Virtual Earth. RoR's extensive support for web services and AJAX would make it a piece of cake to pull in a rich data source and start to map it on Virtual Earth.
Article contributed by Luke Burton. Have you got something to contribute?


