<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blog.trivadis.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Michael Könings Blog</title><link>http://blog.trivadis.com/b/michaelkoenings/default.aspx</link><description>a generalist&amp;#39;s specialties</description><dc:language>en</dc:language><generator>Telligent Community 5.6.583.24393 (Build: 5.6.583.24393)</generator><item><title>TVDLunch: nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 7)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2011/06/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-7.aspx</link><pubDate>Sat, 04 Jun 2011 15:14:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:177155</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=177155</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2011/06/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-7.aspx#comments</comments><description>&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx"&gt;ersten Teil&lt;/a&gt; habe ich eine groben &amp;Uuml;berblick &amp;uuml;ber das Projekt gegeben.&lt;/p&gt;
&lt;p&gt;Im zweiten Schritt haben wir Windows Azure Cloud Services &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx"&gt;einbezogen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx"&gt;dritten Teil&lt;/a&gt; haben wir angeschaut, was uns OData und WCF Data Services und das Entity Framework 4 (EF4) bringen k&amp;ouml;nnen.&lt;/p&gt;
&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/02/25/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-4.aspx"&gt;vierten Teil&lt;/a&gt; haben wir mit einer ASP.NET MVC Seite die OData-Daten als Webservice aufgerufen und als kleine Fotos auf eine Bing Map gezeichnet.&lt;/p&gt;
&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/03/11/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-5.aspx" title="TVDLunch Teil F&amp;uuml;nf"&gt;f&amp;uuml;nften Teil&lt;/a&gt; werden haben wir mit AJAX CRUD Operationen gegen unseren Azure OData Service ausgef&amp;uuml;hrt.&lt;/p&gt;
&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/03/21/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-6.aspx"&gt;sechsten Teil&lt;/a&gt;&amp;nbsp; haben wir die Spatial Features von SQL Server verwendet, um Entfernungen zwischen uns und unseren Kollegen zu&amp;nbsp; berechnen.&lt;/p&gt;
&lt;p&gt;Endlich komme ich dazu, den siebten Teil dieser kleinen Serie zu schreiben. Wir wollen heute die gleiche Anwendung, die wir schon in den vorangegangenen Beitr&amp;auml;gen als ASP.NET MVC L&amp;ouml;sung realisiert haben, auf das Windows Phone 7 bringen! Eigentlich hei&amp;szlig;t es ja nur noch&amp;nbsp; &amp;ldquo;Windows Phone&amp;rdquo;, gemeint ist aber die neue Generation, die Silverlight und XNA unterst&amp;uuml;tzt, nicht die &amp;ldquo;alte&amp;rdquo; Plattform&amp;nbsp; (die nach wie vor von MS unterst&amp;uuml;tzt wird) die bis Version 6.5 hochgez&amp;auml;hlt wurde.&lt;/p&gt;
&lt;p&gt;Diese Beispiel-App hat massgeblich mein gro&amp;szlig;artiger Trivadis-Kollege &lt;a href="http://blog.trivadis.com/blogs/thomashuber/default.aspx"&gt;Thomas Huber&lt;/a&gt; geschrieben, der auch der Autor von &lt;a href="http://www.amazon.de/gp/product/383621413X?ie=UTF8&amp;amp;tag=trinity07-21&amp;amp;linkCode=as2&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;creativeASIN=3446412018"&gt;2 hervorragenden B&amp;uuml;chern&lt;/a&gt; &amp;uuml;ber WPF und Silverlight ist! &lt;/p&gt;
&lt;p&gt;ein Hinweis: Diese App wird es sicher nicht in den Zune Marketplace schaffen, dazu fehlen ein paar wichtige Dinge. Vor allem eine verl&amp;auml;ssliche Security Infrastruktur. Hier bieten sich die Azure AppFabric Komponenten an, die es erm&amp;ouml;glichen einen Service mit den ben&amp;ouml;tigten security features auszustatten.&lt;/p&gt;
&lt;p&gt;Diese App soll in erster Linie Ihre Fantasie anregen, um dann vielleicht irgendwann eine eigene App Idee zu verwirklichen. In Zukunft wird MS (hoffentlich) Business Applikationen f&amp;uuml;r geschlossene Benutzerkreise f&amp;uuml;r das Windows Phone erm&amp;ouml;glichen. Ger&amp;uuml;chte im Umfeld des gro&amp;szlig;en Mango Updates (angek&amp;uuml;ndigt f&amp;uuml;r Q4 2011) lassen darauf hoffen. Der Marketplace Deployment Mechanismus muss also um die F&amp;auml;higkeit erweitert werden, eine App z.B. nur innerhalb einer Firma zu verteilen. Erst dann macht eine solche App richtigen Sinn.&lt;/p&gt;
&lt;p&gt;Hier ein paar Screenshots von unserer Beispiel-App:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/Phone1_62DC26FE.png"&gt;&lt;img height="244" width="148" src="http://blog.trivadis.com/blogs/michaelkoenings/Phone1_thumb_70423A04.png" alt="Phone1" border="0" title="Phone1" style="border-width:0px;margin:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hier kann man Daten eingeben, f&amp;uuml;r Ort und Zeit des geplanten Mittagessens und anschliessend an den Server &amp;uuml;bertragen.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone3_2.png"&gt;&lt;img height="244" width="148" src="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone3_thumb.png" alt="Phone3" border="0" title="Phone3" style="border-width:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Aus dem Men&amp;uuml; kann man die Kartenansicht und die Telefonliste ausw&amp;auml;hlen:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone2_2.png"&gt;&lt;img height="244" width="148" src="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone2_thumb.png" alt="Phone2" border="0" title="Phone2" style="border-width:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;interaktive Kartenansicht mit den Bildchen der Kollegen&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone4_2.png"&gt;&lt;img height="244" width="148" src="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone4_thumb.png" alt="Phone4" border="0" title="Phone4" style="border-width:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Telefonliste der Kollegen in der N&amp;auml;he.&lt;/p&gt;
&lt;h3&gt;Was wird ben&amp;ouml;tigt ?&lt;/h3&gt;
&lt;p&gt;Alles was man f&amp;uuml;r die Entwicklung einer Windows Phone App braucht kann bei MSDN &lt;a href="http://msdn.microsoft.com/de-de/windowsphone/ff380145.aspx"&gt;kostenlos&lt;/a&gt; heruntergeladen werden.&lt;/p&gt;
&lt;p&gt;Das beinhaltet :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio 2010 Express for Windows Phone &lt;/li&gt;
&lt;li&gt;Windows Phone Emulator Resources &lt;/li&gt;
&lt;li&gt;Silverlight 4 Tools f&amp;uuml;r Visual Studio &lt;/li&gt;
&lt;li&gt;XNA Game Studio 4.0 &lt;/li&gt;
&lt;li&gt;Microsoft Expression Blend for Windows Phone &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wir ben&amp;ouml;tigen f&amp;uuml;r unsere App &amp;ldquo;nur&amp;rdquo; Visual Studio und den Emulator. Wer nicht mit SQL Azure arbeiten will, kann selbstverst&amp;auml;ndlich den Datenzugriff (SQL Server, OData Web Service) auch lokal betreiben. dazu wird dann noch SQL Server Express ben&amp;ouml;tigt, ebenfalls kostenlos bei MS erh&amp;auml;ltlich.&lt;/p&gt;
&lt;p&gt;F&amp;uuml;r den OData Zugriff brauchen wir noch das OData Client API f&amp;uuml;r Windows Phone. Das gibt es auf &lt;a href="http://odata.codeplex.com/"&gt;Codeplex&lt;/a&gt;, ebenfalls gratis. (Open Source Projekt)&lt;/p&gt;
&lt;h3&gt;Und dann ?&lt;/h3&gt;
&lt;p&gt;Ich werde hier nicht im Einzelnen erkl&amp;auml;ren, wie man Window Phone Apps programmiert, dazu gibt es jede Menge guter Informationen im Internet (angefangen bei MSDN) sowie hervorragende B&amp;uuml;cher. In diesem Beitrag&amp;nbsp; wollen wir bei unserem Thema bleiben und eine App erzeugen, die OData Services verwendet, und diese mit einem Bing Map Control visualisiert.&lt;/p&gt;
&lt;p&gt;Wir wollen im Code in der gewohnt bequemen Weise auf unsere OData Services zugreifen. Dazu brauchen wir ein Tool, das uns f&amp;uuml;r die bereitgestellten Web Services eine C# Client Library generiert. So k&amp;ouml;nnen wir komfortabel auf Objektebene programmieren, ohne uns &amp;uuml;ber die zu Grunde liegenden Protokolle den Kopf zerbrechen zu m&amp;uuml;ssen. Daf&amp;uuml;r nehmen wir das command line tool datasvcutil, das in diesem &lt;a href="http://odata.codeplex.com/releases/view/54698#DownloadId=161862"&gt;Zip&lt;/a&gt; enthalten ist.&lt;/p&gt;
&lt;p&gt;Bei der ersten Anwendung hatte ich eine Menge Spass, da die Dokumentation nicht sehr eindeutig ist: F&amp;uuml;r unsere Zwecke muss der Parameter &lt;em&gt;Version&lt;/em&gt; auf 2.0 gesetzt sein:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&lt;em&gt;datasvcutil /uri:&lt;/em&gt;&lt;/span&gt;&lt;a href="http://localhost{port}"&gt;&lt;span style="font-family:Arial;"&gt;&lt;em&gt;http://localhost:{port}/WcfDS.svc&lt;/em&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:Arial;"&gt;&lt;em&gt; /out:.\TVDLunchEntities.cs /DataServiceCollection /Version:2.0&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;als Ergebnis wird eine C# Klasse generiert, die wir in unserem Windows Phone Projekt einbinden. Leider werden dabei unsere 2 Stored Procedures&amp;nbsp; &lt;em&gt;FindColleguesNearMe&lt;/em&gt; und &lt;em&gt;FindColleguesNearPoint &lt;/em&gt;nicht ber&amp;uuml;cksichtigt, nur der Datentyp &lt;em&gt;ColleguesNearMe&lt;/em&gt; wird behandelt. Wir k&amp;ouml;nnen diese aber leicht &amp;uuml;ber eine weitere Service Referenz einbinden.&lt;/p&gt;
&lt;p&gt;Dazu f&amp;uuml;gen wir einen neuen WCF Data Service in unser Web Projekt ein. &lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchAPI &lt;/span&gt;: &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:#2b91af;"&gt;ITVDLunchAPI
    &lt;/span&gt;{
        &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;ColleguesNearMe&lt;/span&gt;&amp;gt; FindColleguesNearMe(&lt;span style="color:blue;"&gt;string &lt;/span&gt;nickName, &lt;span style="color:blue;"&gt;string &lt;/span&gt;howFar)
        {
            &lt;span style="color:#2b91af;"&gt;TVDLunchEntities &lt;/span&gt;tvde = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchEntities&lt;/span&gt;();
            &lt;span style="color:blue;"&gt;return &lt;/span&gt;tvde.FindColleguesNearMe(nickName, &lt;span style="color:blue;"&gt;long&lt;/span&gt;.Parse(howFar)).ToList();
        }

        &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;ColleguesNearMe&lt;/span&gt;&amp;gt; FindColleguesNearPoint(&lt;span style="color:blue;"&gt;string &lt;/span&gt;point, &lt;span style="color:blue;"&gt;string &lt;/span&gt;howFar, &lt;span style="color:blue;"&gt;string &lt;/span&gt;nickName)
        {
            &lt;span style="color:#2b91af;"&gt;TVDLunchEntities &lt;/span&gt;tvde = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchEntities&lt;/span&gt;();
            &lt;span style="color:blue;"&gt;return &lt;/span&gt;tvde.FindColleguesNearPoint(point, &lt;span style="color:blue;"&gt;long&lt;/span&gt;.Parse(howFar), nickName).ToList();
        }
    }&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;der Code sieht zugegebenermassen ein bisschen &amp;ldquo;smelly&amp;rdquo; aus: der Grund ist, dass ich erst durch try und error lernen musste, das Web Services am besten &lt;em&gt;List&amp;lt;&amp;gt;&lt;/em&gt; Objekte exponieren und String Parameter &amp;uuml;bernehmen.&amp;nbsp; das k&amp;ouml;nnen Sie sicher besser!&lt;/p&gt;
&lt;p&gt;Jetzt haben wir alle ben&amp;ouml;tigten Bausteine zusammen und k&amp;ouml;nnen die App zusammenf&amp;uuml;gen:&lt;/p&gt;
&lt;h3&gt;Best practice: MVVM pattern&lt;/h3&gt;
&lt;p&gt;Wir kapseln die Kommunikation mit dem OData Service in einer Klasse. die Logik f&amp;uuml;r die asynchronen Zugriffe auf die Daten wird dadurch zentral abgehandelt, und bl&amp;auml;ht nicht den eigentlichen Code der App unn&amp;ouml;tig auf.&lt;/p&gt;
&lt;p&gt;Ich habe hier 1:1 das Code Beispiel von der Beispiel Applikation des WP Odata API Projekts&amp;nbsp; &amp;uuml;bernommen. Dort wird mit Hilfe der allseits bekannten Northwind Datenbank der OData Zugriff gezeigt. &lt;a href="http://odata.codeplex.com/releases/view/54698#DownloadId=161882"&gt;ODataClient_WinPhone7SampleApp.zip&lt;/a&gt; . Sehr Empfehlenswert!&lt;/p&gt;
&lt;p&gt;In unserem Falle geht es&amp;nbsp; nicht um Customer sondern um TVDLunch, sonst ist alles gleich:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;using &lt;/span&gt;System;
&lt;span style="color:blue;"&gt;using &lt;/span&gt;System.ComponentModel;
&lt;span style="color:blue;"&gt;using &lt;/span&gt;System.Data.Services.Client;
&lt;span style="color:blue;"&gt;using &lt;/span&gt;System.Windows;
&lt;span style="color:blue;"&gt;using &lt;/span&gt;TVDLunchPhone.TVDLunchEntitiesReference;


&lt;span style="color:blue;"&gt;namespace &lt;/span&gt;TVDLunchPhone
{
    &lt;span style="color:blue;"&gt;public class &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;MainViewModel &lt;/span&gt;: &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:#2b91af;"&gt;INotifyPropertyChanged
    &lt;/span&gt;{
        &lt;span style="color:blue;"&gt;static readonly &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Uri &lt;/span&gt;serviceUri = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Uri&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;http://localhost:57811/WcfDS.svc&amp;quot;&lt;/span&gt;);
        &lt;span style="color:blue;"&gt;static readonly &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Uri &lt;/span&gt;TVDLunchsUri = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;Uri&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;/TVDLunch&amp;quot;&lt;/span&gt;, &lt;span style="color:#2b91af;"&gt;UriKind&lt;/span&gt;.Relative);

        &lt;span style="color:#2b91af;"&gt;DataServiceCollection&lt;/span&gt;&amp;lt;TVDLunchEntitiesReference.&lt;span style="color:#2b91af;"&gt;TVDLunch&lt;/span&gt;&amp;gt; tVDLunchs;

        &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchEntities &lt;/span&gt;Context { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;private set&lt;/span&gt;; }

        &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;DataServiceCollection&lt;/span&gt;&amp;lt;&lt;span style="color:#2b91af;"&gt;TVDLunch&lt;/span&gt;&amp;gt; TVDLunchs
        {
            &lt;span style="color:blue;"&gt;get &lt;/span&gt;{ &lt;span style="color:blue;"&gt;return this&lt;/span&gt;.tVDLunchs; }

            &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;private set
            &lt;/span&gt;{
                &lt;span style="color:blue;"&gt;this&lt;/span&gt;.tVDLunchs = &lt;span style="color:blue;"&gt;value&lt;/span&gt;;

                &lt;span style="color:blue;"&gt;this&lt;/span&gt;.tVDLunchs.LoadCompleted += &lt;span style="color:blue;"&gt;this&lt;/span&gt;.OnTVDLunchsLoaded;
                &lt;span style="color:blue;"&gt;this&lt;/span&gt;.tVDLunchs.CollectionChanged += (o, e) =&amp;gt; { &lt;span style="color:blue;"&gt;this&lt;/span&gt;.NotifyPropertyChanged(&lt;span style="color:#a31515;"&gt;&amp;quot;TVDLunchsTitle&amp;quot;&lt;/span&gt;); };

                &lt;span style="color:blue;"&gt;this&lt;/span&gt;.NotifyPropertyChanged(&lt;span style="color:#a31515;"&gt;&amp;quot;TVDLunchs&amp;quot;&lt;/span&gt;);
                &lt;span style="color:blue;"&gt;this&lt;/span&gt;.NotifyPropertyChanged(&lt;span style="color:#a31515;"&gt;&amp;quot;TVDLunchsTitle&amp;quot;&lt;/span&gt;);
            }
        }&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;Das MainViewModel verankern wir an zentraler Stelle (App.xaml.cs), indem wir es als statisches member an das &lt;em&gt;App&lt;/em&gt; Object h&amp;auml;ngen.&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;static &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;MainViewModel &lt;/span&gt;viewModel = &lt;span style="color:blue;"&gt;null&lt;/span&gt;;

        &lt;/span&gt;&lt;span style="color:gray;"&gt;&lt;span style="font-size:xx-small;"&gt;/// &amp;lt;summary&amp;gt;
        /// &lt;/span&gt;&lt;/span&gt;&lt;span style="color:green;"&gt;&lt;span style="font-size:xx-small;"&gt;A static ViewModel used by the views to bind against.
        &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:gray;"&gt;/// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;&lt;/span&gt;&lt;span style="color:green;"&gt;The MainViewModel object.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:gray;"&gt;&amp;lt;/returns&amp;gt;
        &lt;/span&gt;&lt;span style="color:blue;"&gt;public static &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;MainViewModel &lt;/span&gt;ViewModel
        {
            &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;get
            &lt;/span&gt;{
                &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:green;"&gt;// Delay creation of the view model until necessary
                &lt;/span&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;(viewModel == &lt;span style="color:blue;"&gt;null&lt;/span&gt;)
                    viewModel = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;MainViewModel&lt;/span&gt;();

                &lt;span style="color:blue;"&gt;return &lt;/span&gt;viewModel;
            }
        }&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Interessant ist auch noch der Code f&amp;uuml;r die App Events &lt;em&gt;Application_Activated&lt;/em&gt; und &lt;em&gt;Application_Deactivated: &lt;/em&gt;wenn die App auf dem Phone verlassen wird (durch Dr&amp;uuml;cken eines der Hardware Buttons), und danach mit dem &amp;ldquo;Zur&amp;uuml;ck&amp;rdquo; Button wieder aktiviert wird, kann man einen&amp;nbsp; (teuren und m&amp;ouml;glicherweise langsamen) Aufruf des Services sparen, in dem man eine Version der Daten im State Cache des Phones speichert und bei Bedarf reaktiviert. Wen das interessiert: auch hier ist der Code aus dem genannten Beispiel-Projekt &amp;uuml;bernommen.&lt;/p&gt;
&lt;h3&gt;Wie funktioniert der Datenzugriff ?&lt;/h3&gt;
&lt;p&gt;Alle Zugriffe geschehen asynchron. Es gibt also immer eine Aktion die Daten anfordern, l&amp;ouml;schen, einf&amp;uuml;gen oder aktualisieren m&amp;ouml;chte und dem Service Context diesen Wunsch mitteilt.&amp;nbsp; Ob es funktioniert hat, erf&amp;auml;hrt man erst in einer zuvor angegebenen Callback Methode, nur dort kann auf das Ergebnis der Aktion Bezug genommen werden.&lt;/p&gt;
&lt;p&gt;Hier als Beispiel die Methode f&amp;uuml;r das Speichern der eigenen Lokation:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;private void &lt;/span&gt;btnSetLocation_Click(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;RoutedEventArgs &lt;/span&gt;e)
{
    
    &lt;span style="color:blue;"&gt;var &lt;/span&gt;center = bingMap.Center;

    &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:green;"&gt;// Update database
    &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchEntities &lt;/span&gt;ctx = &lt;span style="color:#2b91af;"&gt;App&lt;/span&gt;.ViewModel.Context;

    &lt;span style="color:blue;"&gt;var &lt;/span&gt;mangiare = &lt;span style="color:#2b91af;"&gt;App&lt;/span&gt;.ViewModel.TVDLunchs;


    &lt;span style="color:blue;"&gt;var &lt;/span&gt;myLunch = (&lt;span style="color:blue;"&gt;from &lt;/span&gt;l &lt;span style="color:blue;"&gt;in &lt;/span&gt;mangiare
                   &lt;span style="color:blue;"&gt;where &lt;/span&gt;l.Nickname == _loggedInNick
                   &lt;span style="color:blue;"&gt;select &lt;/span&gt;l).FirstOrDefault();

    &lt;span style="color:blue;"&gt;if &lt;/span&gt;(myLunch == &lt;span style="color:blue;"&gt;null&lt;/span&gt;) &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:green;"&gt;// insert
    &lt;/span&gt;{
        myLunch = &lt;span style="color:#2b91af;"&gt;TVDLunch&lt;/span&gt;.CreateTVDLunch(-1, _loggedInNick, &lt;span style="color:#2b91af;"&gt;DateTime&lt;/span&gt;.Now);
        ctx.AddToTVDLunch(myLunch);
    }
    &lt;span style="color:blue;"&gt;else &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:green;"&gt;// update
    &lt;/span&gt;{
        ctx.UpdateObject(myLunch);
    }

    &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:green;"&gt;// Set the new GeoPoint
    &lt;/span&gt;myLunch.GeoPoint = &lt;span style="color:#2b91af;"&gt;CoordinateHelper&lt;/span&gt;.GeoPointFromLocation(center);

    &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:green;"&gt;// Set the lunchText
    &lt;/span&gt;&lt;span style="color:blue;"&gt;if &lt;/span&gt;(_lunchText != &lt;span style="color:blue;"&gt;null&lt;/span&gt;)
        myLunch.LocationText = _lunchText;
    _lunchText = myLunch.LocationText;

        ctx.BeginSaveChanges(OnSaveCompleted, ctx);

    
}&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;
&lt;span style="font-size:xx-small;"&gt;
&lt;p&gt;&lt;span style="font-size:x-small;"&gt;jetzt folgt die Callback Methode, in der wir die aktualisierten Daten verwenden k&amp;ouml;nnen:&lt;/span&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;
&lt;span style="color:blue;"&gt;private void &lt;/span&gt;OnSaveCompleted(&lt;span style="color:#2b91af;"&gt;IAsyncResult &lt;/span&gt;result)
{
    &lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;try
    &lt;/span&gt;{
        &lt;span style="color:blue;"&gt;var &lt;/span&gt;ctx = result.AsyncState &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchEntities&lt;/span&gt;;
        ctx.EndSaveChanges(result);

        RefreshAllLunchesInCard();
    }
    &lt;span style="color:blue;"&gt;catch &lt;/span&gt;(&lt;span style="color:#2b91af;"&gt;Exception &lt;/span&gt;ex)
    {
        &lt;span style="color:#2b91af;"&gt;Debug&lt;/span&gt;.WriteLine(ex.Message);
    }
}&lt;/span&gt;&lt;/pre&gt;
&lt;pre class="code"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;Ab hier ist die Applikation eigentlich &amp;ldquo;straight forward&amp;rdquo;, die visuellen Controls (Silverlight) &amp;ldquo;sehen&amp;rdquo; die Daten als normale Collections. Wir k&amp;ouml;nnen das Silverlight Data Binding verwenden, um z.B. eine Liste zu f&amp;uuml;llen (z.B die Telefonliste) , oder aber auch Linq, um einen bestimmten TVDLunch Eintrag zu finden. Dazu verfeinern wir das einfache Daten Objekt ein bisschen, um das Binding noch einfacher zu machen:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;&lt;span style="font-size:xx-small;"&gt;public class &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:#2b91af;"&gt;ImageTrivadian
    &lt;/span&gt;{
        &lt;span style="color:blue;"&gt;public &lt;/span&gt;ImageTrivadian(&lt;span style="color:#2b91af;"&gt;ColleguesNearMe &lt;/span&gt;trivadian)
        {
            Trivadian = trivadian;
            ImagePath = &lt;span style="color:blue;"&gt;string&lt;/span&gt;.Format(&lt;span style="color:#a31515;"&gt;&amp;quot;http://yourimageserver.com/ma_photos/{0}.jpg&amp;quot;&lt;/span&gt;, trivadian.Nickname);
            Distance = &lt;span style="color:#2b91af;"&gt;Math&lt;/span&gt;.Round(((&lt;span style="color:blue;"&gt;double&lt;/span&gt;)trivadian.Distance / 1000), 1).ToString() + &lt;span style="color:#a31515;"&gt;&amp;quot; km entfernt&amp;quot;&lt;/span&gt;;
        }

        &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ColleguesNearMe &lt;/span&gt;Trivadian { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
        &lt;span style="color:blue;"&gt;public string &lt;/span&gt;ImagePath { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
        &lt;span style="color:blue;"&gt;public string &lt;/span&gt;Distance { &lt;span style="color:blue;"&gt;get&lt;/span&gt;; &lt;span style="color:blue;"&gt;set&lt;/span&gt;; }
    }&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Jetzt k&amp;ouml;nnen wir es leicht an eine List Control binden:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ListBox &lt;/span&gt;&lt;span style="color:red;"&gt;x&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;Name&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;=&amp;quot;lsbCollegues&amp;quot;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;DataTemplate&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;StackPanel &lt;/span&gt;&lt;span style="color:red;"&gt;Orientation&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;=&amp;quot;Horizontal&amp;quot;&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Image &lt;/span&gt;&lt;span style="color:red;"&gt;Source&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding &lt;/span&gt;&lt;span style="color:red;"&gt;ImagePath&lt;/span&gt;&lt;span style="color:blue;"&gt;}&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;Width&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;50&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;Height&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;50&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;Margin&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;=&amp;quot;5&amp;quot;/&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBlock &lt;/span&gt;&lt;span style="color:red;"&gt;Text&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding &lt;/span&gt;&lt;span style="color:red;"&gt;Trivadian&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;.Nickname}&amp;quot;/&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBlock &lt;/span&gt;&lt;span style="color:red;"&gt;Text&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;=&amp;quot; (&amp;quot;/&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBlock &lt;/span&gt;&lt;span style="color:red;"&gt;Text&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;{&lt;/span&gt;&lt;span style="color:#a31515;"&gt;Binding &lt;/span&gt;&lt;span style="color:red;"&gt;Distance&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;}&amp;quot;/&amp;gt;
                            &amp;lt;&lt;/span&gt;&lt;span style="color:#a31515;"&gt;TextBlock &lt;/span&gt;&lt;span style="color:red;"&gt;Text&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;=&amp;quot;)&amp;quot;/&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;StackPanel&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;DataTemplate&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ListBox.ItemTemplate&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color:#a31515;"&gt;ListBox&lt;/span&gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&lt;span style="font-size:xx-small;"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Die Daten werden geholt, wenn der Standort des Benutzers gesetzt ist:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;private void &lt;/span&gt;LoadColleguesNearMyLunch()
       {
           &lt;span style="color:blue;"&gt;if &lt;/span&gt;(_myLunchLocation == &lt;span style="color:blue;"&gt;null&lt;/span&gt;)
           {
               &lt;span style="color:#2b91af;"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color:#a31515;"&gt;&amp;quot;Bitte erst die Location in der Karte setzen&amp;quot;&lt;/span&gt;);
               &lt;span style="color:blue;"&gt;return&lt;/span&gt;;
           }

           &lt;span style="color:blue;"&gt;string &lt;/span&gt;pointString = &lt;span style="color:#2b91af;"&gt;CoordinateHelper&lt;/span&gt;.GeoPointFromLocation(_myLunchLocation);

           lsbCollegues.Items.Clear();
           &lt;span style="color:#2b91af;"&gt;TVDLunchAPIClient &lt;/span&gt;client = &lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;TVDLunchAPIClient&lt;/span&gt;();
           client.FindColleguesNearPointCompleted += (s, e) =&amp;gt;
               {
                   &lt;span style="color:blue;"&gt;foreach &lt;/span&gt;(LunchApi.&lt;span style="color:#2b91af;"&gt;ColleguesNearMe &lt;/span&gt;trivadianer &lt;span style="color:blue;"&gt;in &lt;/span&gt;e.Result)
                   {
                       lsbCollegues.Items.Add(&lt;span style="color:blue;"&gt;new &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ImageTrivadian&lt;/span&gt;(trivadianer));
                   }
               };
           client.FindColleguesNearPointAsync(pointString, &lt;span style="color:#a31515;"&gt;&amp;quot;10000&amp;quot;&lt;/span&gt;, _loggedInNick);
       }&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone4_5.png"&gt;&lt;img height="244" width="148" src="http://blog.trivadis.com/blogs/michaelkoenings/Windows-Live-Writer/TVDLunch-nie-mehr-alleine-Mittagessen-da_AEAD/Phone4_thumb_1.png" alt="Phone4" border="0" title="Phone4" style="border-width:0px;padding-top:0px;padding-right:0px;padding-left:0px;display:inline;background-image:none;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;hier nochmals die Listenansicht. Der &amp;ldquo;Call&amp;rdquo; Button startet direkt einen Anruf:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="font-size:xx-small;"&gt;&lt;span style="color:blue;"&gt;private void &lt;/span&gt;ButtonCall_Click(&lt;span style="color:blue;"&gt;object &lt;/span&gt;sender, &lt;span style="color:#2b91af;"&gt;RoutedEventArgs &lt;/span&gt;e)
        {
            &lt;span style="color:blue;"&gt;var &lt;/span&gt;trivadianer = lsbCollegues.SelectedItem &lt;span style="color:blue;"&gt;as &lt;/span&gt;&lt;span style="color:#2b91af;"&gt;ImageTrivadian&lt;/span&gt;;
            &lt;span style="color:blue;"&gt;if &lt;/span&gt;(trivadianer == &lt;span style="color:blue;"&gt;null&lt;/span&gt;)
            {
                &lt;span style="color:#2b91af;"&gt;MessageBox&lt;/span&gt;.Show(&lt;span style="color:#a31515;"&gt;&amp;quot;Please select a person from the list&amp;quot;&lt;/span&gt;);
                &lt;span style="color:blue;"&gt;return&lt;/span&gt;;
            }
            Microsoft.Phone.Tasks.&lt;span style="color:#2b91af;"&gt;PhoneCallTask &lt;/span&gt;call = &lt;span style="color:blue;"&gt;new &lt;/span&gt;Microsoft.Phone.Tasks.&lt;span style="color:#2b91af;"&gt;PhoneCallTask&lt;/span&gt;();
            call.PhoneNumber = trivadianer.Trivadian.Phone;
            call.Show();
        }&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;ok, das soll f&amp;uuml;r heute mal reichen, im n&amp;auml;chsten Beitrag werden wir das Bing Maps Control anschauen und ein Custom PushPin Object erzeugen. Bis dahin freue ich mich &amp;uuml;ber Feedback!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=177155" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/-NET/default.aspx">.NET</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Azure/default.aspx">Azure</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Bing+Maps/default.aspx">Bing Maps</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/OData/default.aspx">OData</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Windows+Phone+7/default.aspx">Windows Phone 7</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/WP7/default.aspx">WP7</category></item><item><title>TVDLunch: nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 6)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2011/03/21/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-6.aspx</link><pubDate>Mon, 21 Mar 2011 16:00:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:172440</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=172440</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2011/03/21/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-6.aspx#comments</comments><description>&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx"&gt;ersten Teil&lt;/a&gt; habe ich eine groben Überblick über das Projekt gegeben.&lt;/p&gt;  &lt;p&gt;Im zweiten Schritt haben wir Windows Azure Cloud Services &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx"&gt;einbezogen&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx"&gt;dritten Teil&lt;/a&gt; haben wir angeschaut, was uns OData und WCF Data Services und das Entity Framework 4 (EF4) bringen können.&lt;/p&gt;  &lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/02/25/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-4.aspx"&gt;vierten Teil&lt;/a&gt; haben wir mit einer ASP.NET MVC Seite die OData-Daten als Webservice aufgerufen und als kleine Fotos auf eine Bing Map gezeichnet.&lt;/p&gt;  &lt;p&gt;Im &lt;a title="TVDLunch Teil Fünf" href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/03/11/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-5.aspx" target="_blank"&gt;fünften Teil&lt;/a&gt; werden haben wir mit&amp;nbsp; AJAX CRUD Operationen gegen unseren Azure OData Service ausgeführt.&lt;/p&gt;    &lt;p&gt;Jetzt wollen wir zeigen, wie wir in der Datenbank Entfernungen zwischen den Kollegen berechnen können!&lt;/p&gt;    &lt;p&gt;Dazu verwenden wir eine Tabelle mit einer Spalte vom Typ “geography”:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_1D6C396C.png"&gt;&lt;img style="border-width:0px;display:inline;" title="image" border="0" alt="image" src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_43CE1CB7.png" width="644" height="327" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In diesem Feld können wir eine Positions-Infomation (einen Punkt) speichern, die sich jeweils aus der Latitude und Longitude Information zusammensetzt. Dieser Datentyp wird binär gespeichert, deshalb habe ich zur Verdeutlichung noch das Feld GeoPoint als Varchar(255) angelegt, das eine textuelle Entsprechung des Wertes enthält.&lt;/p&gt;  &lt;p&gt;Beispiel:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;GeoLocation&amp;nbsp;&amp;nbsp; und&amp;nbsp; GeoPoint:      &lt;br /&gt;0xE6100000010CA31FB98C53B7474091976E726B1F2140&amp;nbsp;&amp;nbsp;&amp;nbsp; POINT(9.552612304687494 49.01265386395501)       &lt;br /&gt;0xE6100000010CC0791DC832B7474004000060E81E2140&amp;nbsp;&amp;nbsp;&amp;nbsp; POINT(8.562847139546658, 47.45562644775183)&lt;/em&gt;&lt;/p&gt;  &lt;h4&gt;Woher kommen die Werte ?&lt;/h4&gt;  &lt;p&gt;Wir lassen das Bing Maps Control diese Arbeit erledigen. Vom Control bekommen wir eine genaue Geo-Position eines Punktes auf der Karte. Wir erreichen das, indem wir das&amp;nbsp; Klick-Event abfangen und die Position auslesen (siehe &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/02/25/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-4.aspx" target="_blank"&gt;Teil 4&lt;/a&gt;) .&lt;/p&gt;  &lt;p&gt;Die beiden Dezimal-Werte bauen wir zu einen String zusammen, mit dem oben gezeigten Format.&lt;/p&gt;  &lt;p&gt;Diesen Punkt müssen wir jetzt noch in einen &lt;em&gt;geography&lt;/em&gt; Wert umwandeln, das geht am besten über eine Trigger auf der TVDLunch Tabelle:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;CREATE TRIGGER &lt;/span&gt;[dbo]&lt;span style="color:gray;"&gt;.&lt;/span&gt;[TVDLunch_Ins_Upd] 
   &lt;span style="color:blue;"&gt;ON  &lt;/span&gt;[dbo]&lt;span style="color:gray;"&gt;.&lt;/span&gt;[TVDLunch] 
   &lt;span style="color:blue;"&gt;AFTER INSERT&lt;/span&gt;&lt;span style="color:gray;"&gt;,&lt;/span&gt;&lt;span style="color:blue;"&gt;UPDATE
AS 
BEGIN
    &lt;/span&gt;&lt;span style="color:blue;"&gt;SET NOCOUNT ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;

    &lt;/span&gt;&lt;span style="color:blue;"&gt;Update &lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TVDLunch
    &lt;span style="color:blue;"&gt;set &lt;/span&gt;geoLocation &lt;span style="color:gray;"&gt;= &lt;/span&gt;&lt;span style="color:blue;"&gt;geography&lt;/span&gt;&lt;span style="color:gray;"&gt;::&lt;/span&gt;STGeomFromText&lt;span style="color:gray;"&gt;(&lt;/span&gt;&lt;span style="color:magenta;"&gt;coalesce&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;i&lt;span style="color:gray;"&gt;.&lt;/span&gt;GeoPoint&lt;span style="color:gray;"&gt;,&lt;/span&gt;t&lt;span style="color:gray;"&gt;.&lt;/span&gt;GeoPoint&lt;span style="color:gray;"&gt;), &lt;/span&gt;4326&lt;span style="color:gray;"&gt;)
    &lt;/span&gt;&lt;span style="color:blue;"&gt;from &lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TVDLunch t &lt;span style="color:gray;"&gt;inner join &lt;/span&gt;inserted &lt;span style="color:blue;"&gt;as &lt;/span&gt;i
    &lt;span style="color:blue;"&gt;on &lt;/span&gt;t&lt;span style="color:gray;"&gt;.&lt;/span&gt;id &lt;span style="color:gray;"&gt;= &lt;/span&gt;i&lt;span style="color:gray;"&gt;.&lt;/span&gt;Id&lt;span style="color:gray;"&gt;;
     

&lt;/span&gt;&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Hier sehen wir jetzt die Spatial-Funktionen von SQL Server im Einsatz. Die Funktion &lt;span style="color:blue;"&gt;geography&lt;/span&gt;&lt;span style="color:gray;"&gt;::&lt;/span&gt;STGeomFromText wandelt unseren String im Feld GeoPoint in einen geography Wert um!&lt;/p&gt;

&lt;p&gt;So können wir jetzt auch weitere Spatial-Funktionen verwenden, um die Distanz zwischen den Kollegen auszurechnen. Dafür habe ich eine Stored Procedure erstellt, die alle Kollegen in der Nähe eines einzelnen Kollegen auflistet:&lt;/p&gt;



&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;CREATE PROCEDURE &lt;/span&gt;[dbo]&lt;span style="color:gray;"&gt;.&lt;/span&gt;[FindColleguesNearMe]
&lt;span style="color:green;"&gt;    &lt;/span&gt;@NickName &lt;span style="color:blue;"&gt;Varchar&lt;/span&gt;&lt;span style="color:gray;"&gt;(&lt;/span&gt;50&lt;span style="color:gray;"&gt;) , 
    &lt;/span&gt;@HowFar &lt;span style="color:blue;"&gt;bigint &lt;/span&gt;&lt;span style="color:gray;"&gt;= &lt;/span&gt;10000
&lt;span style="color:blue;"&gt;AS
BEGIN
    &lt;/span&gt;&lt;span style="color:blue;"&gt;SET NOCOUNT ON&lt;/span&gt;&lt;span style="color:gray;"&gt;;

    &lt;/span&gt;&lt;span style="color:blue;"&gt;Declare &lt;/span&gt;@Center &lt;span style="color:blue;"&gt;geography&lt;/span&gt;&lt;span style="color:gray;"&gt;;
    &lt;/span&gt;&lt;span style="color:blue;"&gt;Select &lt;/span&gt;@center &lt;span style="color:gray;"&gt;= &lt;/span&gt;GeoLocation &lt;span style="color:blue;"&gt;from &lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TVDLunch &lt;span style="color:blue;"&gt;where &lt;/span&gt;Nickname &lt;span style="color:gray;"&gt;= &lt;/span&gt;@NickName&lt;span style="color:gray;"&gt;;
    
     

&lt;/span&gt;&lt;span style="color:blue;"&gt;select  &lt;/span&gt;@center&lt;span style="color:gray;"&gt;.&lt;/span&gt;STDistance&lt;span style="color:gray;"&gt;(&lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;geoLocation&lt;span style="color:gray;"&gt;) &lt;/span&gt;&lt;span style="color:blue;"&gt;as &lt;/span&gt;Distance&lt;span style="color:gray;"&gt;, 
&lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;Nickname&lt;span style="color:gray;"&gt;, &lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;LunchTime&lt;span style="color:gray;"&gt;, &lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;LocationText&lt;span style="color:gray;"&gt;, 
&lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;GeoLocation&lt;span style="color:gray;"&gt;.&lt;/span&gt;STAsText&lt;span style="color:gray;"&gt;() &lt;/span&gt;&lt;span style="color:blue;"&gt;as &lt;/span&gt;geoPoint
&lt;span style="color:blue;"&gt;from &lt;/span&gt;dbo&lt;span style="color:gray;"&gt;.&lt;/span&gt;TVDLunch a 
&lt;span style="color:blue;"&gt;where &lt;/span&gt;@center&lt;span style="color:gray;"&gt;.&lt;/span&gt;STDistance&lt;span style="color:gray;"&gt;(&lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;geoLocation&lt;span style="color:gray;"&gt;) &amp;lt;= &lt;/span&gt;@HowFar
&lt;span style="color:gray;"&gt;and &lt;/span&gt;Nickname &lt;span style="color:gray;"&gt;&amp;lt;&amp;gt; &lt;/span&gt;@NickName

&lt;span style="color:blue;"&gt;END&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Diese SP selektiert alle hungrigen Kollegen in der Nähe, im Umkreis von 10000 Metern, falls nichts anderes als Distanz übergeben wurde.&lt;/p&gt;

&lt;p&gt;Hierzu verwenden wir die Spatial-Funktion &lt;em&gt;STDistance&lt;span style="color:gray;"&gt;(&lt;/span&gt;a&lt;span style="color:gray;"&gt;.&lt;/span&gt;geoLocation&lt;/em&gt;&lt;span style="color:gray;"&gt;&lt;em&gt;), &lt;/em&gt;&lt;font color="#000000"&gt;die direkt vom Datentyp geography bereitgestellt wird.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:gray;"&gt;&lt;font color="#000000"&gt;Die Stored Procedure wird im OData Web-Service veröffentlicht, so das der Ajax-Client (und alle anderen Odata Clients) diese komfortabel aufrufen kann.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:gray;"&gt;&lt;font color="#000000"&gt;So können wir die Positionen “live” im Browser anzeigen, z. B. wenn der Anwender seine eigene Position verändert.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:gray;"&gt;&lt;font color="#000000"&gt;Der Mitarbeiter kann dann direkt mit seinen Kollegen in der Nähe Kontakt aufnehmen und braucht nicht alleine zu essen! &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:gray;"&gt;&lt;font color="#000000"&gt;Mission accomplished!&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_6A9C32F7.png"&gt;&lt;img style="border-width:0px;display:inline;" title="image" border="0" alt="image" src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_0A4B0CC0.png" width="644" height="474" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;hier noch der Code für den ADO.NET Data Service:&lt;/p&gt;



&lt;pre class="code"&gt;[&lt;span&gt;WebGet&lt;/span&gt;]
        &lt;span style="color:blue;"&gt;public &lt;/span&gt;&lt;span&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span&gt;ColleguesNearMe&lt;/span&gt;&amp;gt; FindColleguesNearMe(&lt;span style="color:blue;"&gt;string &lt;/span&gt;nickName, &lt;span style="color:blue;"&gt;string &lt;/span&gt;howFar)
        {
            &lt;span style="color:blue;"&gt;return this&lt;/span&gt;.CurrentDataSource.FindColleguesNearMe(nickName, &lt;span style="color:blue;"&gt;long&lt;/span&gt;.Parse(howFar)).AsQueryable();
          
        }&lt;/pre&gt;

&lt;p&gt;&lt;font color="#0000ff" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;



&lt;p&gt;jetzt haben wir alle Bausteine zusammen, um eine Location-based Cloud-Applikation zu bauen.&lt;/p&gt;

&lt;p&gt;Als nächstes wollen wir das Frontend auf dem Windows Phone 7 programmieren.&lt;/p&gt;

&lt;p&gt;Hier wird uns wieder das Bing Map Control helfen, diesmal als Silverlight Ausfühung.&lt;/p&gt;

&lt;p&gt;Die Geo-Location Information des Anwenders bekommen wir direkt von Telefon, das mit seinem GPS Sensor eine sehr genaue Ortsbestimmung erlaubt.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=172440" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/SQL/default.aspx">SQL</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/MVC/default.aspx">MVC</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/ASP-NET/default.aspx">ASP.NET</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/OData/default.aspx">OData</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Windows+Phone+7/default.aspx">Windows Phone 7</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/WP7/default.aspx">WP7</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Spatial+Data/default.aspx">Spatial Data</category></item><item><title>TVDLunch: nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 5)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2011/03/11/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-5.aspx</link><pubDate>Fri, 11 Mar 2011 16:14:55 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:172222</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=172222</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2011/03/11/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-5.aspx#comments</comments><description>&lt;p&gt;im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx"&gt;ersten Teil&lt;/a&gt; habe ich eine groben Überblick über das Projekt gegeben.&lt;/p&gt;  &lt;p&gt;im zweiten Schritt haben wir Windows Azure Cloud Services &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx"&gt;einbezogen&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx"&gt;dritten Teil&lt;/a&gt; haben wir angeschaut, was uns OData und WCF Data Services und das Entity Framework 4 (EF4) bringen können.&lt;/p&gt;  &lt;p&gt;im &lt;a title="TVDLunch Teil 4" href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/02/25/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-4.aspx" target="_blank"&gt;vierten Teil&lt;/a&gt; haben wir mit einer ASP.NET MVC Seite die OData-Daten als Webservice aufgerufen und als kleine Photos auf eine Bing Map gezeichnet.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In diesem Beitrag wollen wir aus der ASP.NET MVC Web-Seite heraus die Daten unseres Azure-basierten Odata Services bearbeiten (CRUD Operiationen).&lt;/p&gt;  &lt;p&gt;Dazu werden wir &lt;u&gt;nicht&lt;/u&gt; den klassischen MVC-Controller/Model Weg gehen ( das würde natürlich auch funktionieren). Ich möchte vielmehr zeigen, wie wir die OData Schnittstelle per Ajax ansprechen können. So wird der Mashup-Charakter&amp;#160; unserer Applikation mehr betont: eine HTML Seite dient als Hülle für eine AJAX Anwendung, die Daten aus verschiedenen Cloud-Datenquellen kombiniert:&amp;#160; hier sind es Azure und Bing Maps. &lt;/p&gt;  &lt;p&gt;Wir könnten unsere Applikation noch mit weiteren öffentlichen APIs erweitern , um z.B. Restaurants in der Nähe (z.B. Foursquare API) anzuzeigen, Schnäppchen zu machen&amp;#160; (z.B. Groupon API ),&amp;#160; oder um uns zu den Social Networks (Facebook Places, Google Latitude) zu verbinden. Alles was wir brauchen sind Longitude und Latitude Werte, damit können wir auf der Bing Map die entsprechende Information in unserer Nähe einzeichnen ( siehe letzter Beitrag) . Wenn man als Geo-Information “nur” eine postalische Adresse zur Verfügung&amp;#160; hat, kann man über das&amp;#160; &lt;a title="Bing Services REST API" href="http://msdn.microsoft.com/en-us/library/ff701714.aspx" target="_blank"&gt;Bing Services REST API&lt;/a&gt;&amp;#160; dazu die Longitude/Latitude-Daten&amp;#160; abfragen!&lt;/p&gt;  &lt;p&gt;z.B. die Adresse von Microsoft in Redmond:&lt;/p&gt;  &lt;pre&gt;&lt;font size="1"&gt;http://dev.virtualearth.net/REST/v1/Locations/US/WA/98052/Redmond/1 Microsoft Way?o=xml&amp;amp;key=BingMapsKey&lt;/font&gt;&lt;/pre&gt;

&lt;p&gt;&lt;font size="1" face="Courier New"&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Noch einfacher geht es direkt über das Map Control mit der .find(Suchadresse) Methode.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h4&gt;CRUD mit OData und Ajax Data-Binding&lt;/h4&gt;

&lt;p&gt;Als alter WinForms Programmierer träume ich immer noch den Traum, dass so etwas Banales wie Data-Binding eigentlich rein deklarativ, also ohne zusätzlichen, selbstgeschriebenen&amp;#160; Code funktionieren sollte. Dies gilt ( bei einfachen Anwendungen) soweit auch bei .NET Client Programmierung, aber wie sieht es damit bei Web-Applikationen aus ?&lt;/p&gt;

&lt;p&gt;Es gibt(gab?) aus dem Hause Microsoft eine Lösung dafür, die aber wohl eher als experimentell zu bezeichnen ist: &lt;/p&gt;

&lt;p&gt;Data Binding in ASP.NET AJAX 4.0 &lt;/p&gt;

&lt;p&gt;Dino Esposito&amp;#160; hat hier einen einführenden &lt;a title="ASP.NET Ajax 4.0 Databinding" href="http://msdn.microsoft.com/en-us/magazine/ee309508.aspx" target="_blank"&gt;Artikel&lt;/a&gt; geschrieben, der mittlerweile überarbeitet wurde. Ich konnte leider nicht viel weiterführendes Material finden.&lt;/p&gt;

&lt;p&gt;Das hat zum Einen damit zu tun, dass das damalige Produkt “ADO.NET Data Services”&amp;#160; jetzt als “freies” Projekt &lt;em&gt;OData&lt;/em&gt; auf OData.org lebt, und MS der jungen Technologie einige Libraries als “Mitgift” spendiert hat. Dabei haben sich auch die Namespaces entsprechend geändert! Die ehemalige ADO.NET Ajax Client Library ist jetzt bei den &lt;a title="Odata Ajax API" href="http://www.odata.org/developers/odata-sdk" target="_blank"&gt;OData APIs&lt;/a&gt; zu finden.&lt;/p&gt;

&lt;p&gt;Möglicherweise ist diese Technologie (ASP.NET Ajax Data Binding) aber auch an einem Punkt angekommen, wo es sich mit dem großen Erfolg von JQuery überholt hat. Im JQuery Umfeld wird an dem &lt;a title="JQuery Data Link Plugin" href="http://api.jquery.com/category/plugins/data-link/" target="_blank"&gt;Data Link Plugin&lt;/a&gt; gearbeitet (Microsoft trägt auch zu dem Projekt bei). Diese Library ist generell für Binding zu verwenden (ähnlich dem Silverlight Property Binding), ist aber nicht unbedingt geeignet, um schnell eine Datenquelle an ein paar Input Controls zu binden. Deshalb hatte ich mich bei unserem Beispiel für die OData AJAX Variante entschieden. Der Zugriff auf OData&amp;#160; Webservices funktioniert einwandfrei und das Databinding kann zumindest beispielhaft angewendet werden.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h4&gt;Wie funktioniert das ?&lt;/h4&gt;

&lt;p&gt;Zunächst müssen die AJAX Script Libraries referenziert werden:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;script &lt;/span&gt;&lt;span style="color:red;"&gt;src&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;../../Scripts/Start.debug.js&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;type&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;script&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;jetzt brauchen wir den initialen Aufruf der Library (lädt benötigte Komponenten nach) :&lt;/p&gt;

&lt;pre class="code"&gt;Sys.require([Sys.components.dataView, Sys.components.openDataContext]);&lt;/pre&gt;

&lt;p&gt;und wenn alles geladen ist:&lt;/p&gt;

&lt;p&gt;Sys.onReady(&lt;span style="color:blue;"&gt;function &lt;/span&gt;() { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; dataContext = Sys.create.openDataContext( 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; serviceUri: &lt;span style="color:maroon;"&gt;&amp;quot;/WcfDS.svc&amp;quot;&lt;/span&gt;, 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; mergeOption: Sys.Data.MergeOption.appendOnly 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }); 

  &lt;br /&gt;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; dataContext.initialize(); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; oDataProxy = &lt;span style="color:blue;"&gt;new &lt;/span&gt;Sys.Data.OpenDataServiceProxy(&lt;span style="color:maroon;"&gt;&amp;#39;/WcfDS.svc&amp;#39;&lt;/span&gt;); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#808080"&gt;GetMap(); 
    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AddMyLayer(VEDataType.GeoRSS);&lt;/font&gt; 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; });&lt;/p&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;wir initialisieren ein dataContext Objekt auf unseren OData Service.&lt;/p&gt;

&lt;p&gt;Dazu noch ein OpenDataServiceProxy, das brauchen wir für eine separate Abfrage (später im Text).&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Aber wo ist das deklarative Data-Binding ?&lt;/p&gt;

&lt;p&gt;Hier, bitteschön:&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;div &lt;/span&gt;&lt;span style="color:red;"&gt;id&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;#39;dataform&amp;#39; &lt;/span&gt;&lt;span style="color:red;"&gt;style&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;&lt;/span&gt;&lt;span style="color:red;"&gt;margin-left&lt;/span&gt;&lt;span style="color:blue;"&gt;: 15px; &lt;/span&gt;&lt;span style="color:red;"&gt;float&lt;/span&gt;&lt;span style="color:blue;"&gt;:left&amp;quot;&amp;gt;
       
        &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;table &lt;/span&gt;&lt;span style="color:red;"&gt;sys&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;attach&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;dataview&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;id&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;Editor&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;class&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;sys-template&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;dataview&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;dataprovider&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;{{ dataContext }}&amp;quot;
            &lt;/span&gt;&lt;span style="color:red;"&gt;dataview&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;autofetch&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;true&amp;quot;
            &lt;/span&gt;&lt;span style="color:red;"&gt;dataview&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;onfetchsucceeded&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;{{ onFetchSucceededEditor }}&amp;quot;
            &lt;/span&gt;&lt;span style="color:red;"&gt;dataview&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;fetchoperation&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;TVDLunch?%24filter=Nickname%20eq%20&amp;#39;&lt;/span&gt;&lt;span style="background:yellow;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color:blue;"&gt;: &lt;/span&gt;Page.User.Identity.Name &lt;span style="background:yellow;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;#39;&amp;quot;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;tr&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &lt;/span&gt;your short name:&lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &lt;/span&gt;&lt;span style="background:yellow;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;Html.SysTextBox(&lt;span style="color:#a31515;"&gt;&amp;quot;NickName&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515;"&gt;&amp;quot;{binding Nickname, mode=twoWay}&amp;quot;&lt;/span&gt;)&lt;span style="background:yellow;"&gt;%&amp;gt;
&lt;/span&gt;                &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;tr&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
            &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;tr&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &lt;/span&gt;Id
                &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &lt;/span&gt;&lt;span style="background:yellow;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color:blue;"&gt;= &lt;/span&gt;Html.SysTextBox(&lt;span style="color:#a31515;"&gt;&amp;quot;Id&amp;quot;&lt;/span&gt;, &lt;span style="color:#a31515;"&gt;&amp;quot;{binding Id, mode=twoWay}&amp;quot;&lt;/span&gt;)&lt;span style="background:yellow;"&gt;%&amp;gt;
&lt;/span&gt;                &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
            &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;tr&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
   … usw.&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Man kann erkennen, dass die Zellen der HTML Tabelle direkt an Felder aus der Datenquelle verknüpft werden.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Die Datenquelle (dataContext)&amp;#160; ist ein Objekt, das wir in derSys. onReady Funktion initialisiert haben.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Es kennt die URI zu Web-Service, deshalb kann der String im Property dataview:fetchoperation als Abfrage direkt ausgeführt werden. Hier rufen wir die TVDLunchTabelle ab, mit dem Filter auf dem Nickname des angemeldeten Benutzers. Alle Input Felder in der HTML-Table sind an die Felder der Tabelle gebunden. Die Abfrage wird automatisch beim Laden der Seite ausgeführt ( autofetch = true) . &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Ganz einfach, oder ?&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Nun ja, den “bösen” Code habe ich noch nicht gezeigt. Alle “Sonder”-Fälle müssen selbst behandelt werden, z.B. wenn kein Datensatz gefunden wurde…&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;h4&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Und wie geht Insert, Update und Delete ?&lt;/font&gt;&lt;/span&gt;&lt;/h4&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Eigentlich ganz einfach. &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;function &lt;/span&gt;SaveLoc() {
            &lt;span style="color:blue;"&gt;var &lt;/span&gt;pendingChanges = dataContext.get_hasChanges();
            &lt;span style="color:blue;"&gt;if &lt;/span&gt;(pendingChanges !== &lt;span style="color:blue;"&gt;true&lt;/span&gt;) {
                alert(&lt;span style="color:maroon;"&gt;&amp;quot;No pending changes to save.&amp;quot;&lt;/span&gt;);
                &lt;span style="color:blue;"&gt;return&lt;/span&gt;;
            }

            &lt;span style="color:blue;"&gt;var &lt;/span&gt;changes = dataContext.get_changes();
           
            &lt;span style="color:blue;"&gt;if &lt;/span&gt;(confirm(buffer))
                dataContext.saveChanges(saveSucceeded, &lt;span style="color:blue;"&gt;null&lt;/span&gt;, dataContext);


        }

        &lt;span style="color:blue;"&gt;function &lt;/span&gt;DeleteLoc() {

            dv = $find(&lt;span style="color:maroon;"&gt;&amp;quot;Editor&amp;quot;&lt;/span&gt;);
            &lt;span style="color:blue;"&gt;var &lt;/span&gt;data = dv.get_data()[0];

            dataContext.removeEntity(data);
            &lt;font color="#808080"&gt;DeleteShape();&lt;/font&gt;
            dataContext.saveChanges(deleteSucceeded, &lt;span style="color:blue;"&gt;null&lt;/span&gt;, dataContext);
           
         }&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Es gibt noch ein bisschen mehr Code, z.B. um ein neues Datenobjekt zu erzeugen und dem dataContext anzuhängen (Insert). Außerdem muss die Bing Map nach jeder Aktion synchronisiert werden um die eigene Position anzuzeigen. Als alter Spaghetti-Programmierer hatte ich meine liebe Mühe mit dem asynchronen Programmiermodell ( was kommt nach was ? Welcher Code wird wann ausgeführt?) Das Ergebnis meiner Bemühungen zeige ich hier lieber nicht :-)&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Wer sich ernsthaft dafür interessiert, möge mir bitte schreiben (Kontakt-Link im Menü).&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Für die Liste der Kollegen in der Nähe habe ich das gleiche Prinzip angewendet:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Eine HTML Tabelle (der Body) ist an den dataContext gebunden. &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;…&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt; &lt;span style="color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;tbody &lt;/span&gt;&lt;span style="color:red;"&gt;sys&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;attach&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;dataview&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;class&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;sys-template&amp;quot; &lt;/span&gt;&lt;span style="color:red;"&gt;dataview&lt;/span&gt;&lt;span style="color:blue;"&gt;:&lt;/span&gt;&lt;span style="color:red;"&gt;dataprovider&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;{{ dataContext }}&amp;quot;
                    &lt;/span&gt;&lt;span style="color:red;"&gt;id&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;tbodycollegues&amp;quot;&amp;gt;
                    &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;tr&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                            &lt;/span&gt;{{ Nickname }}
                        &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                            &lt;/span&gt;{{ LocationText }}
                        &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                            &lt;/span&gt;{{ Distance }}
                        &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                           &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;a &lt;/span&gt;&lt;span style="color:red;"&gt;href&lt;/span&gt;&lt;span style="color:blue;"&gt;=&amp;quot;mailto: {{ Email }}&amp;quot;&amp;gt; &lt;/span&gt;{{ Email }} &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;a&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                        &amp;lt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                            &lt;/span&gt;{{ Phone }}
                        &lt;span style="color:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;td&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                    &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;tr&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
                &amp;lt;/&lt;/span&gt;&lt;span style="color:maroon;"&gt;tbody&lt;/span&gt;&lt;span style="color:blue;"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;…&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:blue;"&gt;&lt;font color="#000000"&gt;Beim erfolgreichen Ausführen der ersten Query (siehe oben) wird im Callback die Query für diese Tabelle ausgeführt. &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color:blue;"&gt;function &lt;/span&gt;UpdateColleguesListPoint(LatLong) {

       &lt;span style="color:blue;"&gt;var &lt;/span&gt;pointstring = LatLongToPoint(LatLong);

       &lt;span style="color:blue;"&gt;var &lt;/span&gt;querystring = &lt;span style="color:maroon;"&gt;&amp;quot;FindColleguesNearPoint?Point=&amp;quot; &lt;/span&gt;&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color:maroon;"&gt;           &lt;/span&gt;+ &lt;span style="color:maroon;"&gt;&amp;quot;&amp;#39;&amp;quot; &lt;/span&gt;+ pointstring + &lt;span style="color:maroon;"&gt;&amp;quot;&amp;#39;&amp;quot; &lt;/span&gt;+ &lt;span style="color:maroon;"&gt;&amp;quot;&amp;amp;howFar=&amp;#39;10000&amp;#39;&amp;quot; &lt;/span&gt;&lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color:maroon;"&gt;           &lt;/span&gt;+ &lt;span style="color:maroon;"&gt;&amp;quot;&amp;amp;nickName=&amp;#39;&lt;/span&gt;&lt;span style="background:yellow;color:maroon;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color:maroon;"&gt;: Page.User.Identity.Name &lt;/span&gt;&lt;span style="background:yellow;color:maroon;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;#39;&amp;quot;&lt;/span&gt;;
       oDataProxy.query(querystring, querySuceededCallback, queryFailedCallback);
   }


&lt;span style="color:blue;"&gt;function &lt;/span&gt;querySuceededCallback(result, context, operation) {

       &lt;span style="color:blue;"&gt;if &lt;/span&gt;(result.toString() == &lt;span style="color:maroon;"&gt;&amp;quot;&amp;quot;&lt;/span&gt;)
           $get(&lt;span style="color:maroon;"&gt;&amp;quot;infotext&amp;quot;&lt;/span&gt;).innerHTML = &lt;span style="color:maroon;"&gt;&amp;quot;no collegues found within 10km!&amp;quot;&lt;/span&gt;;
       &lt;span style="color:blue;"&gt;else
           &lt;/span&gt;$get(&lt;span style="color:maroon;"&gt;&amp;quot;infotext&amp;quot;&lt;/span&gt;).innerHTML = result.length.toString() + &lt;span style="color:maroon;"&gt;&amp;quot; collegues found within 10km!&amp;quot;&lt;/span&gt;;

       $find(&lt;span style="color:maroon;"&gt;&amp;quot;tbodycollegues&amp;quot;&lt;/span&gt;).set_data(result);

   }&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;&lt;font color="#000080"&gt;&lt;em&gt;&lt;font color="#000000"&gt;&lt;span style="color:maroon;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;Hier sehen wir wieder einen Querystring, diesmal für eine Stored Procedure:&lt;/p&gt;

&lt;p&gt;&lt;font color="#000080"&gt;&lt;em&gt;&lt;span style="color:maroon;"&gt;&lt;font color="#000000"&gt;FindColleguesNearPoint?Point=&lt;/font&gt;&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;#39;&lt;/span&gt;&lt;font color="#000000"&gt;POINT(7.5888276100158745 47.5491527235811)&lt;span style="color:maroon;"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color:maroon;"&gt;&amp;amp;howFar=&amp;#39;10000&amp;#39; &lt;/span&gt;&lt;/font&gt;&lt;/em&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:maroon;"&gt;&lt;font color="#000000"&gt;Wie kann unsere OData SP mit diesen Angaben die Distanz zum angemeldeten Benutzer berechnen ?&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:maroon;"&gt;&lt;font color="#000000"&gt;das Zauberwort heißt &lt;a title="Spatial data in SQL Server" href="http://www.microsoft.com/sqlserver/2008/en/us/spatial-data.aspx" target="_blank"&gt;Spatial Data&lt;/a&gt; und ist ein Feature von SQL Server. Im nächsten Beitrag sehen wir wie das funktioniert!&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:maroon;"&gt;&lt;font color="#000000"&gt;Danach werden wir die ganze Funktionalität (Bing Map Darstellung, OData CRUD) entsprechend auf dem Windows Phone 7 implementieren.&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:maroon;"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color:maroon;"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;font color="#000000"&gt;&lt;span style="color:maroon;"&gt;&amp;#160;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=172222" width="1" height="1"&gt;</description></item><item><title>TVDLunch: nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 4)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2011/03/11/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-4.aspx</link><pubDate>Fri, 11 Mar 2011 15:15:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:171612</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=171612</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2011/03/11/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-4.aspx#comments</comments><description>&lt;p&gt;im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx" target="_blank"&gt;ersten Teil&lt;/a&gt; habe ich eine groben Überblick über das Projekt gegeben.&lt;/p&gt;
&lt;p&gt;im zweiten Schritt haben wir Windows Azure Cloud Services &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx" target="_blank"&gt;einbezogen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx" target="_blank"&gt;dritten Teil&lt;/a&gt; haben wir angeschaut, was uns OData und WCF Data Services und das Entity Framework 4 (EF4) bringen können.&lt;/p&gt;
&lt;p&gt;In diesen Beitrag werden wir die auf SQL Azure gespeicherten Daten in einer ASP.NET MVC Applikation anzeigen und editieren. Außerdem werden wir das &lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=09905eea-f8d4-4af3-bb35-b479bf342e1e&amp;amp;DisplayLang=en" target="_blank"&gt;Bing Maps Ajax Control&lt;/a&gt; verwenden, um die Lokations-Daten der Kollegen auf der Karte anzuzeigen! Keine Angst, das geht alles ganz einfach, die APIs für Bing Maps sind gut dokumentiert und können &lt;a title="Bing Maps Ajax API" href="http://www.microsoft.com/maps/isdk/ajax/" target="_blank"&gt;hier&lt;/a&gt; live ausprobiert werden.&lt;/p&gt;
&lt;p&gt;Unsere kleine Web Applikation soll natürlich auch auf Azure laufen, dafür können wir das Web Projekt (für die ADO.NET Data Services) aus dem letzten Beitrag gut weiterverwenden.&lt;/p&gt;
&lt;p&gt;Wir brauchen nur die Basisfunktionalität aus ASP.NET MVC. Wir werden genau eine Seite erstellen, die gesamte Datenverarbeitung im Zusammenspiel mit dem Service machen wir per Ajax.&lt;/p&gt;
&lt;p&gt;Als Goodie können wir die Standard-Zugriffsverwaltung&amp;nbsp; von ASP.NET verwenden, dadurch können wir den Zugriff auf Kollegen beschränken und wissen innerhalb der Applikation immer wer angemeldet ist.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;(Für eine “echte” Unternehmensanwendung wäre natürlich eine Integration mit Active Directory sinnvoll. Das ist mit Hilfe von&amp;nbsp; &lt;a title="MSDN Artikel über Azure Access Control" href="http://msdn.microsoft.com/de-de/magazine/gg490345.aspx" target="_blank"&gt;Azure Appfabric Access Control&lt;/a&gt; technisch relativ einfach zu realisieren.) &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Hier ist ein Screenshot, der zeigt,&amp;nbsp; wie die fertige Applikation aussehen soll:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_3CA7F2AA.png" target="_blank"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="image" border="0" alt="image" src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_3BCF8CC0.png" width="244" height="218" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Der angemeldete Benutzer sieht eine Karte, auf der alle Kollegen in seiner Nähe in Form von kleinen Images abgebildet sind.&lt;/p&gt;
&lt;p&gt;dazu kann er seine aktuelle Position eingehen (Rechtsklick auf die karte) , und ein paar Infos eingeben, z.B. Uhrzeit und Restaurantvorschläge, etc..&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Wie funktioniert das ?&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Bing Maps stellt ein Ajax Control zur Verfügung, dass mit wenigen Zeilen Code für eigene Anwendungen verwendet werden kann.&lt;/p&gt;
&lt;p&gt;das Control ist vollständig in Javascript realisiert, es gibt keine ASP.NET Servercontrols oder ähnliches. es ist wird über eine Script-Referenz in unsere HTML Seite integriert. &lt;/p&gt;&lt;pre class="code"&gt;    &lt;span style="COLOR:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:maroon;"&gt;script &lt;/span&gt;&lt;span style="COLOR:red;"&gt;src&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&amp;quot;http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&amp;quot; &lt;/span&gt;&lt;span style="COLOR:red;"&gt;type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:maroon;"&gt;script&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;Für die Darstellung in der Webseite wird das Control an ein ganz normales &amp;lt;div&amp;gt; gebunden, unseres heisst &lt;span style="COLOR:maroon;"&gt;&amp;#39;myMap&amp;#39;.&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="COLOR:maroon;"&gt;&lt;font color="#000000"&gt;Das geschieht per Javascript, siehe&amp;nbsp; Function “GetMap()” weiter unten.&amp;nbsp; &lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="COLOR:maroon;"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4&gt;&lt;span style="COLOR:maroon;"&gt;&lt;font color="#000000"&gt;Wie passen wir das Bing Maps Control für unsere Applikation an?&lt;/font&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style="COLOR:maroon;"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="COLOR:maroon;"&gt;&lt;/span&gt;In unseren Beispiel möchten wir “Pushpins” auf der Karte abbilden, jeweils an den Koordinaten die der Mitarbeiter als seinen Standort angeklickt hat. Es sollen kleine Icons mit dem Foto des Mitarbeiters angezeigt werden, damit man gleich sieht, mit wem man es zu tun hat !&lt;/p&gt;
&lt;p&gt;Dazu benutzen wir 2 Fähigkeiten de Controls: &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1&lt;/strong&gt;. Die Koordinaten eines Mausklicks auf der Karte auszulesen&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; eine Liste von Objekten auf der Karte anzuzeigen ( per &lt;a title="geoRSS Wiki" href="http://www.georss.org/Main_Page" target="_blank"&gt;GeoRSS&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;hierfür brauchen wir ein bisschen Javascript, um mit dem API des Bing Maps Controls zu interagieren. &lt;/p&gt;
&lt;p&gt;hier fängt wie immer alles an (wir verwenden die ASP.NET Ajax Library) :&lt;/p&gt;&lt;pre class="code"&gt;Sys.onReady(&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;() {
           
           GetMap();
           AddMyLayer(VEDataType.GeoRSS);
        
       });&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;jetzt wird das Map Control geladen und auf eine beliebige Startposition (Mittelpunkt der Karte) initialisiert.&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;GetMap() {
           map = &lt;span style="COLOR:blue;"&gt;new &lt;/span&gt;VEMap(&lt;span style="COLOR:maroon;"&gt;&amp;#39;myMap&amp;#39;&lt;/span&gt;);
           map.LoadMap(&lt;span style="COLOR:blue;"&gt;new &lt;/span&gt;VELatLong(47.4312372344898, 8.5603666305542063), 12);
           map.AttachEvent(&lt;span style="COLOR:maroon;"&gt;&amp;quot;onmousedown&amp;quot;&lt;/span&gt;, MouseHandler);
       }&lt;/pre&gt;&lt;pre class="code"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;p&gt;&lt;span style="COLOR:blue;"&gt;&lt;font color="#000000"&gt;diese Funktion liest einen GeoRSS feed mit den Koordinaten unserer Kollegen, und setzt sie als Mini-Bilder auf die Karte:&lt;/font&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="COLOR:blue;"&gt;&lt;font color="#000000"&gt;&lt;/font&gt;&lt;/span&gt;var layer = new VEShapeLayer();&lt;/p&gt;
&lt;p&gt;&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;AddMyLayer(type) { &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; layer .DeleteAllShapes(); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; layer .SetClusteringConfiguration(VEClusteringType.Grid); &lt;font color="#006400"&gt;// determines how clusters of pushpins are displayed &lt;br /&gt;&lt;/font&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;var &lt;/span&gt;veLayerSpec = &lt;span style="COLOR:blue;"&gt;new &lt;/span&gt;VEShapeSourceSpecification(type, &lt;span style="COLOR:maroon;"&gt;&amp;#39;GeoFeed.svc&amp;#39;&lt;/span&gt;, l); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; map.ImportShapeLayerData(veLayerSpec, onFeedLoad); &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;Hinter dem Geofeed steckt eine Stored Procedure die wir über die ADO.NET Data Services exponieren.&lt;/p&gt;
&lt;p&gt;Den T_SQL Code sowie die Deklaration des Services zeige ich im nächsten Beitrag.&lt;/p&gt;
&lt;p&gt;das Map Control zentriert die Karte danach automatisch, so dass alle Punkte der Liste sichtbar sind.&lt;/p&gt;
&lt;p&gt;wenn der GeoRSS Feed geladen wurde, wird diese callback function&amp;nbsp; aufgerufen, welche die Icons platziert:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;onFeedLoad(feed) {
            &lt;span style="COLOR:#006400;"&gt;//alert(&amp;#39;RSS or Collection loaded. There are &amp;#39; + feed.GetShapeCount() + &amp;#39; items in this list.&amp;#39;);
            &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;var &lt;/span&gt;icon_org = &lt;span style="COLOR:maroon;"&gt;&amp;#39;&amp;lt;img src=&amp;quot;https://Picturesite.com/ma_photos/$.jpg&amp;quot; alt=&amp;quot;£&amp;quot; width=25 /&amp;gt;&amp;#39;&lt;/span&gt;;
            &lt;span style="COLOR:blue;"&gt;var &lt;/span&gt;icon = icon_org;
            &lt;span style="COLOR:blue;"&gt;for &lt;/span&gt;(&lt;span style="COLOR:blue;"&gt;var &lt;/span&gt;i = 0; i &amp;lt; l.GetShapeCount(); i++) {
                &lt;span style="COLOR:blue;"&gt;var &lt;/span&gt;shape = layer.GetShapeByIndex(i);
                icon = icon.replace(&lt;span style="COLOR:maroon;"&gt;&amp;#39;$&amp;#39;&lt;/span&gt;, shape.GetTitle());
                icon = icon.replace(&lt;span style="COLOR:maroon;"&gt;&amp;#39;£&amp;#39;&lt;/span&gt;, shape.GetDescription());
                shape.SetCustomIcon(icon);
                icon = icon_org;
            }
        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;&lt;br /&gt;jetzt haben wir alle Mitarbeiter als kleine Mini-Bildchen auf der Karte platziert.&lt;/p&gt;
&lt;p&gt;Als nächstes wollen wir unsere eigene Position festlegen:&lt;/p&gt;
&lt;p&gt;Der Mousehandler gibt uns (beim Rechtsklick) die aktuelle Position als Latitude/Longitude Kombination. &lt;/p&gt;
&lt;p&gt;Wir setzen dann ein Pushpin (Shape), das auf der Karte anzeigt, wo wir selbst uns befinden.&lt;/p&gt;&lt;pre class="code"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;MouseHandler(e) {

     &lt;span style="COLOR:blue;"&gt;if &lt;/span&gt;(e.rightMouseButton) {
         pixel = &lt;span style="COLOR:blue;"&gt;new &lt;/span&gt;VEPixel(e.mapX, e.mapY);

         &lt;span style="COLOR:#006400;"&gt;// this magic function calculates the geo position from the pixel that was clicked on the control!
         &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;var &lt;/span&gt;LatLong = map.PixelToLatLong(pixel);

         &lt;span style="COLOR:#006400;"&gt;//...later we will update our data here with the new geolocation

         // clear current shape
         &lt;/span&gt;DeleteShape();
         &lt;span style="COLOR:#006400;"&gt;// set new pushpin at mouse position
         &lt;/span&gt;AddPushpin(LatLong);

         &lt;span style="COLOR:#006400;"&gt;// we reload the list of geopoints with collegues near to us
         &lt;/span&gt;UpdateColleguesListPoint(LatLong);

     }
 }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;AddPushpin(LatLong) {
            shape = &lt;span style="COLOR:blue;"&gt;new &lt;/span&gt;VEShape(VEShapeType.Pushpin, LatLong);
            map.ClearInfoBoxStyles();
            shape.SetTitle(&lt;span style="COLOR:maroon;"&gt;&amp;quot;&amp;lt;h2&amp;gt;Ich!&amp;lt;/h2&amp;gt;&amp;quot;&lt;/span&gt;);
            shape.SetDescription(&lt;span style="COLOR:maroon;"&gt;&amp;#39;hier bin ich.&amp;#39;&lt;/span&gt;);

            &lt;span style="COLOR:#006400;"&gt;//Add the shape to the map         
            &lt;/span&gt;map.AddShape(shape);

        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;function &lt;/span&gt;DeleteShape() {
            &lt;span style="COLOR:blue;"&gt;if &lt;/span&gt;(shape != &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;) {
                map.DeleteShape(shape);
                shape = &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;;
            }
        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Das ist eigentlich alles was man für die Integration einer Bing Maps Karte in eine Web Applikation braucht!&lt;/p&gt;
&lt;p&gt;Zu sagen bleibt noch, das wir die gleiche serverseitige Funktionalität (GeoRSS Feed)&amp;nbsp; auch für die Windows Phone 7&amp;nbsp; Applikation verwenden werden!&lt;/p&gt;
&lt;p&gt;Al nächstes wollen wir die Distanz zu unseren Kollegen in Metern auf der Webseite anzeigen, und zwar synchronisiert mit dem Mausklick auf der Karte. Wie das geht, erfahrt Ihr im nächsten Beitrag . Außerdem werden wir unseren OData Service per Ajax Data Binding&amp;nbsp; an unsere Seite anbinden, und so CRUD Funktionalität für die &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx" target="_blank"&gt;TVDLunch Tabelle&lt;/a&gt;&amp;nbsp; bereitstellen.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Technorati-Tags: &lt;a href="http://technorati.com/tags/Odata" rel="tag"&gt;Odata&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Azure" rel="tag"&gt;Azure&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Ajax" rel="tag"&gt;Ajax&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Bing+Maps" rel="tag"&gt;Bing Maps&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Windows+Phone+7" rel="tag"&gt;Windows Phone 7&lt;/a&gt;,&lt;a href="http://technorati.com/tags/ASP.NET+MVC" rel="tag"&gt;ASP.NET MVC&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=171612" width="1" height="1"&gt;</description></item><item><title>TVDLunch: nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 3)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx</link><pubDate>Tue, 04 Jan 2011 08:37:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:168348</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=168348</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2011/01/04/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-3.aspx#comments</comments><description>&lt;p&gt;Passend zur Markteinführung des neuen Windows Phone 7 (WP7) haben wir uns &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx" target="_blank"&gt;überlegt&lt;/a&gt;, wie wir für einen Vortrag die aktuellen Technologien von Microsoft auf eine interessante und „präsentionstaugliche“ Art kombinieren können. Was dabei herausgekommen ist, möchte ich in den folgenden Beiträgen vorstellen.&lt;/p&gt;
&lt;p&gt;im &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx" target="_blank"&gt;ersten Teil&lt;/a&gt; habe ich eine groben Überblick über das Projekt gegeben.&lt;/p&gt;
&lt;p&gt;im zweiten Schritt haben wir Windows Azure Cloud Services &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx" target="_blank"&gt;einbezogen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;jetzt wollen wir untersuchen, was uns OData und WCF Data Services und das Entity Framework 4 (EF4) bringen können.&lt;/p&gt;
&lt;h3&gt;Warum OData ?&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.odata.org/" target="_blank"&gt;OData&lt;/a&gt; ist ein neuer Standard für den einfachen Austausch von Daten über das Internet.&amp;nbsp; Einfach heißt: es ist ein ein Format gewählt worden, das es möglichst vielen Technologien und Plattformen ermöglicht diese Daten zu beziehen und zu&amp;nbsp; verstehen. Interoperabilität ist damit endlich zur Realität geworden. Dafür hat man auf das bereits existierende AtomPub Protokoll aufgesetzt, und es um einige Features erweitert, die es für den Einsatz mit Datenobjekten optimieren.&lt;/p&gt;
&lt;p&gt;OData ist zwar von Microsoft entworfen und unterstützt, es wird aber nicht durch Patente und Lizenzpolitik zum Risiko für langfristige Investitionen durch Drittanbieter (siehe Java: Oracle vs. Google) . Microsoft garantiert das in diesem Dokument &lt;a href="http://www.microsoft.com/interop/osp/default.mspx"&gt;Microsoft Open Specification Promise (OSP)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Der wichtigste Punkt im OData Standard ist jedoch die URL-basierte Abfragemöglichkeit. Es wurde eine einfache Syntax geschaffen, die es ermöglicht, über die URL SQL-ähnliche Filter zu konstruieren. Dieses Feature sowie die Möglichkeit Daten per REST zu verarbeiten, ermöglicht es praktisch jeder technischen Plattform die über HTTP kommunizieren kann, OData Daten zu verwenden.&lt;/p&gt;
&lt;p&gt;Durch das einfache XML/JSON Format sowie die einfache Abfragemöglichkeit ist OData prädestiniert für die Verwendung in offenen Internet Szenarien.&lt;/p&gt;
&lt;p&gt;OData Services stellen Daten typischerweise generell zur Verfügung, die Art der Verwendung ist nicht festgelegt. Ein Beispiel sind öffentliche APIs von großen Anbietern wie z.B. Netflix. Einige interessante Beispiele findet man &lt;a href="http://www.odata.org/producers" target="_blank"&gt;hier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hier kann jeder Entwickler mit “seiner” Technologie auf den gesamten Katalog des Online Video Anbieters zugreifen um Applikationen zu bauen, z.B. für Smartphones oder das Web (Mashups)&lt;/p&gt;
&lt;p&gt;Ein anderes, ebenso interessantes Szenario findet man bei einigen amerikanischen Behörden: für den einfachen Datenaustausch zwischen verschiedenen Einrichtungen hat sich OData als bestens geeignet erwiesen.&lt;/p&gt;
&lt;p&gt;Microsoft verwendet OData auch in seinen eigenen Produkten, wichtig zu nennen sind hier z.B. Sharepoint, Reporting Services, sowie das Ad Hoc BI Tool PowerPivot.&amp;nbsp; Dieser Tatsache haben wir es wohl zu verdanken, dass auch auf der Tool Seite (.NET) gute Unterstützung vorhanden ist. So können wir mit wenigen Zeilen Code eine Datenbank per OData “veröffentlichen”.&lt;/p&gt;
&lt;p&gt;Dazu verwenden wir in unseren Beispiel Entity Framework 4 und WCF Data Services (a.k.a. ADO.NET Data Services a.k.a. Astoria)&lt;/p&gt;
&lt;p&gt;Das Entity Framework erklären wir hier nicht, wer mehr wissen will findet alle Infos &lt;a href="http://msdn.microsoft.com/en-us/data/aa937723" target="_blank"&gt;hier&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unser Datenmodell ist schnell&amp;nbsp;beschrieben :-)&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_338178BA.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="image" border="0" alt="image" src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_0C472F85.png" width="446" height="258" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Wir haben eine Tabelle TVDEmp, hier werden alle teilnehmenden Trivadis Mitarbeiter hinterlegt. In der Tabelle TVDLunch werden die aktuellen Daten für das Mittagessen gespeichert: Zeit, Ort und Mitarbeiter Kurzname (Nickname). Zu den Details kommen wir noch. Wir haben bewusst keine “echte” Relation (Foreign Key Constraint)&amp;nbsp; modelliert, um die Dinge einfach zu halten. Somit kann jede Entität für sich allein verwendet werden, ohne Joins. In einer “echten” Applikation könnte man als zusätzliche Abstraktionsschicht in der Datenbank einen View Layer definieren, der nach verschiedenen Kriterien optimiert werden kann ( Performance, Zugriffsberechtigung, etc.). Objektorientierte Zeitgenossen können das Gleiche mit einem verfeinerten Entity Model erzielen, oder mit Hilfe von LINQ.&lt;/p&gt;
&lt;h3&gt;Wie kommen Die Daten ins Internet ?&lt;/h3&gt;
&lt;p&gt;Das geht ziemlich einfach: wir brauchen ein Visual Studio Projekt, das eine WCF Data Services Komponente aufnehmen kann. ich empfehle hier ein ASP.NET MVC Projekt zu erzeugen, damit geht es perfekt.&lt;/p&gt;
&lt;p&gt;einen WCF Data Service hinzufügen:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_6C2C22C7.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="Dialog box WCF Data Services" border="0" alt="Dialog box WCF Data Services" src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_650CE64F.png" width="244" height="170" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;mit dem Hinzufügen dieser Komponente ist eigentlich schon fast alles erledigt. Wir müssen der Komponente nur&amp;nbsp; noch erklären , wo das EF Model ist, und welche Objekte mit welchen Rechten aufgerufen werden können. Dazu modifizieren wir den Code geringfügig:&lt;/p&gt;&lt;pre class="code"&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;public class &lt;/span&gt;&lt;span style="COLOR:#2b91af;"&gt;WcfDS &lt;/span&gt;: &lt;span style="COLOR:#2b91af;"&gt;DataService&lt;/span&gt;&amp;lt; TVDLunchWeb.Models.&lt;span style="COLOR:#2b91af;"&gt;TVDLunchEntities&lt;/span&gt;&amp;gt;
 {
     &lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:green;"&gt;// This method is called only once to initialize service-wide policies.

     &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;public static void &lt;/span&gt;InitializeService(&lt;span style="COLOR:#2b91af;"&gt;DataServiceConfiguration &lt;/span&gt;config)
     {
        
         config.SetEntitySetAccessRule(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;TVDEmp&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#2b91af;"&gt;EntitySetRights&lt;/span&gt;.All);
         config.SetEntitySetAccessRule(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;TVDLunch&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#2b91af;"&gt;EntitySetRights&lt;/span&gt;.All);
                     
         &lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:green;"&gt;// Make the remaining entity sets read-only.
         &lt;/span&gt;config.SetEntitySetAccessRule(&lt;span style="COLOR:#a31515;"&gt;&amp;quot;*&amp;quot;&lt;/span&gt;, &lt;span style="COLOR:#2b91af;"&gt;EntitySetRights&lt;/span&gt;.AllRead);

         config.DataServiceBehavior.MaxProtocolVersion = &lt;span style="COLOR:#2b91af;"&gt;DataServiceProtocolVersion&lt;/span&gt;.V2;
         
         

     }
     &lt;span style="COLOR:blue;"&gt;protected override void &lt;/span&gt;HandleException(&lt;span style="COLOR:#2b91af;"&gt;HandleExceptionArgs &lt;/span&gt;args)
     {
         &lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:green;"&gt;// need this to create a breakpoint and debug errors
         &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;base&lt;/span&gt;.HandleException(args);
     }

 }&lt;/font&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Den Exceptionhandler empfehle ich dringend, hier kann man zur Laufzeit einen breakpoint für das Debuggen setzen. So erleichtert man sich das Finden von Fehlern ungemein, da man das &lt;span style="COLOR:#2b91af;"&gt;HandleExceptionArgs &lt;font color="#000000"&gt;&lt;em&gt;args&lt;/em&gt; &lt;/font&gt;&lt;/span&gt;Objekt komfortabel in Visual Studio untersuchen kann. &lt;/p&gt;
&lt;p&gt;jetzt können wir das Projekt kompilieren und aus VS heraus testen. Im Browser geben wir dazu folgende URL ein:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://localhost:4332/WcfDS.svc/" href="http://localhost:4332/MyService.svc/"&gt;http://localhost:4332/MyService.svc/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;die Portnummer und den Namen des Services bitte entsprechend anpassen.&lt;/p&gt;
&lt;p&gt;dann sollte etwas in dieser Art erscheinen:&lt;/p&gt;
&lt;p&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;xml &lt;/span&gt;&lt;span style="COLOR:red;"&gt;version&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;encoding&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;utf-8&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;standalone&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;yes&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;?&amp;gt; &lt;br /&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;service &lt;/span&gt;&lt;span style="COLOR:red;"&gt;xml:base&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://localhost:4332/WcfDS.svc/&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;xmlns:atom&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://www.w3.org/2005/Atom&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;xmlns:app&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://www.w3.org/2007/app&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;xmlns&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://www.w3.org/2007/app&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;workspace&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;atom:title&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;Default&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;atom:title&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;collection &lt;/span&gt;&lt;span style="COLOR:red;"&gt;href&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDEmp&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;atom:title&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;TVDEmp&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;atom:title&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;collection&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;collection &lt;/span&gt;&lt;span style="COLOR:red;"&gt;href&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDLunch&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;atom:title&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;TVDLunch&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;atom:title&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;collection&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;nbsp; &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;workspace&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;br /&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;service&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR:blue;"&gt;&lt;font size="1"&gt;&amp;gt; &lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Das ist eine einfache strukturelle Beschreibung unseres Services.&lt;/p&gt;
&lt;p&gt;Ein kleiner Test zeigt uns, ob wir auch Daten aus der Datenbank laden können. Dazu geben wie den Namen einer Entität in der URL an:&lt;/p&gt;
&lt;p&gt;&lt;a title="http://localhost:4332/WcfDS.svc/" href="http://localhost:4332/MyService.svc/TVDLunch"&gt;http://localhost:4332/MyService.svc/TVDLunch&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;IE zeigt Odata Daten als Feed an.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_44F1D992.png"&gt;&lt;img style="BORDER-RIGHT-WIDTH:0px;DISPLAY:inline;BORDER-TOP-WIDTH:0px;BORDER-BOTTOM-WIDTH:0px;BORDER-LEFT-WIDTH:0px;" title="image" border="0" alt="image" src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_00B17246.png" width="244" height="239" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;hier ist das XML dazu (Testdaten) :&lt;/p&gt;&lt;pre class="code"&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;xml &lt;/span&gt;&lt;span style="COLOR:red;"&gt;version&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;encoding&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;utf-8&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;standalone&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;yes&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;?&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;feed &lt;/span&gt;&lt;span style="COLOR:red;"&gt;xml:base&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://localhost:4332/WcfDS.svc/&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;xmlns:d&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;xmlns:m&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/metadata&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;xmlns&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://www.w3.org/2005/Atom&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;title &lt;/span&gt;&lt;span style="COLOR:red;"&gt;type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;text&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;TVDLunch&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;title&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;id&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;http://localhost:4332/WcfDS.svc/TVDLunch&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;id&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;updated&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;2011-01-03T13:32:41Z&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;updated&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;link &lt;/span&gt;&lt;span style="COLOR:red;"&gt;rel&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;self&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;title&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDLunch&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;href&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDLunch&lt;/span&gt;&amp;quot; &lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;/&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;entry&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;id&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;http://localhost:4332/WcfDS.svc/TVDLunch(0)&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;id&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;title &lt;/span&gt;&lt;span style="COLOR:red;"&gt;type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;text&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;title&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;updated&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;2011-01-03T13:32:41Z&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;updated&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;author&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;name &lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;/&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;author&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;link &lt;/span&gt;&lt;span style="COLOR:red;"&gt;rel&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;edit&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;title&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDLunch&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;href&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDLunch(0)&lt;/span&gt;&amp;quot; &lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;category &lt;/span&gt;&lt;span style="COLOR:red;"&gt;term&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;TVDLunchModel.TVDLunch&lt;/span&gt;&amp;quot; &lt;span style="COLOR:red;"&gt;scheme&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;http://schemas.microsoft.com/ado/2007/08/dataservices/scheme&lt;/span&gt;&amp;quot; &lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;/&amp;gt;
    &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;content &lt;/span&gt;&lt;span style="COLOR:red;"&gt;type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;application/xml&lt;/span&gt;&amp;quot;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
      &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;m:properties&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:Id &lt;/span&gt;&lt;span style="COLOR:red;"&gt;m:type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;Edm.Int32&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;0&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:Id&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:Nickname&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;mik&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:Nickname&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:LunchTime &lt;/span&gt;&lt;span style="COLOR:red;"&gt;m:type&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;Edm.DateTime&lt;/span&gt;&amp;quot;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;2010-08-31T12:00:00&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:LunchTime&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:LocationText&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;Pianissimo&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:LocationText&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:Comment&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;I’m really hungry!&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:Comment&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
        &amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:GeoPoint&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;&lt;/span&gt;POINT(8.86871337890625, 50.84410451978965)&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;d:GeoPoint&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
      &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;m:properties&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
    &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;content&lt;/span&gt;&lt;/font&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt;
  &amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;entry&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR:blue;"&gt;&lt;font size="1"&gt;&amp;gt;
…&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;&lt;font size="1"&gt;…&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;span style="COLOR:blue;"&gt;&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&lt;font size="1"&gt;…&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class="code"&gt;&lt;font size="1"&gt;&lt;span style="COLOR:blue;"&gt;  &lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;feed&lt;/span&gt;&lt;/font&gt;&lt;span style="COLOR:blue;"&gt;&lt;font size="1"&gt;&amp;gt;
&lt;/font&gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Man kann schön sehen, dass die Daten tatsächlich als fortlaufender Feed geliefert werden. die “…” habe ich eingefügt, um Platz auf dieser Seite zu sparen.&lt;/p&gt;
&lt;p&gt;Die Felder innerhalb des &lt;span style="COLOR:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="COLOR:#a31515;"&gt;entry&lt;/span&gt;&lt;span style="COLOR:blue;"&gt;&amp;gt; &lt;/span&gt;Tags beinhalten die Daten aus unserer Tabelle. Zu den einzelnen Feldern (speziell das GeoPoint Feld) erkläre ich später mehr.&lt;/p&gt;
&lt;p&gt;Der WCF Data Service ist damit bereit! Er kann übrigens uch per REST auch Daten einfügen, updaten und löschen.&lt;/p&gt;
&lt;p&gt;Für unsere App haben wir noch 2 Stores Procedures in das System integriert. Diese können ebenfalls per URL aufgerufen werden und somit z.B. von einer Ajax Routine in JavaScript verwendet werden.&lt;/p&gt;
&lt;p&gt;das machen wir im nächsten Beitrag.&lt;/p&gt;
&lt;h3&gt;Geht das auch mit Azure ?&lt;/h3&gt;
&lt;p&gt;Selbstredend. Wir brauchen eine Visual Studio Azure Solution, in das wir das Web Projekt (als Web Role) einhängen.&lt;/p&gt;
&lt;p&gt;(Keine Ahnung wie das geht ? &lt;a href="http://msdn.microsoft.com/en-us/ff380142" target="_blank"&gt;hier&lt;/a&gt;&amp;nbsp; ist ein guter Startpunkt für Tutorials und Dokumentation) .&lt;/p&gt;
&lt;p&gt;In dieses Projekt fügen wir einen WCF Data Service ein , siehe oben. Das ist schon alles.&lt;/p&gt;
&lt;p&gt;Es macht natürlich Sinn, ab hier auch eine SQL Azure Datenbank zu verwenden. Dazu muss nur noch der Connectionstring in der Web.config Datei geändert werden.&lt;/p&gt;
&lt;p&gt;Nach dem Deployment können wir die Daten von der Azure Webadresse herunterladen. &lt;strong&gt;Wilkommen in der Cloud!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Möglichweise wird es mit Azure noch einfacher werden, einen OData Web Service zu erstellen.&lt;/p&gt;
&lt;p&gt;Dazu gibt es einen Versuch auf der Seite &lt;a title="https://www.sqlazurelabs.com/ConfigOData.aspx" href="https://www.sqlazurelabs.com/ConfigOData.aspx"&gt;https://www.sqlazurelabs.com/ConfigOData.aspx&lt;/a&gt;. Ich habe es aber leider bis jetzt nicht zum Laufen gebracht.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Und wie geht’s weiter?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Als nächstes bauen wir ein mit ASP.NET MVC ein Frontend, das die OData Daten per Ajax abruft und zurückschreibt.&lt;/p&gt;
&lt;p&gt;Hier werden wir auch das Bing Maps API kennenlernen.&lt;/p&gt;
&lt;p&gt;Im darauffolgenden Beitrag werden wir dann “endlich” zur Windows Phone 7 App kommen.&lt;/p&gt;
&lt;p&gt;Bis dahin: beste Wünsche für 2011!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=168348" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Azure/default.aspx">Azure</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Bing+Maps/default.aspx">Bing Maps</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/OData/default.aspx">OData</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/REST/default.aspx">REST</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/WP7/default.aspx">WP7</category></item><item><title>TVDLunch: nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 2)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx</link><pubDate>Tue, 28 Dec 2010 17:00:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:167864</guid><dc:creator>admin</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=167864</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;Passend zur Markteinführung des neuen Windows Phone 7 (WP7) haben wir uns &lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx" target="_blank"&gt;überlegt&lt;/a&gt;, wie wir für einen Vortrag die aktuellen Technologien von Microsoft auf eine interessante und „präsentionstaugliche“ Art kombinieren können. Was dabei herausgekommen ist, möchte ich in den folgenden Beiträgen vorstellen.&lt;/p&gt;  &lt;p&gt;Fangen wir also an mit &lt;/p&gt;  &lt;h5&gt;Windows Azure Cloud Services&lt;/h5&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;Mit Microsofts Cloud Angebot Azure nutzen wir die Möglichkeit, eine Anwendung hochskalierbar zu machen und die Kapazität bedarfsgesteuert regulieren zu können. Natürlich ist das ein bisschen übertrieben für eine kleine Anwendung wie TVDLunch. Das Beispiel kann aber die prinzipiellen Vorteile einer Cloud Lösung verdeutlichen. Ich möchte hier versuchen, mit einfachen Worten die Vorteile zu beschreiben:&lt;/p&gt;  &lt;p&gt;1. &lt;b&gt;Bedarfsgesteuert&lt;/b&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Warum soll man Server-Kapazität für 24h bezahlen wenn man sie effektiv nur 3h am Tag benötigt ?&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;Mit Azure ist es leicht, die Anwendung z.B. nach 15 Uhr auf „Standby“ zu schalten, dadurch sinken die Kosten auf ein Minimum. Dieses Prinzip kann auf viele Anwendungen übertragen werden. Wer dann noch Hunger hat, muss leider alleine Essen gehen...&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;2.&lt;b&gt; Skalierbar&lt;/b&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;TVDLunch hat logischerweise gegen 12:00 einen Peak in der Auslastung, wenn traditionell die meisten Menschen zum Essen gehen möchten. Damit keine gefährlichen Stress-Situationen durch Unterzuckerung entstehen (ausgelöst durch schlechte Performance des Web Services durch Überlastung und die damit verbundenen Wartezeiten) können bei Bedarf weitere Instanzen des Services gestartet werden. Sind alle Lunch-Verabredungen getätigt, kann man diese wieder abschalten.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;3. &lt;b&gt;Managed&lt;/b&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Für ein „Nicht-Line-Of-Business“System wie dieses (Ihr Magen sieht das vielleicht anders :-)) soll der Aufwand für Wartung und Betrieb so gering wie möglich sein. Es bietet sich also an, auf die preiswerten Cloud Services zu setzen. Extra-Kosten für die interne Betreuung des Systems, sowie für Leitungskapazität, Backup, Ausfallsicherung etc. fallen somit nicht an. Azure bietet hier ein Cent/Rappen genaues Abrechnungssystem für die bezogenen Leistungen, das die Kosten transparent macht.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;4. &lt;b&gt;Verfügbar&lt;/b&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Microsoft Azure nimmt uns das Problem ab, die Daten zu den Kollegen zu bringen, egal wo sich diese befinden (weltweit :-)). Grundsätzlich profitiert eine Cloud basierte Applikation von den „unendlich“ verfügbaren Kapazitäten der Grossanbieter. Das gilt z.B. auch für das Netzwerk: Auch eine kleine Anwendung wie TVDLunch muss in der Cloud nicht befürchten, auf der Datenleitung mit anderen Systemen zu konkurrieren. Das ist bei selbstbetriebenen Diensten nicht selbstverständlich, wenn die zentrale Internet-Anbindung des Unternehmens für viele Anwendungen gleichzeitig genutzt wird. &lt;/p&gt; &lt;/blockquote&gt;  &lt;h5&gt;Wie bringt man eine Applikation in die Azure Cloud ?&lt;/h5&gt;  &lt;p&gt;Mit einer Kreditkarte :-). Wer schon mal in einem Online Shop eingekauft hat, wird es auch ohne weiteres schaffen, einen Account bei Azure zu eröffnen. Kosten über eine Grundgebühr hinaus fallen grundsätzlich erst bei der ersten Nutzung an. Die aktuellen Preise finden Sie &lt;a href="http://www.microsoft.com/windowsazure/offers/"&gt;hier&lt;/a&gt;. Haben Sie einen MSDN Account ? dann können sie sofort &lt;a href="http://msdn.microsoft.com/de-ch/subscriptions/ee461076.aspx"&gt;loslegen&lt;/a&gt;. Haben Sie gerade ein Startup Unternehmen gegründet ? Dann ist &lt;a href="http://www.microsoft.com/germany/gruender/bizspark.mspx"&gt;BizSpark&lt;/a&gt; vielleicht interessant. Ein Förderprogramm für Gründer, das jetzt auch Cloud Dienste beinhaltet.&lt;/p&gt;  &lt;h5&gt;Und dann?&lt;/h5&gt;  &lt;p&gt;Microsoft Azure besteht aus 2 Angebotsbündeln: &lt;/p&gt;  &lt;p&gt;1. &lt;a href="http://www.microsoft.com/windowsazure/windowsazure/default.aspx"&gt;Windows Azure&lt;/a&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Compute, AppFabric, Queues und mehr.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;2. &lt;a href="http://www.microsoft.com/en-us/sqlazure/default.aspx"&gt;SQL Azure&lt;/a&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;SQL Datenbank, Data Sync, Reporting, Appliance&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Es würde den Rahmen diese Beitrages sprengen, wenn ich alle Komponenten hier einzeln erklären wollte. Wir haben für diese Projekt versucht, eine „klassische“ Web-Applikation in die Cloud (und dann aufs Handy) zu bringen. Dazu braucht man zunächst nur die &lt;a href="http://www.microsoft.com/windowsazure/compute/default.aspx"&gt;Windows Azure Compute&lt;/a&gt; Dienste ( Laufzeitumgebung für ASP.NET Anwendungen) sowie die relationale Datenbank &lt;a href="http://www.microsoft.com/en-us/SQLAzure/database.aspx"&gt;SQL Azure Database&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h5&gt;Was braucht man noch ?&lt;/h5&gt;  &lt;p&gt;Als nächstes wird Visual Studio Cloud-fähig gemacht: Laden Sie die das &lt;a href="http://www.microsoft.com/windowsazure/getstarted/default.aspx"&gt;Azure SDK&lt;/a&gt; herunter und installieren Sie es. Auf der verlinkte Seite finden sie eine Reihe von Links zu Dokumentation, Tutorials weiteren Downloads usw.. Keine VS Lizenz ? mit &lt;a href="http://www.microsoft.com/express/web/"&gt;Visual Studio Express&lt;/a&gt; geht es auch. &lt;/p&gt;  &lt;p&gt;Als .NET Entwickler haben Sie es bereits geahnt: In Visual Studio stehen jetzt eine Reihe von Projekt-Templates zur Verfügung, um .NET Anwendungen für die Cloud zu erstellen. Das Beste daran: Sie können Ihren Code sofort lokal testen und debuggen, wie eine „normale“ Webapplikation. Visual Studio stellt eine lokale Emulation der Cloud Laufzeitumgebung zur Verfügung. Wenn Sie mit Ihrer Lösung zufrieden sind, können sie diese auf Azure hochladen. Auch das geschieht direkt aus Visual Studio heraus. Ich werde später noch ein bisschen konkreter erklären, wie wir TVDLunch auf diese Weise erstellt haben.&lt;/p&gt;  &lt;p&gt;Mit dem neuen Silverlight Frontend kann man seine Azure Anwendungen im Browser verwalten. Man hat jeweils eine Test- sowie eine Produktivumgebung zur Verfügung, zwischen denen man die Anwendung einfach hin und her verschieben kann. Das dauert immer einige Minuten, man sollte diesen Schritt jeweils erst machen, wenn man ein neues Release lokal fertig getestet hat.    &lt;br /&gt;Mit dem gleiche Frontend stellt man auch die Anzahl der Instanzen ein (Skalierung), sowie weitere Parameter.&lt;/p&gt;  &lt;h5&gt;Und die Datenbank ?&lt;/h5&gt;  &lt;p&gt;Von hier sind es nur ein paar Mausklicks zur SQL Azure SQL Database. Hier legt man mit SQL Azure eine SQL Server 2008 Datenbank an, die sich aus Entwickler-Sicht wie eine „normale“ DB verhält. Man kann sich über SQL Server Management Studio damit verbinden, wie mit jeder anderen SQL Server Datenbank. (Voraussetzung ist, dass Sie eine Firewallregel eigerichtet haben). Eigentlich sehr unspektakulär.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image2_627DEC69.png"&gt;&lt;img src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb4_2310130C.png" style="border-width:0px;display:inline;" title="image_thumb[4]" alt="image_thumb[4]" border="0" height="167" width="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Im Detail gibt es (systembedingt) natürlich Unterschiede, vor allem bezogen auf User Management und Storage Parameter. Wer es genau wissen will, findet &lt;a href="http://msdn.microsoft.com/en-us/library/ee336241.aspx"&gt;hier&lt;/a&gt; alle Informationen.&lt;/p&gt;  &lt;h5&gt;Kann jetzt jeder auf die SQL Daten zugreifen ?&lt;/h5&gt;  &lt;p&gt;Wenn man es nicht will, selbstverständlich nicht. Die SQL Azure Datenbanken sind für die Verbindung mit anderen Systemen gedacht, nicht für den direkten Zugriff durch Endanwender. Dazu ist eine Firewall eingerichtet, die nur bestimmten IP-Adressen(Bereichen) Zugang erlaubt. Zusätzlich werden verschlüsselte Zugänge unterstützt. Wer zusätzlich noch die gespeicherten Daten verschlüsseln möchte, findet dazu Informationen &lt;a href="http://msdn.microsoft.com/en-us/magazine/ee291586.aspx"&gt;hier&lt;/a&gt;.     &lt;br /&gt;Neben dem Security Aspekten wollen wir die Speicherungsschicht in der Anwendung abstrahieren können. Dieses architektonische Mittel erlaubt es uns, die technische Implementierung zu verändern, ohne die andere Teile der Applikation zu beeinflussen. So können wir das System z.B. später leicht skalieren, in dem wir die Daten horizontal partitionieren (auf mehrere Server verteilen).&lt;/p&gt;  &lt;h5&gt;&lt;b&gt;Und wie geht es weiter?&lt;/b&gt;&lt;/h5&gt;  &lt;p&gt;jetzt haben wir gesehen, das Visual Studio auch im Cloud-Zeitalter der Dreh- und Angelpunkt für die .NET Applikationsentwicklung ist und bleibt. Das wird sich auch bei den nächsten Abschnitten des Projektes nicht ändern.&lt;/p&gt;  &lt;p&gt;Im nächsten Schritt legen wir eine Service Schicht über die Datenbank legen (OData Web Services) um den Zugriff nach unseren Vorstellungen zu erlauben. Dann werden wir diese Daten “konsumieren”, mit einem Ajax Web-Frontend, sowie einer Windows Phone Applikation. Für die Visualierung von Geo-Location Daten werden wir das API von Bing Maps verwenden. Ich hoffe das ich die Beiträge zeitnah liefern kann!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=167864" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Cloud/default.aspx">Cloud</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Azure/default.aspx">Azure</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/TVDLunch/default.aspx">TVDLunch</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Windows+Phone+7/default.aspx">Windows Phone 7</category></item><item><title>TVDLunch: Nie mehr alleine Mittagessen dank einer Location Based Windows Phone 7 App, basierend auf Azure, OData und Bing Maps (Teil 1)</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2010/12/27/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx</link><pubDate>Mon, 27 Dec 2010 15:43:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:167789</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=167789</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2010/12/27/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-1.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;Passend zur Markteinführung des neuen Windows Phone 7 (WP7) haben wir uns überlegt, wie wir für einen Vortrag die aktuellen Technologien von Microsoft auf eine interessante und „präsentionstaugliche“ Art kombinieren können. Was dabei herausgekommen ist, möchte ich in den folgenden Beiträgen vorstellen.&lt;/p&gt;  &lt;p&gt;Die Idee: eine Windows Phone 7 App, die es ermöglicht, sich einfach mit Kollegen zum Mittagessen zu verabreden.&lt;/p&gt;  &lt;p&gt;Was steckt dahinter? Trivadis Consultants sind oft verstreut in kleinen Teams oder allein bei grossen Kunden „unterwegs“. So verbringt man seine Pausen oft allein, obwohl man ahnt, dass Kollegen in der Nähe sind. Aber wie soll man die finden ? Eine E-Mail an Alle ist eine Möglichkeit, aber bei über 500 Kollegen ein bisschen unübersichtlich, wenn alle die gleiche Idee haben. Social Media (z.B. Twitter) wäre eine andere Möglichkeit, aber längst nicht alle Kollegen nutzen diese Medien aktiv, schon gar nicht für solche Trivialitäten.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/clip_image002_24DF4507.jpg"&gt;&lt;img src="http://blog.trivadis.com/blogs/michaelkoenings/clip_image002_thumb_63D0C5A2.jpg" style="border-width:0px;display:inline;" title="clip_image002" alt="clip_image002" border="0" height="151" width="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Es muss also eine Lösung her: TVDLunch!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/clip_image004_350B0D00.jpg"&gt;&lt;img src="http://blog.trivadis.com/blogs/michaelkoenings/clip_image004_thumb_0C1FF7F7.jpg" style="border-width:0px;display:inline;" title="clip_image004" alt="clip_image004" border="0" height="244" width="152" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Microsoft bietet uns alle benötigten „Legosteine“ um eine location-based Lösung zu bauen, die auch auf den neuen WP7 Smartphones funktioniert. „Location-based Service“ ist eine kurze Bezeichnung für einen Dienst, der positionsabhängige Daten, die zum Bespiel über die GPS-Empfänger der Handys empfangen werden, mit einbezieht. Mit dem Landkartendienst Bing Maps steht eine gute Möglichkeit zur Verfügung, um Geodaten auf Karten anzuzeigen, natürlich auch auf Smartphones.&lt;/p&gt;  &lt;p&gt;Die mit Silverlight erstellte TVDLunch App nutzt diese Dienste, um mit wenigen Klicks (oder besser: touches und swipes) die Bereitschaft zum Mittagessen, sowie die aktuelle Position an einen zentralen Service zu senden. Zugleich kann man Kollegen in der Nähe auf einer Karte „sehen“ , um mit diesen direkt Kontakt aufnehmen zu können.&lt;/p&gt;  &lt;p&gt;Damit der Dienst nicht nur WP7 Besitzern zur Verfügung steht , haben wir zusätzlich ein Web-Frontend realisiert, das die gleiche Funktionalität wie die App liefert, jedoch in klassischer HTML/Ajax Ausführung (ASP.NET MVC) . Diese Lösung könnte man zusätzlich noch IPhone und Android tauglich machen,&amp;nbsp; indem man die Seiten auf die spezifische Bildschirmgrösse der Geräte optimiert.&lt;/p&gt;  &lt;p&gt;Für die Umsetzung haben wir folgende Komponenten verwendet, die ich in einzelnen Beiträgen genauer beleuchten werde:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://windows.azure.com/"&gt;Windows Azure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.odata.org/" target="_blank"&gt;OData&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/maps/developers/web.aspx" target="_blank"&gt;Bing Maps&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://create.msdn.com/en-US/" target="_blank"&gt;Windows Phone 7&lt;/a&gt; (Silverlight)&lt;/p&gt;  &lt;p&gt;Hier ist ein Überblick, wie die Komponenten zusammenspielen:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/image_37FB242C.png"&gt;&lt;img src="http://blog.trivadis.com/blogs/michaelkoenings/image_thumb_3EEAB0E4.png" style="border-width:0px;display:inline;" title="image" alt="image" border="0" height="184" width="244" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Fangen wir also an mit &lt;/p&gt;  &lt;h5&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/archive/2010/12/28/tvdlunch-nie-mehr-alleine-mittagessen-dank-einer-location-based-windows-phone-7-app-basierend-auf-azure-odata-und-bing-maps-teil-2.aspx" target="_blank"&gt;Windows Azure Cloud Services&lt;/a&gt;&lt;/h5&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=167789" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/ASP-NET/default.aspx">ASP.NET</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Cloud/default.aspx">Cloud</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Azure/default.aspx">Azure</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/TVDLunch/default.aspx">TVDLunch</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Bing+Maps/default.aspx">Bing Maps</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/OData/default.aspx">OData</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Windows+Phone+7/default.aspx">Windows Phone 7</category></item><item><title>Silverlight 3 Spinning 3D Tag Cloud!</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2009/07/18/tagcloud.aspx</link><pubDate>Sat, 18 Jul 2009 10:35:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:38734</guid><dc:creator>admin</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=38734</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2009/07/18/tagcloud.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://blogs.tamtam.nl/peterg/2009/02/13/CreatingA3DTagcloudInSilverlightPart1.aspx" target="_blank"&gt;Here&lt;/a&gt; is a great tutorial on how to create a 3D Tag Cloud with Silverlight.&lt;/p&gt; &lt;p&gt;I combined it with a little routine (some regEx, too) that scrapes Links from a &lt;a href="http://blog.trivadis.com/tags/default.aspx" target="_blank"&gt;web page&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;How do you like it ? &lt;/p&gt; &lt;p&gt;The only thing that holds me back from putting it on the front page of our site is the quite extreme CPU consumption.. (check your Taskmanager!). Therefore I put a simple timer routine in it, that stops the spinning after 3 secs when the mouse left the control.&lt;/p&gt; &lt;p&gt;It can probably be optimised, maybe with a lower &amp;quot;frame rate&amp;quot;. If you want the code, just send me a mail!&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;move your mouse over it !&lt;/p&gt;  &lt;div id="errorLocation" style="font-size:small;color:Gray;"&gt;     &lt;/div&gt;     &lt;div id="silverlightControlHost"&gt;         &lt;object id="Xaml1" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="500"&gt;  		  &lt;param name="source" value="/blogs/michaelkoenings/WikiScraper.zip" /&gt;  		  &lt;param name="onError" value="onSilverlightError" /&gt; 	 	  &lt;param name="background" value="white" /&gt;  		  &lt;param name="minRuntimeVersion" value="3.0.40624.0" /&gt;  		  &lt;param name="autoUpgrade" value="true" /&gt; 	 	  &lt;a href="http://go.microsoft.com/fwlink/?LinkID=149156&amp;amp;v=3.0.40624.0" style="text-decoration:none;"&gt;   			  &lt;img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none;" /&gt;  		  &lt;/a&gt;  	    &lt;/object&gt; &lt;iframe style="visibility:hidden;height:0;width:0;border:0px;"&gt;&lt;/iframe&gt;     &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=38734" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/MS/default.aspx">MS</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/-NET35/default.aspx">.NET35</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/-NET/default.aspx">.NET</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/VS/default.aspx">VS</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Silverlight/default.aspx">Silverlight</category></item><item><title>How To: Create Age Pyramid Charts in Reporting Services 2008</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2009/06/29/how-to-create-age-pyramid-charts-in-reporting-services-2008.aspx</link><pubDate>Mon, 29 Jun 2009 08:40:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:38270</guid><dc:creator>admin</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=38270</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2009/06/29/how-to-create-age-pyramid-charts-in-reporting-services-2008.aspx#comments</comments><description>&lt;p&gt;I had to create charts for a HR department that show the&amp;nbsp; distribution of age (or years of service) and gender in organization units. The customer wanted that typical Christmas tree look, which shows a symmetric bar chart in two directions, like shown in the example below. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image002_2.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" border="0" alt="clip_image002" src="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image002_thumb.jpg" width="441" height="463" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are two challenges here: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;make the tree look symmetric, the left and right bars should be in line. 
&lt;li&gt;make the labels and axis show positive values, even on the left side of the graph.&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;How can you achieve that in Reporting Services ?&lt;/p&gt;
&lt;p&gt;We use the Dundas chart control with the Bar Chart layout. A stacked bar chart did not work too well for me, it did not put the labels on the tip of the bars. &lt;/p&gt;
&lt;p&gt;To have the values point in to directions multiply one set of data with -1. you can do that in your query or by editing the value expression.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image002%5B4%5D.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" border="0" alt="clip_image002[4]" src="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image0024_thumb.jpg" width="483" height="359" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;T&lt;em&gt;he value expression for the data column might look like this:&lt;/em&gt; 
&lt;p&gt;&lt;em&gt;&lt;/em&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;=IIF(Fields!Gender.Value = &amp;quot;Male&amp;quot; , Sum(Fields!Head_Count.Value),Sum(Fields!Head_Count.Value)*-1)&lt;/strong&gt;&lt;/em&gt; 
&lt;p&gt;&lt;em&gt;&lt;/em&gt;
&lt;p&gt;&lt;em&gt;Since we have gender on one axis, it will show the values in two different colours.&lt;/em&gt; 
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image00215.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" border="0" alt="clip_image002[15]" src="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image00215_thumb.jpg" width="425" height="352" /&gt;&lt;/a&gt; 
&lt;p&gt;The default settings of the bar chart will draw the different bars with a little offset (side by side), so it would not look symmetrically. I found this parameter that sorts this one out: 
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image00210.jpg"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" border="0" alt="clip_image002[10]" src="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image00210_thumb.jpg" width="432" height="261" /&gt;&lt;/a&gt; 
&lt;p&gt;the &lt;strong&gt;Custom Attribute&lt;/strong&gt; &lt;strong&gt;DrawSidebySide&lt;/strong&gt;&amp;nbsp;of the Chart Series should be set to &lt;strong&gt;False&lt;/strong&gt;. Now the two bars for each gender in one time period are in line nicely.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What&amp;#39;s left to do?&lt;/p&gt;
&lt;p&gt;We need to take care of the negative label values for the gender pointing to the left. You guessed how I did it:&lt;/p&gt;
&lt;p&gt;change the series label &lt;strong&gt;Format&lt;/strong&gt; property and the Axis &lt;strong&gt;LabelsFormat&lt;/strong&gt; to your wish:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;0;0&lt;/strong&gt;&amp;nbsp; did the job for me.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/image_6.png"&gt;&lt;img style="BORDER-BOTTOM:0px;BORDER-LEFT:0px;BORDER-TOP:0px;BORDER-RIGHT:0px;" border="0" alt="image" src="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/image_thumb_2.png" width="410" height="485" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;That&amp;#39;s it!&amp;nbsp; Maybe you have a better way to do it ? Let us know! Put a comment!&lt;/p&gt;
&lt;p&gt;Too brief ? ask questions!&lt;/p&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;PADDING-TOP:0px;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:2a729bc7-61f4-4cc0-83c1-e157a8e39238" class="wlWriterSmartContent"&gt;Technorati-Tags: &lt;a href="http://technorati.com/tags/Reporting%20Services" rel="tag"&gt;Reporting Services&lt;/a&gt;,&lt;a href="http://technorati.com/tags/HowTo" rel="tag"&gt;HowTo&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Charts" rel="tag"&gt;Charts&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Age%20pyramid" rel="tag"&gt;Age pyramid&lt;/a&gt;,&lt;a href="http://technorati.com/tags/RS2008" rel="tag"&gt;RS2008&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowToCreateAgePyramidChartsinReportingSe_95C5/clip_image002%5B4%5D.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=38270" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/HowTo/default.aspx">HowTo</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Tutorial/default.aspx">Tutorial</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Charts/default.aspx">Charts</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Reporting+Services/default.aspx">Reporting Services</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/RS2008/default.aspx">RS2008</category></item><item><title>How To: get a RSS feed from BlogSpot filtered by a Tag</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2009/06/11/how-to-get-a-rss-feed-from-blogspot-filtered-by-a-tag.aspx</link><pubDate>Thu, 11 Jun 2009 12:30:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:37989</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=37989</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2009/06/11/how-to-get-a-rss-feed-from-blogspot-filtered-by-a-tag.aspx#comments</comments><description>&lt;p&gt;by default Blogspot offers Atom feeds, which can not be digested by some systems (like our Community Server)&lt;/p&gt;
&lt;p&gt;but there is help! try this syntax : &lt;/p&gt;
&lt;p&gt;&lt;a href="http://yourfantasticblog.blogspot.com/feeds/posts/default/-/TheTag?alt=rss"&gt;http://yourfantasticblog.blogspot.com/feeds/posts/default/-/TheTag?alt=rss&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;i put&amp;nbsp;this here so&amp;nbsp;I don&amp;#39;t have to remember it next time I&amp;nbsp;need it &lt;img src="http://blog.trivadis.com/emoticons/emotion-11.gif" alt="Cool" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=37989" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/HowTo/default.aspx">HowTo</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/BlogSpot/default.aspx">BlogSpot</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/RSS/default.aspx">RSS</category></item><item><title>Cloud Computing In Even Simpler Words</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2009/04/15/cloud-computing-in-simple-words-2.aspx</link><pubDate>Wed, 15 Apr 2009 07:55:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:32950</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=32950</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2009/04/15/cloud-computing-in-simple-words-2.aspx#comments</comments><description>&lt;p&gt;I&amp;nbsp;like this one too, it emphasizes the scalability of cloud computing a bit more.&lt;/p&gt;
&lt;p&gt;A&amp;nbsp;bit like &amp;quot;Sendung mit der Maus&amp;quot; style, but an excellent presentation! (check the feedback on youtube)&lt;/p&gt;
&lt;p&gt;I&amp;nbsp;hope you enjoy it, it&amp;#39;s only about 5 minutes long.&lt;/p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/QJncFirhjPg&amp;amp;hl=de&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;
&lt;embed src="http://www.youtube.com/v/QJncFirhjPg&amp;amp;hl=de&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=32950" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Cloud/default.aspx">Cloud</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Video/default.aspx">Video</category></item><item><title>Cloud Computing explained in simple words</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2009/04/14/cloud-computing-explained-in-simple-words.aspx</link><pubDate>Tue, 14 Apr 2009 09:35:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:32411</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=32411</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2009/04/14/cloud-computing-explained-in-simple-words.aspx#comments</comments><description>&lt;p&gt;Ok, maybe a bit too simple for a geek like you... &lt;img src="http://blog.trivadis.com/emoticons/emotion-11.gif" alt="Cool" /&gt;&lt;/p&gt;
&lt;p&gt;Anyway, just watch it in your coffee break, and you&amp;#39;ll have a basic understanding&amp;nbsp;of what it&amp;#39;s all about.&lt;/p&gt;
&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/XdBd14rjcs0&amp;amp;hl=de&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x006699&amp;amp;color2=0x54abd6"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;
&lt;embed src="http://www.youtube.com/v/XdBd14rjcs0&amp;amp;hl=de&amp;amp;fs=1&amp;amp;rel=0&amp;amp;color1=0x006699&amp;amp;color2=0x54abd6" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=32411" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Cloud/default.aspx">Cloud</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Video/default.aspx">Video</category></item><item><title>Oslo is here!</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2008/11/02/oslo-is-here.aspx</link><pubDate>Sun, 02 Nov 2008 13:53:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:3958</guid><dc:creator>admin</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=3958</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2008/11/02/oslo-is-here.aspx#comments</comments><description>&lt;p&gt;at the&amp;nbsp; &lt;a title="http://channel9.msdn.com/pdc2008/TL23/" href="http://channel9.msdn.com/pdc2008/TL23/"&gt;PDC&lt;/a&gt; Douglas Purdy (together with Vijaye Raji) finally presented Oslo (quite entertaining, it&amp;#39;s long but it&amp;#39;s worth it)&lt;/p&gt; &lt;p&gt;Oslo comprises 3 things: &lt;/p&gt; &lt;p&gt;A &lt;u&gt;language&lt;/u&gt;: &amp;quot;M&amp;quot; to model domain specific models and languages (grammars)&lt;/p&gt; &lt;p&gt;A &lt;u&gt;tool:&lt;/u&gt; &amp;quot;Quadrant&amp;quot; to visualize models and to give it simple views (yes views , like in MVC).&lt;/p&gt; &lt;p&gt;A &lt;u&gt;repository&lt;/u&gt;: (basically a SQL Server database) to store models and data&lt;/p&gt; &lt;p&gt;find more information &lt;a href="http://msdn.microsoft.com/oslo" target="_blank"&gt;here&lt;/a&gt;, the SDK is ready for download.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;what&amp;#39;s so special about Oslo?&lt;/p&gt; &lt;p&gt;Microsoft skipped the classic UML/MDA thing and started something completely new. Well, not that new, actually, people (outside the MS world) do use dynamic languages (especially Ruby) to create DSLs for quite some time now. But it&amp;#39;s good to see that MS picks up good ideas [1].&lt;/p&gt; &lt;p&gt;It&amp;#39;s all about better readability, less (better: no) plumbing code, low noise (less braces and brackets, semicolons, declarations, typing, initializations, castings etc.) .&amp;nbsp; All this is intended&amp;nbsp; to gain productivity: we can express our intent directly in simple code, whoever needs to read it will understand it better.&lt;/p&gt; &lt;p&gt;Microsoft takes these concepts and puts it on steroids: all dynamic, visual tools, Intellisense , all the goodness. The complexity of WCF, WF, EF and any other complex domain can now be expressed in domain specific code, we (the developers) do not have to deep dive into XML (XAML...)and APIs in all its flavors anymore (you can still do that if you need to, its all still there).&lt;/p&gt; &lt;p&gt;Check out the upcoming shows on this topic, they will explain the modeling language &amp;quot;M&amp;quot; in more detail.&lt;/p&gt; &lt;p&gt;That&amp;#39;s&amp;nbsp; the beginning of a new era for Microsoft. The post- &amp;quot;write to much code and deal with clumsy XML files&amp;quot; era. Very cool. ;-)&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;[1]&lt;/p&gt; &lt;p&gt;Check out &lt;a href="http://rspec.info/"&gt;RSpec&lt;/a&gt; (a language to describe expected behaviour for Behaviour Driven Development), &lt;a href="http://haml.hamptoncatlin.com/"&gt;HAML&lt;/a&gt; (a better MVC-View language for creating HTML) and &lt;a href="http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html"&gt;SASS&lt;/a&gt; (same thing for CSS) to see what I mean (I forgot &lt;a href="http://yaml.org/"&gt;YAML&lt;/a&gt;, which is a human-friendly data format). BTW,&amp;nbsp; All these great tools live in in &lt;a href="http://www.rubyonrails.com/"&gt;Ruby on Rails&lt;/a&gt;. For me,&amp;nbsp; &lt;a href="http://en.wikipedia.org/wiki/David_Heinemeier_Hansson"&gt;DHH&lt;/a&gt;s (the creator of RoR) greatest achievement is that he opened our eyes: development&amp;nbsp; should be as clear and simple like &lt;a href="http://images.google.com/images?q=arne+jacobsen&amp;amp;hl=de&amp;amp;rls=com.microsoft:en-us:IE-SearchBox&amp;amp;rlz=1I7GFRC_en-US&amp;amp;um=1&amp;amp;ie=UTF-8&amp;amp;sa=X&amp;amp;oi=images&amp;amp;ct=title"&gt;Danish Design&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=3958" width="1" height="1"&gt;</description></item><item><title>Don opens the Box on Oslo</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2008/10/16/don-opens-the-box-on-oslo.aspx</link><pubDate>Thu, 16 Oct 2008 19:33:21 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:2294</guid><dc:creator>admin</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=2294</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2008/10/16/don-opens-the-box-on-oslo.aspx#comments</comments><description>&lt;p&gt;Don Box and Doug Purdy where on &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=385" target="_blank"&gt;Dot.Net Rocks&lt;/a&gt;. I was quite excited to listen to them this morning on my morning commute to Basle. But I&amp;#39;m still confused: what is Oslo ? They still where talking in riddles, not telling any details. There are some traces in the blogs, like &lt;a href="http://douglaspurdy.com/2008/09/06/what-is-oslo/" target="_blank"&gt;Doug put it in 3 bullet points&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;em&gt;To that end, we have boiled down Oslo to three very simple things: &lt;/em&gt; &lt;ul&gt; &lt;li&gt;&lt;em&gt;A &lt;b&gt;tool&lt;/b&gt; that helps people define and interact with models in a rich and visual manner &lt;/em&gt; &lt;li&gt;&lt;em&gt;A &lt;b&gt;language&lt;/b&gt; that helps people create and use textual domain-specific languages and data models &lt;/em&gt; &lt;li&gt;&lt;em&gt;A relational &lt;b&gt;repository &lt;/b&gt;that makes models available to both tools and platform components &lt;/em&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;em&gt;That is it.&amp;nbsp; That is all Oslo is.&amp;nbsp; Oslo is just the modeling platform. &lt;/em&gt; &lt;p&gt;On the DNR show Doug said things like: &amp;quot;the next big thing&amp;quot; ...  &lt;p&gt;well, let&amp;#39;s see what they will show on the &lt;a href="https://sessions.microsoftpdc.com/public/sessions.aspx" target="_blank"&gt;PDC&lt;/a&gt; starting October 27th. There will be 6 sessions about Oslo.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=2294" width="1" height="1"&gt;</description></item><item><title>How To Do a Scrum Project With Busy Consultants</title><link>http://blog.trivadis.com/b/michaelkoenings/archive/2008/08/15/how-to-do-a-scrum-project-with-busy-consultants.aspx</link><pubDate>Fri, 15 Aug 2008 12:20:00 GMT</pubDate><guid isPermaLink="false">7f420732-9615-472e-9723-d9bd9f35b01c:716</guid><dc:creator>admin</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.trivadis.com/b/michaelkoenings/rsscomments.aspx?WeblogPostID=716</wfw:commentRss><comments>http://blog.trivadis.com/b/michaelkoenings/archive/2008/08/15/how-to-do-a-scrum-project-with-busy-consultants.aspx#comments</comments><description>&lt;p&gt;Inspired by the great interview on &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=322"&gt;DotNetRocks&lt;/a&gt; with Stephen Forte, who leads Scrum style agile projects with teams distributed around the globe, I decided: it must be possible to do agile project management with tools that are reachable from everywhere through the Internet. The members of my current project team do not always work together at the same place, they all have tightly scheduled calendars, hopping from one customer project to the next. But almost everywhere they have their mobile phones and a computer in reach. &lt;/p&gt;
&lt;p&gt;One rule in SCRUM is the daily &lt;a href="http://en.wikipedia.org/wiki/Stand-up_meeting"&gt;stand-up meeting&lt;/a&gt;, where every team member tells what he or she was doing the last day , what is next and what impediments keep her or him from continuing the work.&lt;/p&gt;
&lt;p&gt;Normally you will do that in&amp;nbsp; in front of a board with index cards, where all your tasks of the current sprint are written on.&amp;nbsp; The idea is to have a simple visual representation of your work items. The index cards and a simple spreadsheet (the &amp;quot;scrum sheet&amp;quot;) that records the state of the tasks is all you need to do your meeting. But how can you do that when not everybody is in the same room ?&amp;nbsp; &lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;backlog and sprint management&lt;/strong&gt; we use the hosted &lt;a href="http://www.versionone.com/products_V1Team_Overview.asp"&gt;VersionOne Team Edition&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is&amp;nbsp; a free online tool (a V1 representative will call you back) to manage agile projects, it allows up to&amp;nbsp; 5 team members. The clean Ajax-style UI makes it really easy to use. &lt;/p&gt;
&lt;p&gt;it sports a very cool &lt;strong&gt;standup dashboard&lt;/strong&gt; which emulates the index card/scrum sheet view in the browser.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowtodoaScrumProjectwithbusyconsultants_C985/VersionOne_StandupDashboard_lg_2.jpg" target="_blank"&gt;&lt;img style="BORDER-RIGHT:0px;BORDER-TOP:0px;BORDER-LEFT:0px;BORDER-BOTTOM:0px;" height="244" alt="VersionOne Standup Dashboard" src="http://blog.trivadis.com/blogs/michaelkoenings/WindowsLiveWriter/HowtodoaScrumProjectwithbusyconsultants_C985/VersionOne_StandupDashboard_lg_thumb.jpg" width="242" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;this view is interactive, so every connected team member can move tasks around, change task information&amp;nbsp; and so on. Changes will be reflected&amp;nbsp; (after clicking an update button) on all browsers. This can be a great tool to do a &amp;quot;distributed&amp;quot; scrum meeting. I will tell you more about our experiences with it, when we used it for a while...&lt;/p&gt;
&lt;p&gt;There are other tools out there, (you probably heard about &lt;a href="http://www.basecamphq.com/"&gt;basecamp&lt;/a&gt; from the RoR Company 37Signals). I decided to use V1 because it is really focusing to support scrum. &lt;a href="http://studios.thoughtworks.com/mingle-project-intelligence/"&gt;Mingle&lt;/a&gt; from Fowler&amp;#39;s&amp;nbsp;ThoughtWorks was another candidate, but they don&amp;#39;t offer a hosted version!&lt;/p&gt;
&lt;p&gt;For team &lt;strong&gt;time management&lt;/strong&gt; we use a simple &lt;a href="http://www.google.com/calendar/"&gt;google calendar&lt;/a&gt;. Its the easiest way to share information about the presence of the team members. you can access it from everywhere, even with&amp;nbsp; smartphones and PDAs. you can integrate the google calendar with exchange and other systems to your desire. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;stand-up meetings&lt;/strong&gt;:&amp;nbsp; a conference call is perfect for this. there a lots of providers to make it as simple as possible. all you need is a appointment time, a telephone and a pin number. Services like &lt;a href="http://www.powwownow.com/"&gt;powwownow&lt;/a&gt; make that very easy. Or use &lt;a href="http://www.skype.com/help/guides/makeconferencecall_windows/"&gt;Skype&lt;/a&gt; ! The biggest challenge is to get every person involved sitting in front of a computer at a certain time...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code Management:&lt;/strong&gt; my company&amp;nbsp; has&amp;nbsp; a subversion service running that can be accessed from the Internet. If you are not in this comfortable situation: try project services like &lt;a title="http://www.assembla.com/" href="http://www.assembla.com/" target="_blank"&gt;assembla&lt;/a&gt;, they offer complete &amp;quot;team spaces&amp;quot; for free, including subversion and other helpful tools for collaboration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Build management&lt;/strong&gt;: our current project is about BI, so we don&amp;#39;t need a classic build or even continuous integration environment to build our code base yet.&amp;nbsp; But the next project will come soon... There is something coming up but I&amp;#39;m not supposed to talk about it yet . :-)&lt;/p&gt;
&lt;p&gt;I will let you know how things worked out...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blog.trivadis.com/aggbug.aspx?PostID=716" width="1" height="1"&gt;</description><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Agile+Development/default.aspx">Agile Development</category><category domain="http://blog.trivadis.com/b/michaelkoenings/archive/tags/Scrum/default.aspx">Scrum</category></item></channel></rss>