Database Connections with the Virtual Earth Silverlight MapControl CTP

Introduction

It has been long anticipated and finally it arrived as a Community Technology Preview (CTP): The Virtual Earth Silverlight MapControl. To get access to the CTP you need to register at Microsoft Connect. Once you are registered you will have access to an installer which gets you the libraries as well as the offline documentation. There is also an Interactive SDK, a link to a getting stated guide on Via Windows Live and another one that allows you to submit bugs and feature requests.

One of the things that I like particularly about Silverlight is the ability to separate the work of a designer from the developers work. Most developers are quite happy with a button that executes the desired function when you click on it but designers pay much more attention on the details of the presentation. They might look for a button with rounded corners or images in the background and a nice animation when you mouse over it. With Silverlight the developer can put his button on the page and start working in Visual Studio on the code while at the same time the designer can use Expression Blend to work on the style.

image

But aside from that there are a lot of immediate advantages for Virtual Earth:

  • The map rendering is much smoother between zoom-levels since it leverages the DeepZoom technology.
  • The graphics framework is much more powerful not only in terms of animations and integration of videos but also in terms of rendering large numbers of points of interest or more complex polygons.
  • Silverlight provides the same user experience in all browsers and on all platforms. That is not necessarily the case with AJAX, mainly because the implementation of JavaScript is to a certain degree browser-specific. Below you find a graph that shows how different the rendering performance is on my laptop is for the various browsers. Not only is the Silverlight control much faster, it also provides the same performance on all browsers.
    image
  • And finally we can write our code end-to-end in .NET. Remember that with the AJAX control we created an AJAX call to a .NET web service or web handler which then queried the database and returned JSON-objects for our points of interest.
     image
    Well the procedure is pretty much the same with Silverlight but it is now all in .NET  and doesn’t even require half of the lines of code that we needed in AJAX.
    image 

Lets have a look at the last point and create a quick application with the Virtual Earth Silverlight MapControl that connects to a database to retrieve the points of interest in the current map view.

Integrating the Virtual Earth Silverlight MapControl

Before we get started we need to verify that we have the Visual Studio 2008 SP1 and the Silverlight Tools for Visual Studio 2008 SP1 installed. We also need to register at Microsoft Connect and install the Virtual Earth Silverlight MapControl CTP. Once we have prepared our development environment we can start Visual Studio and create a new Silverlight project…

image

…with an ASP.NET Web project.

image

To the Silverlight project (not the Web project) we add now a reference to the Microsoft.VirtualEarth.MapControl.dll. By default this is installed in C:Program FilesMicrosoft Virtual Earth Silverlight Map ControlCTPLibraries.

image

In the Page.xaml we add a reference to our assembly and embed our map. For the map we can already define a number of properties such as the centre point (Center), the zoom-level (ZoomLevel) and the style (Mode). We also define a MapLayer which will host our points of interest as a child of the map. Finally we add a button that will allow us to switch the POI layer on and off.

<UserControl x:Class="VE_SL_DBConn.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:m="clr-namespace:Microsoft.VirtualEarth.MapControl;assembly=Microsoft.VirtualEarth.MapControl">
    <Grid x:Name="LayoutRoot" 
          Background="Black"  
          HorizontalAlignment="Stretch" 
          VerticalAlignment="Stretch">
        <m:Map Name="MyMap" 
               Center="51.461962075378054, -0.9260702133178665"
               ZoomLevel="17"
               Mode="Road">
            <m:Map.Children>
                <m:MapLayer x:Name="MyPOI"></m:MapLayer>
            </m:Map.Children>
        </m:Map>
        <Button 
            Height="25"
            Width="100"
            HorizontalAlignment="Right" 
            VerticalAlignment="Top"
            Click="LoadPoiInMapView_Click">
            <TextBlock x:Name="btnPOI">Get POI</TextBlock>
        </Button>
    </Grid>
</UserControl>

You can already compile the project and have a look at your map but obviously we are not yet connected to our database.

Querying the Database

Now that we have defined our map we prepare the database connection. A quick and simple way to do so is the OR-mapping in the LINQ to SQL classes. In the web project add a new LINQ to SQL mapper.

image

Now simply drag and drop a table from your Server Explorer to the design surface of the dbml file…

image

…and in the properties of the newly created data context set the Serialization Mode to unidirectional.

image

Next we create a web service. We add a Silverlight-enabled WCF Service to our web project.

image

Since we have already mapped the table in our SQL Server to objects we only need a minimum of code. As input parameters we take the bounding box of the current map view in order to reduce the number of returned results. We will determine the bounding box a little bit later. The result is returned as a List of objects.

Imports System.ServiceModel
Imports System.ServiceModel.Activation

<ServiceContract(Namespace:="DataService")> _
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class DataService

    <OperationContract()> _
    Public Function GetPOIinView(ByVal NWlat As Double, _
                                 ByVal NWlon As Double, _
                                 ByVal SElat As Double, _
                                 ByVal SELon As Double) _
                                 As List(Of UK_low_bridges_all)
        Dim datacontext As New HannesPOIDataContext
        Return ((From UK_low_bridges_alls _
            In datacontext.UK_low_bridges_alls _
            Where UK_low_bridges_alls.Latitude <= NWlat And _
                UK_low_bridges_alls.Latitude >= SElat And _
                UK_low_bridges_alls.Longitude >= NWlon And _
                UK_low_bridges_alls.Longitude <= SELon).ToList())
    End Function

End Class

To use this web service in our Silverlight project (not the Web project) we add a Service Reference:

image

Connecting the Map to the Web Service

In order to connect the map to the web service we add some code to our code-file for our page (Page.xaml.vb). First we import the namespaces for our Virtual Earth Silverlight MapControl and our web service. Next we create a procedure that is to be executed when we click on our button (LoadPoiInMapView_Click). To load the POI we add an event handler that fires when the map view changed, i.e. when we finished zooming or panning. This event handler will determine the bounding box of the map and use it as parameters for an asynchronous call to our web service. Once the call returns the result we will render the POI in our map layer.

Imports VE_SL_DBConn.DataServiceReference
Imports Microsoft.VirtualEarth.MapControl

Partial Public Class Page
    Inherits UserControl

    Public Sub New()
        InitializeComponent()
    End Sub

    Public Sub LoadPoiInMapView_Click(ByVal sender As Object, _
                                      ByVal e As RoutedEventArgs)

        If btnPOI.Text = "Get POI" Then
            AddHandler MyMap.ViewChangeEnd, AddressOf MyMap_ViewChanged
            btnPOI.Text = "Remove POI"

            Dim bounds As LocationRect = MyMap.GetBoundingRectangle()
            Dim svc As New DataServiceClient()
            AddHandler svc.GetPOIinViewCompleted, AddressOf svc_GetPoiInMapViewCompleted
            svc.GetPOIinViewAsync(bounds.Northwest.Latitude, _
                                  bounds.Northwest.Longitude, _
                                  bounds.Southeast.Latitude, _
                                  bounds.Southeast.Longitude)
        Else
            RemoveHandler MyMap.ViewChangeEnd, AddressOf MyMap_ViewChanged
            MyPOI.Children.Clear()
            btnPOI.Text = "Get POI"
        End If
    End Sub

    Private Sub MyMap_ViewChanged(ByVal sender As Object, _
                                  ByVal e As MapEventArgs)
        MyPOI.Children.Clear()

        Dim bounds As LocationRect = MyMap.GetBoundingRectangle()
        Dim svc As New DataServiceClient()
        AddHandler svc.GetPOIinViewCompleted, AddressOf svc_GetPoiInMapViewCompleted
        svc.GetPOIinViewAsync(bounds.Northwest.Latitude, _
                              bounds.Northwest.Longitude, _
                              bounds.Southeast.Latitude, _
                              bounds.Southeast.Longitude)
    End Sub

    Private Sub svc_GetPoiInMapViewCompleted(ByVal sender As Object, _
                                             ByVal e As GetPOIinViewCompletedEventArgs)
        If e.Error Is Nothing Then
            For i = 0 To e.Result.Count - 1
                Dim point As New Ellipse()
                point.Width = 10
                point.Height = 10
                point.Fill = New SolidColorBrush(Colors.Red)
                point.Opacity = 0.65
                Dim location As New Location(e.Result(i).Latitude, e.Result(i).Longitude)
                MapLayer.SetMapPosition(point, location)
                ToolTipService.SetToolTip(point, e.Result(i).Name)

                MyPOI.Children.Add(point)
            Next
        Else
            MessageBox.Show("Error occurred while loading POI from database", _
                            "Error", MessageBoxButton.OK)
        End If
    End Sub

End Class

That’s it, we’re done. You will find the sample code here.

image

Summary

In this quick sample we had a look at the database connection for the Virtual Earth Silverlight MapControl. Aside from the fact that we did the coding end-to-end in .NET we could also have a look at the performance and compare the user experience in various browsers.

Yes, using Silverlight may not have the reach of HTML (yet) since you need to install a browser plug-in and most of all since it isn’t supported on all possible platforms and browsers (yet). It isn’t as powerful as the Windows Presentation Framework (WPF) either but it is a great compromise between outreach and richness.

image 

Technorati Tags: ,

Advertisements
This entry was posted in Virtual Earth. Bookmark the permalink.

8 Responses to Database Connections with the Virtual Earth Silverlight MapControl CTP

  1. Scott says:

    Very good information. I didn’t find the database in the VE-SL-DBConn.zip. Would it be possible to include your data with the sample?

  2. Mike says:

    Is there a timeout that may be applicable when loading locations? I have a DB with thousands of locations. When I try to get all of the locations, I get the following error:An exception of type ‘System.ServiceModel.CommunicationException’ occurred in System.ServiceModel.dll but was not handled in user codeAdditional information: The remote server returned an error: NotFoundIf I scale back the number of rows returned, say to 5000, then the app works fine. There is not a consistent number of rows though. In one DB I cant pull out more than 3500 before this error occurs. With another DB, I can pull out over 10,000.Thoughts?Thanks,Mike

  3. Iwan says:

    Thanks for this great post …I wanted to use my own database since you haven’t added yours. No problem, i thought, I have data enough to display. I added a view wit the same name as your table to do less changes when I copy code to try.But I keep getting an error ‘The remote server returned an error: NotFound’on this line of code:Dim _result As System.Collections.ObjectModel.ObservableCollection(Of DataServiceReference.UK_low_bridges_all) = CType(MyBase.EndInvoke("GetPOIinView", _args, result),System.Collections.ObjectModel.ObservableCollection(Of DataServiceReference.UK_low_bridges_all))That’s in the:Public Function EndGetPOIinViewWhich is autgenerated code.I have an Id (guid) , name and longitude, latitufe fields (both float in database).Any idea what I am doing wrong?

  4. Jacek says:

    Thanks! Have you tried connect this with .NET RIA Services?And my second question is, do you think that it is possible to connect OOB (out of browser) and Silverlight VirtualEarth Map in one application? I tried myself but I got some credential erros (at least it showed me messagebox – no debug in OOB :] )Bests,Jacek Ciereszkodzak83@gmail.com

  5. G Andrew says:

    Iwan,The "NotFound" error may indicate an exception in the DataService. If you add the following attribute to the service, and then call the service from the browser, you should be able to see the actual exception:<ServiceBehavior(IncludeExceptionDetailInFaults:=True)> _Alas, I got past that part, and I think I’m successfully returning a list of custom class items (I couldn’t use the LINQ to SQL mapper as I needed to do some string manipulation that isn’t supported by L2S), but when svc_GetPoiInMapViewCompleted gets called, the e argument has no results. Not sure where I’m going wrong with that.

  6. kuppala says:

    The sample is very good. But can any one send me the database file ??? I wanted to test with the database i.e HannesPOI – Thanks Ravi kuppala

  7. Kirk Kuykendall says:

    I have a table with a Geometry column. When I try to drag and drop the table onto the dbml designer, it complains "one or more selected items contain a data type that is not supported by the designer". I presume the geometry column is causing this.Certainly people will want to use VESL with tables containing spatial types. Is this possible with WCF ?

  8. mdhg says:

    Thanks! Have you tried connect this with .NET RIA Services?And my second question is, do you think that it is possible to connect OOB (out of browser) and Silverlight VirtualEarth Map in one application? I tried myself but I got some credential erros (at least it showed me messagebox – no debug in OOB :] )Bests,Jacek Ciereszkodzak83@gmail.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s