OpenSocial Apps entwickeln mit ASP.NET (Autor: Dariusz Parys, Microsoft Deutschland GmbH)

Posted on by

Soziale Netzwerke sind beliebter denn je. Ob Facebook, MySpace oder StudiVZ, jedes dieser Netzwerke hat eine enorme Benutzerzahl, gerade deswegen sind diese Plattformen auch für Entwickler interessant geworden. Eine funktional interessante Anwendung findet oft schnell mehrere Tausend Benutzer und so manche Softwareschmiede ist zu Ruhm und Reichtum gekommen (z.B. Zynga mit Farmville ).

Egal was die persönlichen Beweggründe sind Anwendungen für Soziale Netzwerke zu schreiben, es gibt für all diese Netzwerke eine Hürde: Die API der Plattform.

StudiVZ ist hier den Weg der Standardisierung gegangen. StudiVZ setzt bei der Plattform API ganz auf die OpenSocial API mit einigen speziellen VZ Erweiterungen. Für Entwickler hat die OpenSocial API den Vorteil das die Apps im Prinzip einfacher auf andere Plattformen, die ebenfalls die OpenSocial API implementieren, portiert werden können.

Anwendungen für StudiVZ Entwickeln

Gadgets spielen eine zentrale Rolle in der Anwendungsentwicklung für StudiVZ. Gadgets sind XML Dokumente die als Manifest für die Anwendungen fungieren. Im XML definiert man die API die verwendet wird, die Features die von der Plattform benötigt werden und die Views die verwendet werden. Die Inhalte sind ebenfalls in diesem XML definiert und bestehen in der Regel aus HTML, CSS und JavaScript. Durch die Definition der Inhalte für einen View lassen sich unterschiedliche Darstellungen realisieren. Zum Beispiel kann ein Gadget sich auf der Profil Seite anders darstellen als auf der Gruppenseite und auch so komplett andere Funktionalität mitbringen.

Ein praktisches Beispiel

Im folgenden werde ich eine Web Anwendung schreiben und diese mittels eines Gadgets in die StudiVZ Plattform integrieren. Als Tool verwenden wir WebMatrix, eine kostenlose komplette Entwicklungsumgebung mit Editor, Webserver und Datenbank. Das ganze lässt sich elegant über den Web Plattform Installer auf dem Entwickler Rechner installieren und man kann loslegen.

Link: Installation von WebMatrix durch den Web Platform Installer

Neben PHP unterstützt WebMatrix ASP.NET Web Pages welche ich zur Erstellung der Seite wähle. Die Idee für das Szenario ist fiktiv und einfach, zeigt aber grundsätzlich alle wichtigen Konzepte.

Die Anwendung soll eine Petitionsliste für die Erhaltung des Internets darstellen. Die letzten 5 Unterschriften werden angezeigt und man kann sich direkt in die Liste eintragen. Wenn man sich Einträgt wird automatisch an die StudiVZ Pinnwand eine Nachricht erstellt mit dem Wortlaut “{name} hat sich in die Petition zum Erhalt des Internets unterschrieben!”

Die Schritte zur StudiVZ Petitions App

Die folgenden Schritte sind Notwendig um die Anwendung zu realisieren:

  1. Beantragung eines Developer Accounts bei StudiVZ
  2. Erstellen der Petitionslisten Web Anwendung
  3. Publizieren der Anwendung bei einem Hoster
  4. Erstellen des Gadgets
  5. Hochladen des Gadgets und Testen

Beantragung eines Developer Accounts bei StudiVZ

Um einen Entwickleraccount zu beantragen muss man natürlich bei StudiVZ registriert sein. Genauer gesagt langt es wenn man in einem der VZ Netzwerke registriert ist. Ich habe mich bei MeinVZ.net registriert und dort dann auf der Seite http://www.meinvz.net/developer einen Antrag gestellt.

Wer sich jetzt frägt wer Zsuirad ist der mag doch einfach das Wort Rückwärts lesen. Eigentlich hätte ich keinen Alter Ego Account anlegen müssen, die Developer Sandbox bietet bereits eine Reihe an Accounts die man zum Testen der App benutzen kann. Praktisch. Der Link führt einen zu einem weiteren Fragebogen, ausfüllen und warten bis man eine Bestätigung bekommt (Dieser Schritt kann auch mal 1 oder 2 Tage dauern).

Erstellen der Petitions Anwendung

Die Petitions Anwendung erstellen wir in WebMatrix. Dazu wähle ich aus den Projekt-Templates entsprechend das Empty Site Projekt und lege eine neue Datei mit dem Namen Petition.cshtml an.

Danach wechsel ich in den Database Workspace und lege eine neue Datenbank an und erstelle dort die Tabelle Signed. Die Tabelle enthält eine automatisch generierte Id, den Namen und das Datum der Signatur.

Der Grundstein ist gelegt. Nun kann die Anwendung mit Leben sprich Code gefüllt werden.

   1: @{
   2:     var db = Database.Open("Petition");
   3:     
   4:     if( IsPost )
   5:     {
   6:         var errors = false;
   7:         var signature = Request["name"];
   8:  
   9:         if( signature.IsEmpty() )
  10:         {
  11:             errors = true;
  12:             @:Willst Du unterschreiben, dann trage Deinen Namen ein!<br/>
  13:         }
  14:         
  15:         if( errors == false )
  16:         {
  17:             var insert = "INSERT INTO Signed (Name, DateAndTime) 
  18:                             VALUES (@0, @1)";
  19:             db.Execute( insert, signature, DateTime.Now);
  20:         }
  21:     }
  22:     
  23:     var people = db.Query( "SELECT TOP(5) * FROM Signed 
  24:                                 ORDER BY DateAndTime DESC");
  25:     var totalPeopleSigned = db.QueryValue( "SELECT COUNT(*) FROM Signed" );
  26: }
  27:  
  28:  
  29: <!DOCTYPE html>
  30:  
  31: <html lang="en">
  32:     <head>
  33:         <meta charset="utf-8" />
  34:         <title>Petition</title>
  35:     </head>
  36:     <body>
  37:         
  38:         <h1>Petition zur Erhaltung des Internets</h1>
  39:         
  40:         <h2>Zuletzt unterschrieben von</h2>
  41:         
  42:         <ul>
  43:         @foreach( var person in people ) {
  44:             <li>@person.Name am @person.DateAndTime</li>
  45:         }
  46:         </ul>
  47:         
  48:         <h2>@totalPeopleSigned Menschen haben diese Petition unterschrieben</h2>
  49:         
  50:         <div id='petitionform'>
  51:             <form method="POST">
  52:                 <fieldset>
  53:                     <h4>Unterschreibe diese Petition</h4>
  54:                     <label for="Name">Name: </label>
  55:                     <input type="text" name="Name" />
  56:                     <input type="submit" value="Signed"/>
  57:                 </fieldset>
  58:             </form>
  59:         </div>
  60:     </body>
  61: </html>

Das @ Zeichen deklariert einen Razor Code Block. Razor ist die Syntax der View Engine die für ASP.NET Web Pages benötigt wird. Die Zeilen 1 – 26 greifen auf die Datenbank zu und prüfen ob es sich um einen Postback der Seite handelt. Falls ja, wird ein neuer Datensatz in die Datenbank eingetragen.

In der Zeile 43 – 46 sieht man die dynamische Erstellung der Personen die bereits die Petition unterschrieben haben. Zum Schluß folgt noch die Form die den Postback auslösen kann.

Publizieren der Web Anwendung

Damit die Web Anwendung aus einem StudiVZ Gadget genutzt werden kann, muss ich diese erst noch bei einem Hoster veröffentlichen. WebMatrix bietet hierfür eine Publish Schaltfläche, die automatisch auch noch Provider anbietet die ASP.NET Web Pages hosten können.

Nach dem Eintragen meiner Publishing Credentials publiziere ich die Anwendung mittels Web Deploy auf den Server.

Die App ist nun publiziert und unter der URL http://20313wdbv4.adhostbeta.com/studivz/petition.cshtml erreichbar.

Erstellen des Gadgets

Die Anwendung muss nun in ein Gadget gepackt werden. Hierfür gibt es entsprechende XML Schema Definitionen die auf dem Developer Wiki von StudiVZ zu finden sind. Das Gadget soll im Canvas View einfach die Anwendung kapseln und darstellen. Das ist leicht bewerkstelligt und sieht als Gadget folgendermaßen aus:

    1: <?xml version="1.0" encoding="UTF-8" ?>
   2: <Module>
   3:     <ModulePrefs title="Petition Gadget">
   4:         <Require feature="opensocial-0.9" />
   5:         <Require feature="minimessage"/>
   6:         <Require feature="views"/>
   7:         <AllowedDomain name="20313wdbv4.adhostbeta.com"/>
   8:     </ModulePrefs>
   9:     <Content view="canvas" type="url" href="http://20313wdbv4.adhostbeta.com/studivz/petition.cshtml">
  10:     </Content>
  11: </Module>

Doch bevor wir das Gadget testen wollen wir noch die Funktionalität erweitern. Das einbinden der externen Webseite im Canvas bringt zwar ein schnelles Resultat doch hat man hier nichts weiter als die Seite eingebunden und keinerlei Integration in die StudiVZ Plattform getätigt.

Den Canvas View lasse ich erstmal so. Ich erweitere das Gadget um einen Content Bereich für die Views Profile und Group. In diesem View soll sich das Gadget entsprechend in die Seite integrieren. Beachten muss man lediglich das dass Gadget mit den Maßen 390 x 400px angezeigt wird, Content darüber wird abgeschnitten. Unsere Seite eignet sich nicht direkt für die Profile und Group Views, da das generierte HTML mit der Form zusammen größer ist.

Auch die Integration mit der Möglichkeit an die Pinnwand zu schreiben muss in die Signierung der Petition integriert werden. Das erfordert ein “Refactoring” der eigentlichen Anwendung. Ich füge zur Anwendung zwei URL Endpunkte hinzu. Eine die die letzten Petitionen anzeigt und eine die als POST Endpunkt dient um neue Unterschriften hinzuzufügen.

Security über OAuth

Die Authorisierung zwischen Gadget und Web Anwendung erfolgt über OAuth, einem Standard der es erlaubt Anwendungen untereinander zu vertrauen und entsprechend Zugriffe zu gewähren. Im Gadget werde ich die Signatur Funktion von OAuth nutzen, in der Web Anwendung verzichte ich auf die Prüfung, diese sollte natürlich erfolgen damit nicht jeder x-beliebige Post einer beliebigen Seite angenommen wird. Es gibt zahlreiche OAuth Tutorials auf dem Developer Wiki, so dass diese Übung dem Leser überlassen bleibt.

Damit habe ich nun zwei weitere Endpunkte:

ListPetition.cshtml

    1: @{
   2:     var db = Database.Open("Petition");
   3:     
   4:     var people = db.Query( "SELECT TOP(5) * FROM Signed ORDER BY DateAndTime DESC");
   5:     var totalPeopleSigned = db.QueryValue( "SELECT COUNT(*) FROM Signed" );
   6: }
   7:  
   8:  
   9:         <h1>Petition zur Erhaltung des Internets</h1>
  10:         
  11:         <h2>Zuletzt unterschrieben von</h2>
  12:         
  13:         <ul>
  14:         @foreach( var person in people ) {
  15:             <li>@person.Name am @person.DateAndTime</li>
  16:         }
  17:         </ul>
  18:         
  19:         <h2>@totalPeopleSigned Menschen haben diese Petition unterschrieben</h2>
  20:

und SignPetition.cshtml

    1: @{
   2:     var db = Database.Open("Petition");
   3:     
   4:     if( IsPost )
   5:     {
   6:         var errors = false;
   7:         var signature = Request["name"];
   8:  
   9:         if( signature.IsEmpty() )
  10:         {
  11:             errors = true;
  12:             @:Es fehlt die Unterschrift!<br/>
  13:         }
  14:         
  15:         if( errors == false )
  16:         {
  17:             var insert = "INSERT INTO Signed (Name, DateAndTime) VALUES (@0, @1)";
  18:             db.Execute( insert, signature, DateTime.Now);
  19:             @:Danke f�r Deine Unterschrift!<br/>
  20:         }
  21:     }
  22:     else
  23:     {
  24:         Response.Redirect("~/Petition.cshtml");
  25:     }
  26: }

Wie schon gesagt, im richtigen Anwendungsfall sollte letztere auf jeden Fall die OAuth Signatur prüfen.

Da wir nun die Endpunkte haben können wir auch das Gadget um den Content Bereich für Profile und Group erweitern.

    1: <?xml version="1.0" encoding="UTF-8" ?>
   2: <Module>
   3:     <ModulePrefs title="Petition Gadget">
   4:         <Require feature="opensocial-0.9" />
   5:         <Require feature="minimessage"/>
   6:         <Require feature="views"/>
   7:         <AllowedDomain name="20313wdbv4.adhostbeta.com"/>
   8:     </ModulePrefs>
   9:     <Content view="profile,group" type="html">
  10:         <![CDATA[
  11:  
  12:             <script type="text/javascript">
   1:  
   2:             
   3:                 gadgets.util.registerOnLoadHandler( initializeApplication );
   4:     
   5:                 function initializeApplication() {
   6:                     showAppVersionMessage();
   7:                     retrievePeopleSignedPetition();
   8:                 }
   9:                 
  10:                 function showAppVersionMessage() {
  11:                     var msg = new gadgets.MiniMessage( '__MODULE_ID__');
  12:                     var statusMsg = msg.createDismissibleMessage("Petition Demo 
  13:                                                             Version 1.2");
  14:                     statusMsg.style.backgroundColor = "grey";
  15:                     statusMsg.style.color = "white";
  16:                 }
  17:                 
  18:                 function retrievePeopleSignedPetition() {
  19:                     var url = 
  20: "http://20313wdbv4.adhostbeta.com/studivz/listpetition.cshtml";
  21:                     var params = {};
  22:                     params[ gadgets.io.RequestParameters.AUTHORIZATION ] = 
  23: gadgets.io.AuthorizationType.SIGNED;
  24:                     gadgets.io.makeRequest( url, 
  25:                                 onRetrievePeopleSignedPetition, params );
  26:                 }
  27:                 
  28:                 function onRetrievePeopleSignedPetition( response ) {
  29:                     document.getElementById('peopleSigned').innerHTML = 
  30:                                                                 response.data;
  31:                 }
  32:                 
  33:                 function signPetition() {
  34:                     var content = document.getElementById('message');
  35:                     postToPetition(content);
  36:                     postToBuschfunk(content);
  37:                 }
  38:                 
  39:                 function postToPetition(content) {
  40:                     
  41:                     var url = 
  42: "http://20313wdbv4.adhostbeta.com/studivz/signpetition.cshtml";
  43:                     
  44:                     var data = { name: content.value };
  45:                     
  46:                     var postdata = gadgets.io.encodeValues( data );
  47:                     
  48:                     var params = {};
  49:                     params[ gadgets.io.RequestParameters.METHOD ] = 
  50: gadgets.io.MethodType.POST;
  51:                     params[ gadgets.io.RequestParameters.POST_DATA ] = postdata;
  52:                     params[ gadgets.io.RequestParameters.AUTHORIZATION ] = 
  53: gadgets.io.AuthorizationType.SIGNED;
  54:                     gadgets.io.makeRequest( url, 
  55:                                 onRetrievePeopleSignedPetition, params );
  56:                 }
  57:                 
  58:                 function postToBuschfunk(content) {
  59:  
  60:                     var params = {};
  61:                     params[ opensocial.Message.Field.TITLE ] = 
  62:                                         'Petition zum Erhalt des Internets';
  63:                     params[ opensocial.Message.Field.TYPE ] = 
  64: opensocial.Message.Type.PUBLIC_MESSAGE;
  65:                     
  66:                     var message = opensocial.newMessage( content.value + 
  67:                             ' hat die Petition zum Erhalt des 
  68:                                     Internets unterschrieben!', params );
  69:                     var recipient = "VIEWER";
  70:                     
  71:                     opensocial.requestSendMessage(recipient, 
  72:                                         message, onSendMessageComplete);
  73:                 }
  74:                 
  75:                 function onSendMessageComplete( data ) {
  76:                     if( data.hadError() ) {
  77:                         alert( "Es gab ein problem: " + data.getErrorCode() );
  78:                     }
  79:                 }
  80:                 
  81:             
</script>
  13:             
  14:             <div id='main'>
  15:                 <div id='peopleSigned'></div>
  16:                 <div id='content'>
  17:                     Unterschreibe auch Du!
  18:                     <input type='text' id='message' />
  19:                     <a href='javascript:void(0);' onclick='signPetition();'>Unterschreiben</a>
  20:                 </div>
  21:             </div>
  22:         ]]>
  23:     </Content>
  24:     <Content view="canvas" type="url" href="http://20313wdbv4.adhostbeta.com/studivz/petition.cshtml">
  25:     </Content>
  26: </Module>

Eine kurze Erklärung der Funktionen. In Zeile 3 (JavaScript) registriere ich eine Funktion die beim Laden des Gadgets angesprungen wird. Die Funktion ruft showAppVersionMessage(); auf, welche über eine Mini Message einfach die aktuelle Versionsnummer des Gadgets anzeigt und dann schließlich die Funktion retrievePeopleSignedPetition();. Diese Funktion ruft letztlich den listpetition Endpunkt auf und erhält entsprechend ein Stück HTML zurück das in den aktuellen Gadget Bereich übergeben wird.

Weiter unten ab Zeile 13 (HTML) ist dann ein Anchor Tag angegeben welches die Funktion signPetition(); aufruft. Diese Funktion schreibt nun über den signPetition Endpunkt einen neuen Datensatz in die Petitions-Datenbank, zum anderen wird postToBuschfunk(); aufgerufen, welche eine Nachricht an die Pinnwand schreibt.

Das ist schon die komplette Funktionalität des Gadgets.

Hochladen des Gadgets und Testen

Um das Gadget zu testen muss man es in ein gleichnamiges ZIP packen. Das Gadget heißt PetitionGadget.xml und die Zip-Datei heißt demzufolge PetitionGadget.zip. Zum Testen nimmt man nun die Developer Sandbox von *VZ her und lädt das Gadget enstprechend hoch.

Ist das Gadget erfolgreich hochgeladen, so kann man sich in der Vorschau die Funktionalität des Gadgets anschauen. Zuerst einen Blick auf den Canvas View:

Dort wird die Web Anwendung 1:1, wie unter der ursprünglichen URL, integriert angezeigt. Schaltet man nun auf den Profile View erhält man das Mashup von dem HTML das im Gadget enthalten ist und dem Resultat des listpetition Endpunktes.

Gut zu sehen, die Mini Message mit der Versionsnummer und die letzten 5 Petitionsunterschriften. Möchte man nun die Petition unterschreiben, so einfach den Namen eintragen und auf Unterschreiben klicken. Sofort kommt die Meldung ob man das Gadget auf die Pinnwand posten lassen möchte:

Bestätigt man mit senden, so sieht man das Resultat auch in der Pinnwand:

Fazit

Dieses einfache Beispiel hat gezeigt wie man eine bestehende Web Anwendung in StudiVZ mittels Gadgets und der OpenSocial API integrieren kann. Die Interaktion mit der OpenSocial API belief sich hierbei nur auf reinem JavaScript, es gibt sowohl noch die Möglichkeit über RPC und REST die API aus eigenen Web Anwendungen zu benutzen. Ich habe viele Bereiche nicht beschrieben die für eine richtige Produktiv-App wichtig wären, wie z.B. ein Melden Button für Custom Generated Content oder auch zusätzliche Informationen die zur Installation des Gadgets beigesteuert werden sollten. Komplett außen vorgelassen wurde das Thema OAuth Authentifizierung und Authorisierung. Das Thema ist umfangreich und mit Sicherheit einen eigenen Blogpost Wert und auf dem Developer Wiki findet man weitere Informationen zu diesem Thema. Das Gadget ist hier voll Funktionsfähig im Post enthalten und die Web Anwendung existiert noch bis mindestens Ende des Kalenderjahres 2010 unter dieser URL http://20313wdbv4.adhostbeta.com/studivz/petition.cshtml.

Autor: Dariusz Parys, Technical Strategist Web Platform, Microsoft Deutschland GmbH

Dariusz Parys ist seit 2007 als Technical Strategist Web Platform bei der D&PE und seit 2000 bei Microsoft Deutschland tätig. Sein Themenschwerpunkt liegt auf der Microsoft Web Platform und verwandten Technologien. Davor war Dariusz zwei Jahre lang bei einem Großkonzern als Enterprise Architect für Microsoft Consulting Services tätig. Sein Wissen und seine Erfahrung vermittelt er in Vorträgen auf zahlreichen Entwicklerkonferenzen und Workshops. Sie erreichen ihn über seinen Blog unter http://downtocode.net und über Twitter @writeline.

This entry was posted in Uncategorized by admin. Bookmark the permalink.

3 thoughts on “OpenSocial Apps entwickeln mit ASP.NET (Autor: Dariusz Parys, Microsoft Deutschland GmbH)

  1. I for all time emailed this web site post page to all my associates, for the reason that if like to read it next my friends
    will too.

    Here is my web site … Alex

  2. I read a lot of interesting posts here. Probably you spend a lot of time writing,
    i know how to save you a lot of work, there is an online tool that creates unique, SEO friendly articles in minutes, just search in google –
    laranitas free content source

Leave a Reply

Your email address will not be published. Required fields are marked *


*