CoffeeBreak – Ein kleines Fazit

Angefangen hat es mit der Lektüre von Inside Microsoft SharePoint 2013 – insgesamt eine recht gute Übersicht mit auch einigen Vertiefungen und dass mein Interesse am Ende etwas nachgelassen hat liegt vermutlich an den Themen. Es beantwortet sicher nicht alle Fragen, macht aber Lust auf mehr. Da das Thema SharePoint AddIn für mich neu war habe ich mir überlegt, mir mal die Entwicklung eines solchen AddIns an einem (Pseudo-) praktischen Beispiel anzuschauen. Natürlich wollte ich auch noch mal einige Themen wie Listen, Felder, Content Types etc. auffrischen – ja, es gibt seit WSS 3.0 Neues, aber wirklich anders ist es ja nicht: selbst die Art der SQL Datenbankablage ähnelt noch der Urform.

Diese Fokussierung ist auch einer der Gründe warum die folgenden Aussagen mit Vorsicht zu genießen sind, da sie auf gefährlichem Halbwissen basieren. Ich denke zwar, dass ich vielleicht das eine oder andere noch vertiefen werden (Join und GroupBy vor allem), aber im Grund ist mein selbst gesetztes (Zeit-)Budget für die Evaluation erschöpft. Schauen wir mal.

Am Anfang habe ich sehr viel die Visual Studio Assistenten zum Anlegen von Listen, Feldern und Content Types verwendet. Allerdings fand ich immer wieder Aufgaben, die dann doch nur in der XML erledigt werden konnten und hatte Änderungen in der XML vorgenommen, die der Assistent dann beim nächsten Speichern stillschweigend wieder entfernte. Die zweite Liste wurde dann sogar in ein zweites Feature eingefügt, was mich dann eine Zeit beschäftigt hat bis ich herausgefunden habe, dass deswegen ein Lookup Feld nicht funktionierte. Erstes Fazit daher: CAML lernen und direkt die XML Datei pflegen – tatsächlich nimmt der Assistent nicht wirklich viel Arbeit ab (Mindestens allerdings diese Ausnahme: alle Felder eines existierenden Content Types zur Liste hinzufügen).

Die Liste mit den Arten der Kaffeesorten sollte den Titel eigentlich als eindeutigen Schlüssel haben – im Client wird das zwar beim Anlegen geprüft, aber das passiert nur im Client Code und ist nicht Multi-User-sicher. Auch wenn das wohl inzwischen bei SharePoint Out-Of-The-Box geht habe ich darauf erst einmal verzichtet – ein Punkt den ich mir noch einmal anschauen muss: geht das auch auf dem vordefinierten Feld Title, kann man die Fehlermeldung beim Speichern auch über JSOM eindeutig identifizieren, etc.

Auch mein Lookup Feld (eine Spende referenziert genau eine Art von Kaffee) ist etwas halbherzig. Zwar unterstützt die kleine Anwendung selbst weder Löschen noch Ändern von Spenden und Arten, aber über den Direktaufruf der Listen (Lists/CoffeeTypes und Lists/Donations) geht das dann doch – ich habe glücklicherweise noch nicht herausgefunden, wie man den externen Zugriff dieser URLs gänzlich sperrt. Und das Löschen einer Kaffeesorte hinterlässt Spenden mit offenen Referenzen – laut Dokumentation soll dies aber konfigurierbar sein, daher bin ich dem nicht weiter nachgegangen. Das ist aber auch nur eine kleine Spitze eines Eisbergs: SharePoint scheint es grundsätzlich egal zu sein, ob ein Feld Required (TRUE) ist: speichern kann man irgendwie immer. Offenbar nur ein Hinweis für Formulare?

Eigentlich wollte ich das Lookup gar nicht sondern mal schauen, wie man ein Join zwischen zwei Listen in einer CAML Suche formuliert und auswertet. In der Dokumentation ist das ziemlich klar aber leider war die Zeit am Ende – vielleicht später einmal. Lookup Felder sind aber durchaus handlich, daher habe ich hier auch nicht mehr verstärkt gesucht.

Interessant war auch mein Versuch eine CAML Suche auf eine Liste Gruppieren zu lassen. Tatsächlich ist mit das nicht wirklich gelungen, herausgekommen ist nur so eine Art Sortieren: Elemente mit gleichem Wert stehen zusammen. Der Dokumentation nach geht ein echtes Gruppieren (mit Aggregation, in diesem Fall bräuchte ich ein Count() und ein Sum()) nicht mit reinen CAML Suchen sondern nur über Listen. Das kann ich mir noch nicht wirklich vorstellen, hier muss ich sicher noch einmal nachhaken. Wenn dem so ist, wäre das übel, wie man an der implementierten Lösung sieht: der Client liest alle Elemente und gruppiert selbst! Mit wachsender Anzahl von Elementen ein potentielles Performance Problem und ich würde so etwas niemals produktiv freigeben.

Die Gruppierung selbst habe ich über ein berechnetes Feld gemacht, das wiederum sehr einfach einzurichten war. Die Dokumentation der Formelsprache ist aber recht dürftig – zumindest bei Microsoft, oder ich habe mal wieder falsch gesucht. Um die App überhaupt mit einer Gruppierung nach Zeit testen zu können wird hier eine Granularität nach Minuten verwendet – realistisch wäre wohl eher nach Tag, das kann man mit der aktuellen Implementierung einfach durch Umkonfiguration des Feldes erreichen.

Nimmt man nun noch das Problem hinzu, dass SharePoint-Hosted AddIns bei der Deinstallation die Daten in den privaten Listen verlieren, dann bin ich mir nicht ganz sicher, ob das von mir überlegte Beispiel tatsächlich realistisch ist. Im Moment würde ich diese Technologie für Apps nutzen, die auf bestehenden Daten (Listen auf Site Ebene oder höher, die in das App Web hinein sichtbar sind) Zusatznutzen anbieten. Ansonsten reicht eine App evtl. alleine nicht aus. Auf der positiven Seite ist allerdings ganz klar zu sagen: mit den für andere HTML5/JavaScript verwendeten Techniken und Visual Studio lassen sich auch SharePoint Apps prima entwickeln, ohne sich auf das nackte CSS und JavaScript beschränken zu müssen.

Puh, reicht erst mal.

Aber vielleicht reicht dem einen oder anderen das wirre Zeugs hier für einen eigenen schnellen Einstieg in eine Evaluation!

Jochen

CoffeeBreak – Über die Entwicklungsumgebung

Entwickelt man heutzutage HTML5 / JavaScript Anwendungen dann ist man (irgendwie jeder für sich) an eine gewisse Entwicklungsumgebung gewohnt. Nach dem Erstellen des SharePoint AddIn Projektes in Visual Studio 2015 (Update 3) fehlte mir doch einiges zur Comfort Zone, das ich mir dann entsprechend eingerichtet habe.

Natürlich ist da erst einmal TypeScript – als Ergänzung zu JavaScript. Vielleicht habe ich da nicht richtig gesucht, aber Microsoft direkt scheint da nichts anzubieten. Ich habe daher im Projekt nur die Definitely Typed Definitionen verwendet. Zwar gibt es doch so einige Anwender mit TypeScript Bibliotheken zum Zugriff auf SharePoint, aber ich habe das Ganze hier minimalistisch gehalten und das Notwendigste selbst implementiert – vielleicht ein Ausgangspunkt für eine Bibliothek, vielleicht aber auch nur Ideen, die anderswo schon so umgesetzt sind und die ich einfach nur nicht gefunden habe. Auch der Start der Anwendung erfolgt natürlich in einer TypeScript Klasse – mit einem kleinen Tweak für den Unterschied zwischen Stand-Alone Betrieb und Integration als Client Web App.

Aus den einzelnen TypeScript Dateien wird eine einzige JavaScript Datei erstellt, die dann im Package der App landet – für alle TypeScript Dateien habe ich den Deployment Type auf NoDeployment gesetzt, da die nichts auf dem produktiven System zu suchen haben.

Zur Pflege der CSS Dateien verwende ich im Allgemeinen SASS, hier im Projekt via NodeJS und Gulp eingerichtet – will man das Projekt übersetzen, muss einmalig ein NPM UPDATE machen, ich habe darauf verzichtet das Modulverzeichnis auf GitHub hochzuladen. Tatsächlich war das hier ein absoluter Nebenschauplatz und auf Styling habe ich weitestgehend verzichtet – die SASS Datei ist minimal und da ist sicher eine Menge Luft nach oben. Kritisch ist vor allem, dass ich die SharePoint Umgebung weitestgehend ignoriere (die ASPX des Client Web Parts wurde entsprechend reduziert und referenziert nicht das Styling der Seite) darum sieht die Anwendung doch etwas eigenartig aus – naja, die Alternative wäre die Einarbeitung in die SharePoint Konventionen, was ich mir hier erst einmal ersparen wollte.

Die Anwendung ist als Single-Page-Application (SPA) angelegt, ich habe auf ein explizites Binding Framework wie AngularJS verzichtet und die paar Bindungen explizit (und meiner Ansicht nach auch klarer als die $watch-Magie von AngularJS 1.5) vorgenommen. Als externe JavaScript Bibliotheken sind lediglich (die heute 🙂 gerade) aktuelle Versionen von jQuery und jQueryUI über das in Visual Studio integrierten NuGet eingebunden – auch diese Pakete sind nicht auf GitHub und vor dem eigenen Übersetzen des Projektes muss einmalig ein Restore aus Visual Studio heraus ausgeführt werden. Die Programmierung gegen diese Bibliotheken erfolgt natürlich über die Definitely Typed Definitionen aus TypeScript heraus.

Mit diesen kleinen Vorbereitungen lässt sich das SharePoint-Hosted AddIn fast wie ein normales HTML5 / JavaScript Projekt entwickeln und auch gegen eine virtuelle Maschine (Windows Server 2012 R2 – etwas tricky in der Einrichtung der SharePoint Foundation 2013 aber zumindest alles wesentliche bekommt man ans Laufen) debuggen – sowohl Stand-Alone als auch als Client Web Part.

Die Struktur der Anwendung entspricht so ganz grob einem MVC Ansatz, richtig sauber war ich da aber nicht:

  • Zur Anzeige wird ein Controller und ein passender View erzeugt
  • Der Controller erstellt und verwaltet das Modell
  • Die Kommunikation des Controllers mit seinem Umfeld erfolgt ansonsten über eine Präsentationsschnittstelle
  • Aus Faulheit wird diese aber direkt vom View implementiert
  • Der View bindet sich geeignet an die HTML Element der Oberfläche
  • Für jeden View gibt es im Projekt eine HTML Datei, die bei Aktivieren des Views ins DOM geladen wird

Das muss erst mal reichen, weitere Details im Selbststudium…

Nun, der nächste Post der Reihe sollte sich dann auch mal wirklich um die Ziele der Evaluation kümmern – mit einem kleinen Fazit, das aber wie schon im vorherigen Post angedeutet durch unvollständige Informationen / Recherchen meinerseits verfälscht sein wird.

Jochen

Mal wieder was Neues – CoffeeBreak

Nach langer Zeit habe ich mich entschieden, mal wieder einen Blick in Microsofts SharePoint zu werfen – konkret in die SharePoint Foundation 2013, auch leicht angestaubt aber besser als mein letzter Ausflug mit den Windows SharePoint Services 3.0. Tatsächlich habe ich mir dabei nur einen Aspekt herausgegriffen und ich vermute einmal, dass ich daher noch eine Menge Fehlinformationen habe und Dinge vermutlich einfacher oder überhaupt gehen: also erst mal alles in diesem und den nächsten Posts (ich habe das thematisch aufgeteilt, damit die Posts nicht zu lang werden) als Information eines Laien nehmen und nicht allzu ernst nehmen – auch wenn ich mir durchaus Mühe gegeben habe, das Richtige zu tun.

Konkret wollte ich mir anschauen, wie man ein SharePoint-Hosted AddIn (formerly known as Web App) mit der aktuellen Visual Studio 2015 Version (Update 3), TypeScript, SASS et al entwickeln kann. Entstanden ist eine kleine, in diesem Zustand nicht wirklich nützliche Anwendung namens CoffeeBreak, mit der Kaffeespenden im Büro [hm, ich denke das Prinzip kennen so einige] verwaltet werden können und die auch eine Übersicht über die Zeit gibt – der Quellcode dazu ist natürlich auch öffentlich verfügbar, Verwendung und Interpretation der Vorgehensweise wie immer auf eigene Gefahr. Der wesentliche Nachteil der SharePoint-Hosted App ist es, dass mit der Deinstallation auch immer alle Daten verloren gehen, aber darum ging es mir hier auch nicht: ich denke mal, dass man fast alles aus dieser konkreten App auch direkt mit SharePoint Bordmitteln umsetzen kann!

In diesem ersten Post nur ein paar Screen-Shots, weitere Details folgen wie gesagt separat. Zuerst einmal die Startansicht – die Anwendung läuft Stand-Alone oder auch als Client Web Part in einer SharePoint Seite:
Startansicht

Das Eintragen einer neuen Spende:
Spende anlegen

Und darüber auch das Anlegen neuer Kaffeesorten – nach der Installation gibt es davon keine:
Sorte anlegen

Soweit zur Übersicht, die anderen Posts beschäftigen sich mit der Entwicklungsumgebung und den Zielen sowie einem kleinen Fazit

Jochen

Optionale Parameter in Methoden von TypeScript Schnittstellen

Wie immer: wenn man nachher darüber nachdenkt ist alles klar, aber manchmal ist man dann einen Moment lang doch überrascht. Nehmen wir einmal folgende TypeScript Schnittstelle:

interface ISample {
do(name?: string): void;
}

Die Methode do kann nun mit oder ohne Parameter aufgerufen werden:

extra(test: ISample): void {
test.do();
test.do(undefined);
test.do('ho');
}

Um in der Implementierung festzustellen ob ein Parameter übergeben wurde verwendet man im Allgemeinen einen Vergleich gegen undefined (oder alternativ void 0) – tatsächlich müsste man arguments.length zu Rate ziehen, um die ersten beiden Varianten sicher unterscheiden zu können. Das kann TypeScript einem aber auch abnehmen:

do(name: string = 'default'): void {
}

Genau dieser Vergleich auf undefined wird hier (ohne Rücksicht auf arguments.length, i.e. die beiden ersten Aufrufvarianten werden gleich behandelt) durchgeführt und der Parameter entsprechend belegt.

Alles das war mir im Einzelnen schon klar. Schön ist aber bei genauer Betrachtung, dass im Gegensatz zu Default Werten für Parametern in C# et al nicht der Aufrufer sondern die Implementierung entscheidet, was für ein Default verwendet werden soll. In meinem konkreten Anwendungsfall gibt es dann tatsächlich unterschiedliche Implementierungen der Schnittstelle mit unterschiedlichen Bedürfnissen, wo sich dieses Verhalten dann als sehr praktisch erwiesen hat.

Netter Seiteneffekt

Jochen

VCR.NET 4.3.47: kleinere Fixes und eine Erweiterung

Im täglichen Betrieb habe ich doch einige kleinere Probleme festgestellt, die mich genervt haben und die hiermit behoben sind:

  • Wenn man während einer laufenden Aufgabe (Programmzeitschrift oder Sendersuchlauf) oder Aufzeichnung eine neue Aufzeichnung so anlegt, dass sie eigentlich direkt beginnen müsste, dann zeigte der Aufzeichnungsplan völlig wirres Zeug an: Aufzeichnungen Tage später können angeblich nicht mehr ausgeführt werden und ähnliches.
  • Zu einer Aufzeichnung wird immer auch ein Auftrag angelegt. Die Möglichkeit, weitere Aufzeichnungen zu einem Auftrag hinzuzufügen wird selten verwendet – außer wohl von mir selbst 🙂 Wie dem auch sei: wenn man bei einer weiteren Aufzeichnung eine andere Quelle (Sender) einträgt und dann die Quelle des Auftrags entfernt, so wurde der Aufzeichnungsplan nicht mehr angezeigt – im Prinzip weil der ersten Aufzeichnung nun gar keine Quelle mehr zugeordnet ist.
  • Einige Sender wie E4 (UK) senden von Zeit zu Zeit sehr viel seltener die Sendereckdaten (PAT) als andere. Unabhängig von der konkreten Einstellung des Schlechtwetterschutzes erwartete der VCR.NET Recording Service, dass ein Sender sich spätestens alle 5 Sekunden meldet – üblich sind 2 bis 3 Sekunden. Erfolgt diese Meldung nicht, so wird die Aufzeichnung automatisch unterbrochen und dann später neu gestartet – sehr nützlich etwa bei der Lokalzeit des WDR. Leider hat E4 Phasen mit 9 und mehr Sekunden, was zu unnötigen Unterbrechungen der Aufzeichnung führte. Ich habe daher diese Grundzeit auf 15 Sekunden erhöht, das wäre dann auch die Reaktionszeit des Schlechtwetterschutzes – i.e. Werte unter 15 sind ab sofort sinnlos.

Zumindest für mich viel wichtiger ist aber eine Erweiterung im EasyCut. Ich nehme sehr viel englische Sender auf und versuche auch immer die Untertitel einzumischen. Wenn man wie ich dazu GUI for DVDAuthor (GfD) verwendet, so kann man nun nach dem Erstellen der Untertitelschnittdatei im SUP (SUB geht leider nicht, das habe ich mir aber eh schon lange abgewöhnt) direkt die Werkzeuge von GfD nutzen um eine Videodatei mit Bild, Ton und Untertitel zu erstellen. Das ist in der späteren Handhabung sehr viel einfacher als SUP und SUP.ISO bis zum Erstellen einer DVD mitzuschleppen.

Allerdings gibt es auch einige Wermutstropfen, die ich noch beobachten muss. Für mich passt es im Moment, aber warten wir mal ab:

  • GfD selbst passt die Originalfarben im Allgemeinen noch so an, dass die YCbCr Repräsentation aus dem Originalmaterial auch sicher auf RGB abgebildet werden kann. Das macht EasyCut nicht, bisher habe ich keine Unterschiede festestellen können.
  • Beim Einmischen der SUP in den geschnittenen Film meldet GfD im Normalbetrieb ab und an mal Fehler – zu kurze Untertitel, zu schnell aufeinanderfolgende Untertitel, überlappende Untertitel und so weiter. Diese Meldungen sollte EasyCut ignorieren – ich habe zumindest keine mehr gesehen.
  • Die zusammengemischte Datei wird direkt neben die Schnittdatei gelegt, der Dateiname erhält den Zusatz _SUP. Hier empfiehlt es sich dringend, dies nur auf schnellen Platten durchzuführen, da bei dem Vorgang eine große Datenmenge von der Platte gelesen und direkt wieder geschrieben wird – nun, ich nutze dafür eine SSD.

Die Installationspakete wurden an gewohnter Stelle und bei Heise aktualisiert.

Viel Spaß

Jochen