ADO.NET DataServices mit eigenen Service Methoden erweitern und vom Silverlight Client nutzen

Die ADO.NET DataServices sind seit dem .NET Framework 3.5 SP1 Bestandteil des .NET Frameworks. In verteilten Anwendungen kann man die ADO.NET DataServices nutzen, um Daten aus Linq-Providern via REST Services für Clients zur Verfügung zu stellen. Ein typischer Anwendungsfall ist die Bereitstellung von Daten aus relationalen Datenbank für Http-Client. Das nachfolgende Schaubild verdeutlicht diese Architektur.

image

Besonders elegant lassen sich diese ADO.NET DataServices von Silverlight Clients nutzen. Durch eine Silverlight Client Bibliothek kann man in dieser Programmierumgebung in Linq-artiger Syntax auf die DataServices zugreifen. Das Gleiche gilt auch für .NET Clients. Mehr Informationen zu ADO.NET DataServices findet man unter: “Expose And Consume Data in A Web Services World” http://msdn.microsoft.com/en-us/magazine/cc748663.aspx

Das Serviceinterface, dass ADO.NET DataServices in einen WebProject automatisch für Sie anlegen, orientiert sich sehr stark an den Daten, die typischerweise aus einer relationalen Datenbank angeboten werden.

Was aber, wenn man eigene, zusätzliche Daten anbieten will, die halt eben nicht aus der Datenbank kommen?

Wenn es sich um absehbar vielen neue Methoden und Daten handelt, kann man natürlich einen neuen WCF Service anlegen. Das erhöht allerdings die Komplexität der Anwendung auf der Server- und Client-Seite.

Wenn es sich aus verschiedenen Gründen nicht lohnt, einen neuen WCF basierten Service zur Verfügung zu stellen, kann man auch den vorhandenen ADO.NET DataServices Service, um die eigenen benötigten Funktionen erweitern.

Diese Erweiterungen sind aber ein bisschen tricky.

Wichtig ist zu beachten, dass die Methoden nur bestimmte Rückgabewerte zulassen. So lässt sich zwar einfach ein Serveraufruf ohne Rückgabewert konstruieren und aufrufen. Wie aber gebe ich Daten von Server zurück.

Wie aus dem obigen Bild hervorgeht, müssen die Rückgabewerte vom Typ IQueryable sein. Weiterhin muss bei der Servermethode mit den Attribute „WebGet“ das Rest Protokoll eingeschaltet werden.

Anbei eine einfache Methode, die Strings vom Server zurückgibt:

         [SingleResult]
        [WebGet]
        public IQueryable<string> EchoMsg( string msg )
        {
            System.Diagnostics.Trace.WriteLine( msg ); 
            List<string> lst = new List<string>() { string.Format( "{0} - {1} - {2} - {3}", Environment.MachineName, Environment.OSVersion, DateTime.Now.TimeOfDay.ToString(), msg ) };         
            return lst.AsQueryable<string>();
        }

Neben der Deklaration der Methode müssen auch noch die Zugriffrechte mit „SetServiceOperationAccessRule” auf diese Methode gesetzt werden, damit sie von Clients aufgerufen werden kann.

         public static void InitializeService( IDataServiceConfiguration config )
        {
            config.SetEntitySetAccessRule( "*", EntitySetRights.All );
            config.SetServiceOperationAccessRule( "EchoMsg", ServiceOperationRights.All ); 

#if DEBUG
            config.UseVerboseErrors = true; 
#endif                 
        }

Die Silverlight Client Seite für diese Servermethode sieht wie folgt aus:

         private void ShowEmployee( object sender, RoutedEventArgs e )
        {
            NwServer.NorthwindEntities dbCtx = new DsClient.NwServer.NorthwindEntities( new Uri( "http://vista3gunnard/DataSvcsSample/NorthwindSvc.svc" ) );       

            IAsyncResult r = dbCtx.BeginExecute<string>( new Uri( "http://localhost/DataSvcsSample/NorthwindSvc.svc/EchoMsg?msg='Hello'" ),
                    new AsyncCallback( DisplayResult ),
                    dbCtx );
        }

        public void DisplayString( object o )
        {
            if (o is QueryOperationResponse<string>)
            {
                QueryOperationResponse<string> qr = o as QueryOperationResponse<string>;
                System.Diagnostics.Debug.WriteLine( "result = " + qr.FirstOrDefault() );
            }
        }

Der Aufruf der händischen hinzugefügt Servermethode „EchoMsg“ funktioniert von Silverlight Client aus nur über das REST Uri Schema „http://localhost/DataSvcsSample/NorthwindSvc.svc/EchoMsg?msg='Hello'“. Das muss so sein, da für ADO.NET DataServices V1.0 keine EchoMsg Methode im Silverlight Proxy generiert wird.

By the way … auch auf die EntitySets kann man in oben beschriebener Weise zugreifen, da es sich ja um REST handelt. Das URI Schema, welches DataServices verwendet, sieht wie folgt aus:

 http://<host>/<vdir>/<service.svc>/<EntitySet>[(<Key>)[/<NavigationProperty>[(<Key>)/...]]] 

 

Viel Spass beim Ausprobieren … GunnarD