API Anleitung

Beispielprogramm in .NET

Als Beispiel für die einfachhe Handhabung betrachten wir den Zugriff mit C# auf die API mittels der .NET 3.5 Bibliothek. Das komplette Programm können Sie hier herunterladen.

Weiterführende Informationen zum Umgang mit OData-Schnittstellen, und zahlreiche weitere Codebeispiele in C# und VB finden Sie auch in der .NET Dokumentation.

Service-Referenz erstellen

Um auf die API zuzugreifen, muss man zunächst eine Datenservice-Referenz erstellen. Dies wird von Visual Studio durch ein paar Mausklicks und der Angabe der URI der LogMyTime API automatisch generiert. Die genaue Vorgehensweise hierzu ist in folgendem Artikel geschildert.

Nun kann eine Instanz einer solchen Api-Referenz erschaffen werden:

    var dataSource = new APIDataSource(new Uri("http://api.logmytime.de/V1/Api.svc"));
    //falls auf der Serverseite weitere Eigenschaften in den Ressourcen hinzukommen sollten,
    //wollen wir, dass die Servicereferenz trotzdem noch funktioniert. Hierzu muss man unter
    //.NET noch die Eigenschaft 'IgnoreMissingProperties' auf true setzen. 
    dataSource.IgnoreMissingProperties = true;
    
Achtung: In Visual Studio 2017 oder neueren Versionen können Service-Referenzen zwar noch compiliert werden, jedoch ist es damit nicht mehr möglich, auf die oben gezeigte Art Service-Referenzen zu erstellen oder zu aktualisieren. Microsoft empfiehlt stattdessen das kostenlose Visual Studio Add-In Odata Connected Service oder den ebenfalls kostenlosen Simple.Odata.Client zu verwenden. Beide funktionieren zuverlässig, das Visual Studio Add-In hat den Vorteil, dass man die clientseitigen klassen nicht selbst deklarieren muss, sondern diese ähnlich wie oben gezeigt automatisch generiert werden. Alternativ können Sie jedoch ebenso gut entweder unser Beispielprojekt als Ausgangspunkt für Ihr eigenes Projekt nehmen oder zum Erstellen der Referenz Visual Studio 2015 Community Edition verwenden.

Für die Authentifizierung per HTTP Header weisen wir die Api-Referenz an, bei jedem Request eine Funktion namens AttachAuthHeader aufzurufen:

dataSource.SendingRequest += AttachAuthHeader;

Die Funktion fügt zur Athentifizierung den API-Schlüssel des Mitarbeiters als HTTP Header an:

private static void AttachAuthHeader(object sender, SendingRequestEventArgs e)
{
e.RequestHeaders.Add(new NameValueCollection{{"X-LogMyTimeApiKey", DER_APISCHLUESSEL}});
}

Lesezugriff

Nun können wir mit dem eigentlichen Zugriff auf die API beginnen. Die Service-Referenz besitzt für jeden Ressourcentyp der LogMyTime API ein IQueryable-Objekt, aus dem diese Ressourcen ausgelesen werden können.

Nehmen wir an, auf dem Server wären 2 aktive Projekte namens 'Mondlandung' und 'Marsexpedition', sowie ein abgelegtes Projekt namens 'Kühlschrank abtauen'.

Beispiel: Um die Namen aller Projekte und deren Status aufzulisten:

foreach (var project in dataSource.Projects)
    {
       Console.WriteLine(project.Name+": "+project.Active?"Aktiv":"Abgelegt");
    }

Ausgabe:

Mondlandung: Aktiv
Marsexpedition: Aktiv
Kühlschrank abtauen: Abgelegt

Serverseitige Query Options

Es können auch serverseitige SQL-ahnliche Befehle (sogenannte Query String Options) beim Lesezugriff ausgeführt werden.

Beispiel: Anstatt aller Projekte sollen nur die aktiven Projekte vom LogMyTime-Server geladen werden. Die Projekte sollen auch gleich serverseitig alphabetisch sortieren werden. Dazu muss man das vorherige Beispiel wie folgt abändern:

foreach (var project in dataSource.Projects
		.AddQueryOption("$filter", "Active")
		.AddQueryOption("$orderby", "Name")
		)
	{
		Console.WriteLine(project.Name);
	}

Ausgabe:

Marsexpedition: Aktiv
Mondlandung: Aktiv

Eine Dokumentation aller Query String Options finden Sie auf der OData-Webseite.

Child-Referenzen

Die Service-Referenz unterstützt sogar Links der Ressourcen untereinander. Diese werden durch Eigenschaften in den Ressourcen-Stubs der Service-Referenz repräsentiert.

Beispielsweise sind bei LogMyTime der Projektname und die Tätigkeit keine unmittelbaren Eigenschaften einer Zeiteintrags-Ressource. Mit der Bibliothek kann man auf Projektname und Tätigkeit aber so zugreifen, als ob dies der Fall wäre. Man muss nur die Service-Referenz anweisen, die entsprechenden Child-Referenzen Project und Task beim Ladevorgang zu expandieren, also in dem gleichen Request mit zu laden.

Beispiel: Alle Zeiteinträge mit Projekt und Tätigkeit auflisten:

foreach (var timeEntry in dataSource.TimeEntries
	.Expand("Project")
	.Expand("Task"))
{
	Console.WriteLine("Von {0} bis {1}: {2} / {3}",
		timeEntry.StartTime,
		timeEntry.EndTime,
		timeEntry.Project.Name,
		timeEntry.Task!=null?timeEntry.Task.Description:null);
}

Ausgabe:

Von 27.07.2010 15:34:23 bis 27.07.2010 17:48:26: Marsexpedition / Recherche
Von 27.07.2010 12:31:30 bis 27.07.2010 14:06:31: Marsexpedition / Meeting
Von 27.07.2010 01:00:00 bis 27.07.2010 04:00:00: Mondlandung / Triebwerk B montieren
...

Schreibzugriff

Ressourcen erstellen

Der Schreibzugriff gestaltet sich ähnlich einfach. Für das Erstellen neuer Ressourcen muss der Ressourcen-Stub mit der AddTo{RessourceListenName}-Methode in die Service-Referenz eingefügt werden. Anschließend weist man die Service-Referenz an, die neue Ressource zum Server zu übertragen.

Beispiel: Ein neues aktives Projekt namens "Mondlandung" anlegen und dessen serverseitige ID ausgeben

Project newProject = new Project
                                   {
                                       Name = "Mondlandung",
                                       Active = true
                                   };
  //Das neue Projekt in die API Servicereferenz einfügen
  dataSource.AddToProjects(newProject);
  //Änderungen an Server absenden
  SubmitChanges(dataSource);
  //Das Stub erhält automatisch die serverseitige ID des neuen Projektes:
  Console.WriteLine("Das Projekt wurde angelegt. Die Projekt-ID lautet: "+newProject.ID);

Ressourcen ändern

Beim Ändern von Ressourcen muss man der Service-Referenz explizit mitteilen, dass die am Referenz-Stub gemachten Änderungen mit dem Server synchronisiert werden sollen.

Beispiel: Das Projekt namens "Mondlandung" in "Mondlandungsexpedition" umbenennen:

//Projekt laden...
var enumerator = dataSource.Projects
	.AddQueryOption("$filter", "Name eq 'Mondlandung'")
	.GetEnumerator();
enumerator.MoveNext();
Project project =enumerator.Current;
//umbenennen...
newProject.Name = "Mondlandungsexpedition";
//den Stub zum Synchronisieren auf den Server freigeben...
dataSource.UpdateObject(newProject);
//und zum Server übertragen
SubmitChanges(dataSource);

Ressourcen löschen

Das Löschen ist ist ähnlich einfach wie das Erstellen von Ressourcen.

Beispiel: Das Projekt Namens "Mondlandung" löschen:

//Projekt vom Server laden...
var enumerator = dataSource.Projects
	.AddQueryOption("$filter", "Name eq 'Mondlandung'")
	.GetEnumerator();
enumerator.MoveNext();
Project project =enumerator.Current;
//Service-Referenz anweisen, die Ressource beim nächsten Synchronisieren zu löschen
dataSource.DeleteObject(project);
//änderungen an den Server übertragen
SubmitChanges(dataSource);

ChangesDigest herunterladen

Die LogMyTime API bietet zusätzlich zu ressourcentabellen auch noch einige Service-Operationen, die z.B. die Synchronisation von Daten stark vereinfachen und das Steuern der Stoppuhr über die API ermöglichen. Als Beispiel wird im Beispielprogramm ein ChangesDigest-Objekt mit den Änderungen der letzten 24 Stunden heruntergeladen.

Beispiel: ChangesDigest herunterladen

    var uri = new Uri(String.Format("{0}/GetChangesDigest?LastSynchronizationTime={1}&IgnoreOtherUsersResources={2}",
                    dataSource.BaseUri,
                    referenceTime.ToString("s"),
                    ignoreOtherUsersTimeEntries
                ),
                UriKind.RelativeOrAbsolute);
    var changesDigest = dataSource.Execute<ChangesDigest>(uri).ToList().First();

.net Beispielprogramm

Die oben gezeigten Beispiele wurden als ein komplettes Programm implementiert. Dieses Projekt für Visual Studio 2010 oder höher enthält zusätzlich noch ein paar try / catch Blöcke zur Behandlung von Übertragungsfehlern sowie ein Beispiel zum Herunterladen eines ChangesDigest. Sie können es hier herunterladen.

Weiterführende Informationen

Weiterführende Informationen zum Umgang mit OData-Schnittstellen, und zahlreiche weitere Codebeispiele in C# und VB finden Sie auch in der .NET Dokumentation.