Exploring Solutions For the Cloud-Part1
Introduction
I read recently that in just a couple of years over a third of all development will be cloud based. That’s a big shift. So I started to look into some of the technologies and what it takes to develop applications for the cloud. Now to be clear, I think there might be some misconceptions regarding what is a cloud application. I’m not referring to web server based applications. The development that I’m talking about would be applications for platforms like Azure.
In examining this new paradigm I find that there is an overwhelming number of potential opportunities. I say that because I don’t think that the change is going to be to simply to move existing applications to a new environment. Instead I think the technologies, tools, and infrastructure are all in place for a whole new wave of solutions that were previously not feasible.
We may argue, but I believe a key player in these new solutions will be that device we all carry around with us, the cell phone. Actually I don’t think we should call them cell phones any more. Because they are really ‘wireless personal computers’ that happen to also allow you to make phone calls. These devices have the power and capabilities that surpass those of a laptop of just a couple of years ago. Given the availability of broadband speed to support these devices the sky is the limit as far as application capability. And I’m not just talking about cute pastime applets or games; I’m talking about real world business solutions.
So the primary goal here is to explore what it takes to develop applications for Azure, but not just simply the mechanics of packaging and deploying an application. Specifically, I want to explore using Silverlight on both desktop and phone (as a single solution) deployed on Azure. But this goal is still too broad for the purpose of conceptualizing specific applications. So to narrow things down we’ll bring in Bing Maps as the central theme in exploring solutions for the cloud. You’d be amazed at how many other usages can be devised besides the typical usage for traveling directions.
Since Bing Maps will form the core of the exploration we’ll start by getting acquainted with that service and the associated Silverlight control in this article. In the next article I’ll describe some cloud application concepts centered on Bing Maps. At the same time we'll expand on the map functionality presented in this article to highlight some functionality of the concepts. And in the third article we'll cover a complete solution for the cloud, again utlizing Bing Maps.
Getting Started With Bing Maps
In order for you to get access to the map services provided by Microsoft you need to sign up and get an account. You can sign up for a developer account at http://www.microsoft.com/maps/developers/web.aspx. Once you sign up you’ll be able to get a Bing Maps key which you can then use to get free access to the service. All the information you will need is provided on the above link.
We are also going to make extensive use of the Silverlight Map Control so you will need to download that also. You can find the SDK and associated instructions here: http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=beb29d27-6f0c-494f-b028-1e0e3187e830 .
Now that we’re done with the external pre-requisites let’s see how we can apply them. Start by creating a basic Silverlight application, name it SLMapTest and accept the default ASP web hosting. To start with, since we want to use the Map control you’ll need to add a reference for the dlls to the project (see below). You should find them in the Program Files folder under Bing Maps Silverlight Control-Libraries.

Now add the map control to your page, along with the appropriate namespace, as shown below. Note that you will have to insert your own Bing Maps Credentials key (in place of 'Your Key') in order to get access to the service.
xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl" ... <Grid x:Name="LayoutRoot" Background="White"> <m:Map x:Name="bingMap" CredentialsProvider="Your Key"> </m:Map> </Grid> ...
Compile and run. You have just provided your user with a fully interactive map. The user can scroll through the world map, change view modes, and zoom in to any desired area. Not bad for essentially no work on our part. Although that's not very impressive from the user's perspective (they can do that with Bing), it does prove that we have all the necessary pieces hooked up correctly.
Now let’s add some basic functionality that will allow the user to enter a desired location/address and then have the system display a close up view of the area if it was found. Modify the page as shown below.
<m:Map x:Name="bingMap" CredentialsProvider="Your Key">
<TextBox Height="23" HorizontalAlignment="Right" Margin="0,26,50,0" Name="textAddress" VerticalAlignment="Top" Width="120">
</TextBox>
<Button Content="Find" Height="23" HorizontalAlignment="Right" Margin="0,26,0,0" Name="buttonFind" VerticalAlignment="Top" Width="44" Click="buttonFind_Click">
</Button>
<TextBlock Height="23" HorizontalAlignment="Right" Name="textResult" VerticalAlignment="Top" Width="166"/>
</m:Map>
All we've done is to add a textbox for user entry, a button to invoke the request, and a textblock to display any abnormal results. Here is what it will look like after we've hooked up things and the user has entered a location.

You have programatic control of the map control through the methods and properties that it exposes (the documentation provided with the SDK has full description). The method we are interested in is SetView which centers the map on a set of coordinates that corresponds to the address of the location that the user entered. Unfortunately the map control does not have a method which will accept a street address, only geo coordinates (latitude/longitude). That means that we have to perform the translation between a location address (as a string) and geo coordinates. Fortunately for us Microsoft makes available a service which provides that functionality.
To continue with the project we'll need to set up a proxy to the Bing GeoCode service which will provide the translation we need. Right click on the solution explorer refence node and select “Add Service Reference…”. Type in the following for the address: http://staging.dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl . Click GO to retrieve the file. Once the file is found and loaded you should see the contract definition for the service in the left pane. Before you hit OK to have the wizard generate the proxy, make two additional changes. First, change the default namespace to something more descriptive like “BingGeocodeService” or whatever you’d like. The proxy class that gets generated by default brings in some type definitions that will clash with types already defined in the map control. To elliminate this, click on the Advanced button and then select “Reuse types in specified reference assemblies”. Proceed by selecting the two map assemblies. This will eliminate those definitions from the generated proxy namespace. Finally click OK to generate the proxy.
In order for us to make use of the service add a member variable for the proxy in the code behind file as shown below (don't forget the namespace).
#region private property
private BingGeocodeService.GeocodeServiceClient geocodeClient;
private BingGeocodeService.GeocodeServiceClient GeocodeClient
{
get
{
if (null == geocodeClient)
{
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.None);
UriBuilder serviceUri = new UriBuilder("http://dev.virtualearth.net/webservices/v1/GeocodeService/GeocodeService.svc");
//Create the Service Client
geocodeClient = new BingGeocodeService.GeocodeServiceClient(binding, new EndpointAddress(serviceUri.Uri));
geocodeClient.GeocodeCompleted += new EventHandler(GeocodeCompleted);
}
return geocodeClient;
}
}
We are ready to start hooking things together. Create an event handler for the button Click event. This will occur when the user depresses the Find button. In that handler we'll add some code that will use our newly created proxy to make a call to the Bing Geocode service. The contract indicates a method, appropriately named GeocodeAsync, which can take an address string (in the form of a query) and return, through a callback, the latitude/longitude values for the location. We will then in turn, pass those values to the map control to center the view around the coordinates.
Since the call to the service is an asynchronous call, we created an event handler (GeocodeCompleted) for the reply when the endpoint was being instantiated (see above). In the button click event handler we grab the address string the user entered and pass it to a helper method, GeocodeAddress, where the call to the service is made. The following code shows the three methods.
private void buttonFind_Click(object sender, RoutedEventArgs e)
{
//Make sure there's something there
if (textAddress.Text.Length > 0)
{
GeocodeAddress(textAddress.Text);
}
}
...
private void GeocodeAddress(string address)
{
//Pack up a request
BingGeocodeService.GeocodeRequest request = new BingGeocodeService.GeocodeRequest();
request.Query = address; //what user entered
// Don't raise exceptions.
request.ExecutionOptions = new BingGeocodeService.ExecutionOptions();
request.ExecutionOptions.SuppressFaults = true;
// Only accept results with high confidence.
request.Options = new BingGeocodeService.GeocodeOptions();
//ObservableCollection is the default for Silverlight proxy generation.
request.Options.Filters = new ObservableCollection<BingGeocodeService.FilterBase>();
BingGeocodeService.ConfidenceFilter filter = new BingGeocodeService.ConfidenceFilter();
filter.MinimumConfidence = BingGeocodeService.Confidence.High;
request.Options.Filters.Add(filter);
request.Credentials = new Credentials(); //Need to add your key here
request.Credentials.ApplicationId = (string)App.Current.Resources["BingCredentialsKey"];
//Make the call
GeocodeClient.GeocodeAsync(request);
}
...
private void GeocodeCompleted(object sender, BingGeocodeService.GeocodeCompletedEventArgs e)
{
string callResult = "";
try
{
//Was the service able to parse it? And did it return anything?
if (e.Result.ResponseSummary.StatusCode != BingGeocodeService.ResponseStatusCode.Success ||
e.Result.Results.Count == 0)
{
callResult = "Could not find address.";
}
else
{
// Center and Zoom the map to the location of the item.
bingMap.SetView(e.Result.Results[0].Locations[0], 18);
}
}
catch
{
callResult = "Error processing request.";
}
textResult.Text = callResult;
}
Try it. Compile and run the application to make sure you can access the geocode service. Yeah I know, you can just go to Bing maps and get a lot more information returned. But the plan is not to provide that type of service but instead make use of what's readily available in new ways. At this point we are still just checking the plumbing. But before we start on the road of exploring new functionality that we can create using the map control, I think I'd like to take a little detour into the land of MVVMness. Primarily because once we start adding more code things will get pretty messy if we continue with our current approach. And secondarily because…
MVVMness
There is a lot to be said about MVVM. And in fact a simple search will overwhelm you with ALL that is being said. How can there be so much diversity in opinions, and approaches to a pattern? A pattern by definition is supposed to do the opposite, that is, provide a simple easy to understand approach to solving a problem. A pattern is a communication mechanism. In my opinion we’re missing the forest for the trees.
If we step back and look at it from another perspective perhaps it may become clearer (or not). I think, as a community, we’ve come to a realization of what we want (and need) and are voicing it with the 'umbrella' term MVVM. So I think it really represents our ‘desire’ for all the goals of good design: separated presentation; separation of concerns; testability; etc. That’s too much to be defined as a pattern.
Martin Fowler writing about MVC here states : “It's often referred to as a pattern, but I don't find it terribly useful to think of it as a pattern because it contains quite a few different ideas.” MVVM, being a variation of MVC, would fall under the same critique. And in this blog on MVVM, John Grosman writes: “My team has been using the pattern feverishly for a couple of years, and we still don't have a clean definition of the term ViewModel.”(Note, emphasis mine). “One problem is (that) ViewModel actually combines several separate, orthogonal concepts: view state, value conversion, commands for performing operations on the model.”
Each of the ‘orthogonal concepts’ mentioned above could by itself be described by its own pattern. And not only is it too much stuff to describe as a simple pattern, the mechanisms to implement those 'orthogonal concepts' have not been there (they have been dribbling in over time). In addition, the support that has been added, has varied between the platforms! That should be enough to explain why there is so much confusion surrounding MVVM, but there is more in my opinion.
If an application consisted simply of a single view and its associated ViewModel/Model, then things could be OK (after you figured out how to implement the ‘orthogonal concepts’). However, rarely are things that simple. In even the simplest applications there will be several views. In fact, simply displaying a dialog constitutes a separate view. Typically you’ll have several views which will undoubtedly have some state/data linkage to each other. Buying into the separation of concerns requires that there be some kind of messaging infrastructure available to the viewmodels. This is one additional hole that exists in the support required to implement MVVMness. Fortunately this gap can be filled through the use of various community toolkits and libraries. The dilemma with this approach is that the lifetime of your application may be longer than the support from the community. AND Microsoft may have other plans which may not be completely in line with the library you selected. So hopefully a messaging mechanism will be incorporated into future releases of the .Net framework (and a dependency injection facility would be nice too).
Breaking Up Is Hard To Do
Yeah, I know. Most readers won’t relate. Anyway, within the context of our sample application, the break up is going to be facilitated by using the MVVM Light toolkit which you can find here. The toolkit provides several 'facilities' that assist in pursuing MVVMness, including: a mechanism to tie the view and the viewmodel together; an implementation for ICommand; and a nice messaging mechanism. And it also integrates nicely with Visual Studio and Blend. There are others toolkits and libraries available, I just happened to use this one for this application.
Once you’ve installed the MVVM Light toolkit, the first thing that’s needed to continue with our project is to add references to the GalaSoft MvvmLight library dlls. There are separate libraries for the different platforms, so pull in the ones for Silverlight4 for this project. Then create a folder in the project, call it ViewModel and add a MvvmViewModel(SL) as 'MainViewModel, and a MvvmViewModelLocator(SL) as 'ViewModelLocator', to the new folder. These templates were added as part of the MvvmLight installation.
The MvvmLight template classes provide commented instructions within them that indicate what’s needed. But we’ll go through the steps here. First, add the ViewModelLocator to the application resources (in App.xml) as shown below.
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="SLMapTest.App"
xmlns:vm="clr-namespace:SLMapTest.ViewModel"
mc:Ignorable="d">
<Application.Resources>
<!--Global View Model Locator-->
<vm:ViewModelLocator x:Key="Locator"
d:IsDataSource="True" />
</Application.Resources>
</Application>
Separated presentation in MVVMness means that the View and it's associated ViewModel can be designed independently. However, at some point they need to be introduced to each other. One mechanism to accomplish this is provided by the aptly named ViewModelLocator. It is essentially a global lookup for a View:ViewModel association. So we'll continue by adding an entry entry in the ViewModelLocator for the new ViewModel class we created above, MainViewModel. You can do this with a code snippet provided with the MvvmLight installation and described in the ViewModelLocator template comments. The end result is that the MainViewModel is added as a bindable property to the class.
Now we can bind the MainPage view to the associated MainViewModel class by modifying the MainPage.xml as follows.
...
xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400"
DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelMain}">
...
If you compile and run the application you may notice that nothing really has changed. But if you place a breakpoint in the MainViewModel class constructor you’ll see that it is indeed being created, so now we just need to make use of it.
So the whole idea behind MVVMness is to have as little as possible (or nothing) in the code behind file so that the View can be designed independently from the business logic (starting with the ViewModel), and that the business logic can also be tested independently from the View, thus requiring no user interaction. However, I think that the former should be a goal not a mandate. If you have to complicate the application to an extreme simply to eliminate something from the code behind, stop and think about it. Is the result worth the effort or complexity created?
Continuing with our project, in order for the MainViewModel to support MainPage (View) we need to add some binding properties. Specifically, we need support for the the button and two text boxes. The code below shows the class ready for binding with the View.
public class MainViewModel : ViewModelBase
{
RelayCommand findButton;
string findString;
string resultString;
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
findButton = new RelayCommand(FindButtonClick);
}
#region Commanding
public ICommand FindButtonCommand
{
get { return findButton; }
}
void FindButtonClick()
{
}
#endregion
#region data context
public string FindString
{
get { return findString; }
set { findString = value; }
}
public string ResultString
{
get { return resultString; }
set { resultString = value; }
}
#endregion
}
If you bring up the properties window for the controls you’ll be able to do all of the bindings interactively, it beats typing. But make sure you compile first otherwise the bindable properties won’t show up. Here is how the binding was defined.
...
<TextBox Height="23" HorizontalAlignment="Right" Margin="0,26,50,0" Name="textAddress" VerticalAlignment="Top" Width="120" Text="{Binding Path=FindString, Mode=TwoWay}">
</TextBox>
<Button Content="Find" Height="23" HorizontalAlignment="Right" Margin="0,26,0,0" Name="buttonFind" VerticalAlignment="Top" Width="44" Command="{Binding Path=FindButtonCommand}">
</Button>
<TextBlock Height="23" HorizontalAlignment="Right" Name="textResult" VerticalAlignment="Top" Width="166" Text="{Binding Path=ResultString}" Foreground="#FFEA1818" />
...
Now we can move the remaining code that we had in the code behind file for MainPage to its ViewModel. You can peruse through the complete code in the downloadable project.
There’s only one hiccup at this point (there will be many others) in moving the code out of the code behind file. The MainViewModel class does not know about the map control. And it shouldn’t. The map control is controlled through method calls so there is no easy binding mechanism that allows access to all the functionality we’ll need. I did some searching to see if there was a quick answer to the problem but did not come up with anything. I also know that I intend to add some more interaction than is typical for a map viewer so I don’t want to paint myself into a corner from the beginning. If I later find a way to move the functionality to the ViewModel and make it cleaner I’ll do it then. For now we’ll leave some of that interaction in the code behind file for MainPage.
So how can the MainViewModel handle the button click message but have the view react to the event without the MainViewModel having a linkage to the view? The answer is to use messages. Included with the MvvmLight Toolkit is a nice generic messaging infrastructure. It’s essentially a publication service that allows subscribers to ‘register’ to receive a message and publishers to ‘send’ (publish) a message. It is very similar to the EventAggregator available in Prism.
In our situation we can have the MainPage (View) register to be notified when the MainViewModel processes the button click event. The following code shows the change in both classes. First a definition of a SetMapViewMsg message.
namespace SLMapTest.Messages
{
public struct SetMapViewMsg
{
public Location CenterLocation;
}
}
The message contains the latitude/longitude values for the translated address the user entered, as a Location property. The MainPage (View) subscribes to the message since it knows what to do with the values, that is, pass them to the map control. And the MainViewModel publishes the messages since it has access to the service which does the translation. Here's how the subscription is done.
public MainPage()
{
InitializeComponent();
//Subscribe to message, we know what to do with user input
Messenger.Default.Register<SetMapViewMsg>(this, SetViewHandler);
}
#region message handler
void SetViewHandler(SetMapViewMsg msgData)
{
bingMap.SetView(msgData.CenterLocation, 18);
}
#endregion
And here is the revised GeocodeCompleted in MainViewModel to implement the publication.
...
else
{
//What are we getting back?
Location geoLocation = new Location(e.Result.Results[0].Locations[0].Latitude, e.Result.Results[0].Locations[0].Longitude);
// Zoom the map to the desired location
Messenger.Default.Send<SetMapViewMsg>(new SetMapViewMsg() { CenterLocation = geoLocation });
}
...
Now if we compile and run the application we should be back to where we were but with a better foundation to add the additional functionality to come. But before we start on that, there is just one annoying (to me) part of the UI that needs to be addressed.
It's The Little Things
When the user enters an address in the textbox the most natural action is to terminate it with the ENTER key. But as you can see, if you run the app, nothing happens. The user needs to click on the button in order to process the entry. That’s annoying, so I think we need to address that. The result we want is that when the keyboard ENTER key is depressed (for the textbox) the system behaves the same way as if the Find button was depressed. It’s just more intuitive.
To do this we need to inspect each character that is being entered so we know when the ENTER key comes through. Normally you can do this by implementing a handler for the KEYUP event. But since we are pursuing MVVMness we can achieve that functionality using behaviors and specifically in this solution we can make use of the EventToCommand behavior provided with the MvvmLight Toolkit. The cool feature here is that it allows us to pass the event arguments which we need. Here is the change for the MainPage xaml. It essentially generates a method call to KeyUpCommand, passing to the method the event parameters, whenever the KeyUp event is generated on the textbox.
... <TextBox Height="23" HorizontalAlignment="Right" Margin="0,26,50,0" Name="textAddress" VerticalAlignment="Top" Width="120" KeyUp="textAddress_KeyUp" Text="{Binding Path=FindString, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<cmd:EventToCommand Command="{Binding Path=KeyUpCommand, Mode=OneWay}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
...
As you can see we are setting a trigger on the KeyUp event which will call the method (delegate) defined by the KeyUpCommand and we are passing the Event Args to the method. So in the MainViewModel we have to create the RelayCommand (which implements ICommand) property and define the method to be called for each KeyUp event. Here’s the code in summary form (you can see the completed code in the downloadable project).
…
RelayCommand<KeyEventArgs> keyUpCommand;
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
findButton = new RelayCommand(FindButtonClick);
//We want to know when user presses ENTER in the find address text field
keyUpCommand = new RelayCommand<KeyEventArgs>(TextFieldCharEntry);
}
…
public ICommand KeyUpCommand
{
get { return keyUpCommand; }
}
void TextFieldCharEntry(KeyEventArgs e)
{
//If it's ENTER key...
if (e.Key.Equals(Key.Enter))
{
if (findAddress != null && findAddress.Length > 0)
{
GeocodeAddress(findAddress);
}
}
}
…
Pretty straightforward on this side, right? So go ahead and compile and run the application. Enter an address and press the ENTER key in the textbox to verify you don’t need to use the Find button.
Almost…But Not Exactly
If you were following along you would have noticed that nothing happened! So let’s see if we’re at least getting the keystroke events. Place a breakpoint inside the block that checks for the ENTER key shown in the code block above. Run it again. You’ll note that the characters are indeed being passed and the ENTER key is being detected. But if you examine the findAddress property you’ll notice that it is null! And that’s why the code is not being executed. The problem is that the textbox does not perform the binding update until it loses (input) focus. Which makes sense, but causes us a problem as you can see. That is also why it works when the button is pressed (focus changed to the button).
Since we are getting each character as it is being entered we could just update the local variable (for the address) at the same time we are checking for the ENTER key. But there is another way that may be more appropriate and general, or just maybe more elegant. And this also demonstrates that there can be code in the code behind file which is completely appropriate and does not detract from MVVMness. I don't think it takes anything away from the testability of the ViewModel.
The solution is to add a KeyUp event handler to the MainPage in the code behind file. Then, in the handler, we can force the binding update when the ENTER key is detected. Here’s the code for handler.
…
private void textAddress_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Enter)
{
//We need to force the update manually...
var binding = textAddress.GetBindingExpression(TextBox.TextProperty);
binding.UpdateSource();
}
base.OnKeyUp(e);
}
…
That’ll do it. Now compile and run the application. When the user presses the ENTER key the system responds in the same manner as pressing the Find button.
The Goal
NOW we are ready to start adding some new map related functionality to the application. We've got a good foundation to build on. We'll be looking at the map control with the goal of seeing how it could be used to improve typical business processes as well as how it might be used to create new and novel solutions. However, even though Bing Maps is the visual glue, the final goal though is to tie the triumvariate of Silverlight, Azure, and Phone into a complete solution, that's my ultimate goal.
So in part 2 we'll continue by learning how to draw on the map, we'll do reverse geocode, routing, and other cool stuff. To be able to implement some of that we'll make use of some other Bing Maps services. That's as far as I can see from this vantage point but I'm sure there are going to be some surprises and challenges along the way.
RSS feed for comments on this post. TrackBack URI