Blog

Mit dem Wissen wächst der Zweifel

Wedding coupleDer erste Schritt ist getan, denn ab sofort kann unser CRM/SharePoint-Integrator auch OneNote-Abschnitte und OneNote-Seiten erzeugen. Manchmal gehen Wünsche eben doch in Erfüllung, zumindest wenn es die Wünsche unserer Kunden sind.

Wie ist das möglich?

Beschäftigt man sich ein wenig mit der Materie, findet man die vor kurzem noch angekündigte OneNote-API. Jedoch kann diese API im aktuellen Status nur das OneNote-Notizbuch im eigenen OneDrive bearbeiten. Eine Bearbeitung eines im SharePoint liegenden Notizbuchs ist aktuell noch nicht möglich, aber immerhin bereits auf der Wunschliste.

Da aber auch wir nicht so lange warten wollen, haben wir analysiert, welche Alternativen es gibt. Erstaunlicherweise sind es sogar recht viele, die jedoch alle der Reihe nach aus Gründen der Performance oder Kompatibilität ausscheiden. Nur eine Alternative blieb, die Anfangs regelrecht gepflastert mit Stolpersteinen schien, die sich jedoch im Laufe der Zeit eher als Steighilfen erwiesen.

Wie habt ihr das gemacht?

Nun, allzu sehr möchten wir natürlich nicht ins Detail gehen. Soviel sei jedoch gesagt:
Wir nutzen für dieses Feature die Dienste der Office WebApps für SharePoint. Konkret simulieren wir dabei die Nutzung der OneNote WebApp in SharePoint. Das die entsprechende Implementierung natürlich recht komplex ist und viel Zeit in Anspruch nahm, sollte sich fast schon von selbst verstehen.

Wie schaut das Ganze nun aus?

Dazu haben wir wie üblich ein kleines Beispiel erstellt. In den folgenden Abbildungen haben wir eine Beispielkonfiguration für Sie vorbereitet. Zum besseren Verständnis der Möglichkeiten, zeigen wir Ihnen einen zweistufigen Aufbau.

1. OneNote-Abschnitt pro Firma

Mit dieser Konfiguration wird pro Firma ein OneNote-Abschnitt erstellt. Der Name des Abschnitts wird aus der Firmennummer und dem Firmenname zusammengesetzt, wodurch sich bspw. ein Abschnitt mit dem Name “1234 – Musterbau GmbH” ableitet. Dieser Abschnitt ist leer und erhält, wie in der Konfiguration angegeben, eine zufällige Farbe. Das Ergebnis könnte wie folgt aussehen.

2. OneNote-Seite pro Verkaufschance

Diese Konfiguration basiert auf der Annahme, dass bereits eine Konfiguration zur Erstellung von OneNote-Abschnitten pro Firma existiert, welche die ID des Abschnitts in das Feld “new_onenotesection_id” schreibt. Dieses Feld lesen wir in unserer Konfiguration zur Erstellung von OneNote-Seiten pro Verkaufschance wieder aus, wodurch die OneNote-Seite im vorher angelegten OneNote-Abschnitt erscheint. Das Ergebnis sollte dann wie folgt aussehen.

Fazit

Mit dem neuen Feature des CRM/SharePoint-Integrators zur Integration von OneNote, wird die komfortable Verwaltung von Notizen in OneNote mit der Struktur und Verwaltbarkeit des CRM gepaart. Eine Hochzeit ungleicher Produkte mit dem Ziel sich gegenseitig zu ergänzen. Was gibt es schöneres?

Autor: Dirk Sarodnick

Google+

201403_BLOG_SP_SketchflowBei der Projektplanung stößt man immer wieder auf die gleichen Probleme. Haben alle die Anforderungen verstanden? Weiß der Frontendentwickler, wie er die Anwendung zu strukturieren hat? Kann der Architekt mit den Informationen arbeiten? Hat der Designer bereits eine Idee? Ist der Benutzer mit der geplanten Bedienbarkeit zufrieden? Schlecht ist, wenn keine dieser Fragen mit “Ja” beantwortet werden kann. Noch schlechter ist es, wenn die Vorstellungen trotzdem weit auseinandergehen.
Doch mit SketchFlow muss das nicht sein!

Mit SketchFlow ist es möglich, alle Parteien grundlegend zu informieren und gleichzeitig interaktiv am Gestaltungsprozess teilhaben zu lassen. Es gibt einem die Möglichkeit mit einfachen Mitteln einen Prototypen erstellen zu können, dessen Optik nicht ablenkend wirkt. Ein Prototyp in Window Forms beispielsweise ist dem Designer zu hässlich, der Chef bekommt das Gefühl die Anwendung sei bereits weit fortgeschritten und der Benutzer bekommt eine falsche Vorstellung von der Bedienbarkeit, wenn es am Ende eigentlich um eine Webseite geht. Ein Prototyp in ASP.NET ist möglicherweise zu ein- oder unfarbig oder muss mit einem gewissen Aufwand erst optisch aufgewertet werden, obwohl die Struktur und das Design noch längst nicht feststehen. Alles Gründe, warum man Prototypen üblicherweise nur in eingeschränkten Fällen oder zumindest erst in späteren Planungsphasen verwendet. Vorher gibt es jedoch auch Klärungsbedarf zwischen den beteiligten Personen, bei denen verschiedene Hilfsmittel, wie Skizzen, Flipcharts oder gar wildes herumfuchteln mit den Händen eingesetzt werden. SketchFlow hingegen vereint die Macht dieser Hilfsmittel, wodurch man es bereits sehr früh in der Planungsphase einsetzen kann.

Was kann SketchFlow nun?

Im Prinzip ist SketchFlow ein interaktiv bedienbarer Flipchart. Es wird in Form eines Prototypen, mit klickbaren Knöpfe, ausfüllbaren Textfeldern und navigierbaren Menüs zügig eine Anwendung “zusammengeklickt”, die aussieht als wäre sie skizziert. Somit versteht der Entwickler, wie er die Anwendung zu strukturieren hat. Der Designer weiß, an welchen Stellen er freie Hand hat und wo er wiederum an Vorgaben, bspw. Platzierungen von Menüs, Leisten oder Knöpfe, gebunden ist. Sogar der Benutzer bekommt bereits ein Gefühl für die Bedienbarkeit der Anwendung ohne ablenkende Elemente. Allen ist sofort klar, dass nichts davon fertig ist und es darum geht, die Anwendungs selbst zu planen.

Ich will endlich was sehen!

Aber klar doch, kommt sofort. Fangen wir ganz simpel an und öffnen SketchFlow. Halt! SketchFlow ist keine eigenständige Anwendung. SketchFlow ist seit vielen Versionen in “Microsoft Expression Blend” enthalten, welches nun “Blend for Visual Studio” heißt und mit Visual Studio mitgeliefert wird. Also öffnen wir Blend und erstellen ein neues Projekt der Kategorie “Silverlight” -> “SketchFlow”.

Es wird nun ein neues SketchFlow-Projekt erzeugt, welches in unserem Beispiel auf Silverlight basiert. In diesem kann man nun entsprechende SketchFlow-Controls hinzufügen oder sogar normale Controls, falls einem danach ist. Aus psychologischen Gründen, auch wenn ich diese natürlich nicht wissenschaftlich belegen kann, ist es jedoch ratsam weitestgehend bei den SketchFlow-Controls zu bleiben. Warum? Nun mal ehrlich: Wer würde eine offensichtliche Skizze bspw. nach dem Aussehen be-/verurteilen? Bei echten Controls besteht da schon eher die “Gefahr”.

Als Standard wird uns ein Screen 1 (Screen_1.xaml) erstellt und geöffnet, welches wir nun nach belieben mit lustigen Controls füllen können. Die entsprechenden Elemente holen wir uns aus dem Assets Menü im Unterpunkt “SketchFlow”, wobei die üblichen Controls unter “Styles” zu finden sind. Welche es gibt, sieht man recht deutlich auf dem nebenstehenden Bild. Zusätzlich gibt es aber natürlich auch noch allerhand andere Shapes, Screens, Templates, usw. die einem das Leben deutlich leichter machen sollten.

Ziehen wir uns also direkt mal ein paar Sachen in den Screen. Hat man schon einmal mit Blend und/oder Silverlight gearbeitet, dürfte einem die Bedienung natürlich recht bekannt vorkommen. Praktischerweise sind die Controls, welche man sich in den Screen ziehen kann, nicht nur bewegliche Bilder, sondern echte Controls die nur nach Skizzen aussehen. Somit können Comboboxen beispielsweise mit Auswahlmöglichkeiten gefüllt und Knöpfe mit einem Navigationsziel oder gar beliebigem Code ausgestattet werden. Man kann seinen Prototypen also mit genau der Funktionalität versehen, wie es das jeweilige Ziel am besten verdeutlicht. SketchFlow unterstützt auch bei der Erstellung von Animationen, Navigationsabläufen und einigem mehr, was jeder gern selbst mit ein paar wenigen Klicks erforschen kann.

In meinem Beispiel habe ich im oberen Bereich ein Menü mit einem Rectangle-Sketch angedeutet. In diesem habe ich ein TabControl-Sketch platziert, worin ich wiederum einige Button-Sketches und Checkbox-Sketches eingefügt habe. Somit ergibt sich mit ein wenig Geschick recht schnell ein Menü, welches verdächtig nach dem Ribbon-Menü des Windows Explorers aussieht. Dieses könnte man auch als Component-Screen implementieren, um es in verschiedenen Screens wiederzuverwenden. Unter dem Menü habe ich noch ein paar Thumb-Sketches und TextBlock-Sketches hinzugefügt. Soweit so gut.

Als nächstes legen wir noch einen weiteren Screen an, indem wir auf den bestehenden Screen unten in der SketchFlow Map rechtsklicken und einen neuen verknüpften Screen erzeugen. In meinem Beispiel habe ich diesen Bildschirm “New” genannt und den “New”-Knopf in unserem Hauptscreen zudem auf diesen neuen Screen navigieren lassen. Eine solche Navigation kann man auf Button-Sketches recht einfach hinzufügen, indem man diesen mit der rechten Maustaste anklickt, “Navigiere zu” auswählt und darunter den entsprechenden Screen anklickt. Diesen zweiten Screen füllen wir nun auch mit allerhand Controls. Ich habe dafür das Menü aus dem Hauptscreen kopiert und verändert, ein Title-Sketch, einige TextBlock-, TextBox- und ComboBox-Sketches hinzugefügt und zudem eine kleine Überraschung eingebaut, die jeder selbst erkunden darf. Außerdem habe ich ein Note-Sketch hinzugefügt, um den jeweiligen Benutzer/Tester darauf hinzuweisen, dass die Felder nicht vollständig sind und er gerne Vorschläge einreichen darf. Womit wir auch schon bei dem für diesen Blog letzten genannten Feature sind: Der Feedback-Funktion.

Feedback? Das will ich genauer wissen!

Was nützt einem der tollste Prototyp, wenn man die Eindrücke, Vorschläge und Kritiken der jeweiligen Benutzer nur manuell oder sogar garnicht heraus bekommt. Klar könnte man auch eine Feedback-Funktion in den Prototyp einbauen, aber wozu das Rad neu erfinden? In SketchFlow gibt es bereits eine Feedback-Funktion, welche zudem recht mächtig ist.
Der Nutzer kann mit Textmarker oder Freihand den Screen bemalen/beschriften und einen entsprechenden Text in der Feedback-Box schreiben, um so sein Feedback noch exakter rüberbringen zu können. Wie dies genau funktioniert, darf unten in der Beispiel-Vorschau gern ausprobiert werden. Hat man sein Feedback vollendet, kann man es exportieren und dem jeweiligen Designer/Entwickler zukommen lassen.

Fazit und Download

SketchFlow eignet sich aus meiner Sicht sehr gut für Prototyping und auch bereits zur sehr frühen Planung von Benutzeroberflächen, Prozessabläufen und Layouts. Obwohl man mit SketchFlow fast schon fertige Anwendungen erzeugen kann, bleibt der sichtbare Eindruck auf dem Niveau einer Skizze, wodurch jeder Teilnehmer eines Meetings dazu angehalten ist, sich auf das Wesentliche zu konzentrieren. Dazu kommt die einfache Möglichkeit der Verteilung des Prototyps und der Einsammlung von Feedback der verschiedenen Nutzergruppen. Wie viele Tools ist es sehr mächtig, wenn man es richtig dosiert verwendet!

Natürlich gibt es wie üblich die gesamte Solution zum Download. Außerdem darf jeder, der Silverlight installiert hat, das fertige Beispiel direkt hier begutachten.

Quellen: SketchFlow Übersicht, Erstellen von Prototypen mit SketchFlow, SketchFlow Video
Autor: Dirk Sarodnick

Google+

SharePoint-CRM-IntegrationKennen Sie das Problem, wenn Dokumente im CRM nicht auch im SharePoint sind? Oder wenn zu einem Kunden jedes mal manuell eine passende SharePoint-Seite angelegt werden muss? Wir nicht mehr, denn wir haben eine Lösung.

[Randnotiz: Das ist unser Einführungs-Blogartikel. Erfahren Sie mehr auf unserer Produktseite.]

Seit Längerem haben wir eine Lösung in Betrieb, die uns so einige Integrationsthemen abnimmt. Anfänglich noch eher spartanisch, kann diese mittlerweile mit den Eigenheiten der neuen Onlinevarianten von CRM 2013 und SharePoint 2013 umgehen. Der eine oder andere Kunde bekam diese Lösung bereits, jedoch musste diese immer aufwändig angepasst und bereitgestellt werden. Doch nun haben wir eine CRM-Lösung, die bequem importiert und konfiguriert werden kann.

Was denn nun für eine Lösung?

Wir nennen ihn liebevoll “CRM-SharePoint-Integrator“. Es ist, wie bereits erwähnt, eine CRM-Lösung (Solution) die ziemlich einfach importiert werden kann. Dazu begibt man sich im CRM in das Menu “Einstellungen” > “Lösungen”. Dort angekommen wählt man “Importieren” und klickt sich durch den sich öffnenden Assistenten.

Import-Solution1

Was kann der CRM-SharePoint-Integrator?

Vereinfacht ausgedrückt, kann er für unterschiedlichste Ereignisse im CRM (bspw. das Anlegen/Ändern einer Firma) ein/mehrere SharePoint-Objekt/e (siehe Produktmatrix hier) im SharePoint anlegen. Im Folgenden möchten wir Ihnen ein paar Antworten auf die typischen Fragen zu, die uns als Microsoft Systemhaus in Kundenprojekten immer wieder begegnen beantworten:

Wie verbinde ich Microsoft SharePoint und Dynamics CRM?

  • Wie erstelle ich automatisch eine SharePoint-Webseite pro Account, Opportunity oder Kampagne im Dynamics CRM?
  • Wie erstelle ich nach Bedarf SharePoint Bibliotheken, – Webseiten etc. für Entitäten im Dynamics CRM?
  • Wie synchronisiere ich Accountdaten aus Dynamics CRM als Listeneintrag in SharePoint?

Die Standard-Integration bietet leider nur wenig Features, um SharePoint mit Dynamics CRM zu verbinden: Dynamische URLs werden erzeugt, eine Dokumentenverwaltung steht zur Verfügung. Mehr ist es leider nicht. Aber die Lösung CRM-SharePoint-Integrator von ProTechnology bietet viele Vorteile, wie Sie anhand der Produktmatrix unten sehen. Neben Dokumenten-Bibliotheken sind auch Standardlisten, benutzerdefinierte Listen (auch nach Vorlage), Teamseiten und vieles mehr möglich automatisiert aus Entitäten (Datensatztyp) im CRM zu erzeugen. Für die Konfiguration steht eine eigene Entität zur Verfügung, in der Ihr Systemadmin schnell und einfach bestimmen kann, in welcher Entität bei einem bestimmten Ereignis eine SharePoint-Seite/-Element benötigt wird. Auch die Online-Versionen von SharePoint und Dynamics CRM werden unterstützt .

Oberflaeche_fuer_die_Konfiguration

Oberfläche für die Konfiguration

Wie kann die Standard-SharePoint-Integration in Dynamics CRM erweitert werden?

Die Standard-Integration kann um die in der hier aufgeführten Produktmatrix genannten Listen/Seiten erweitert werden oder nutzen Sie komplett die Funktionalität, die SharePoint Ihnen bietet, indem Sie sich SharePoint im IFrame in Dynamics CRM anzeigen lassen. Auf diesem Weg können Sie über ein Fenster im CRM-Datensatz in den SharePoint schauen und Features, wie Kopie herunterladen, Eigenschaften bearbeiten, SharePoint-Suche etc. nutzen.

SharePoint_Dokumentenbibliothek_pro_Account

SharePoint Dokumentenbibliothek pro Account

Projektmanagement mit Integration Dynamics CRM und SharePoint verbessern

Welche SharePoint Apps und Funktionen sind im Dynamics CRM integrierbar?

Unsere Produktmatrix und unsere Anwendungsfälle erläutert im Detail, welche SharePoint-Elemente, wie im Dynamics CRM konfiguriert werden können. Von Standardlisten, Dokumentenbibliotheken, benutzerdefinierten Listen/Seiten, Teamseiten, Ordnern, benutzerdefinierten Listeneinträgen mit konfigurierbarem Feld-Mapping, OneNote-Notizbücher/bzw. -Abschnitte, Taxonomie-Einträge mit Hierarchie und vieles mehr sind derzeit möglich aus dem CRM im SharePoint zu erstellen.

Wie verbinde ich OneNote mit Dynamics CRM?

Beschäftigt man sich ein wenig mit der Materie, findet man die vor kurzem noch angekündigte OneNote-API. Jedoch kann diese API im aktuellen Status nur das OneNote-Notizbuch im eigenen OneDrive bearbeiten. Eine Bearbeitung eines im SharePoint liegenden Notizbuchs ist aktuell noch nicht möglich, aber immerhin bereits auf der Wunschliste.

Da aber auch wir nicht so lange warten wollen, haben wir analysiert, welche Alternativen es gibt. Erstaunlicherweise sind es sogar recht viele, die jedoch alle der Reihe nach aus Gründen der Performance oder Kompatibilität ausscheiden. Nur eine Alternative blieb, die Anfangs regelrecht gepflastert mit Stolpersteinen schien, die sich jedoch im Laufe der Zeit eher als Steighilfen erwiesen. Im Screenshot sieht man, wie eine mögliche Konfiguration aussehen könnte. Mehr dazu gibt es auf dem folgenden Blog-Beitrag: OneNote heiratet CRM/SharePoint-Integrator

OneNote - Seite

OneNote-Abschnitt/-Seite pro Account/Verkaufschance im Dynamics CRM

Fazit

Der CRM-SharePoint-Integrator kann Ihnen viele wiederkehrende Aufgaben abnehmen und integriert zudem den SharePoint je nach Wunsch in Ihrem CRM. Kompatibel ist der CRM-SharePoint-Integrator mit dem CRM ab Version 2011 in den Varianten On-Premise und Online sowie mit dem SharePoint ab Version 2007 in den Varianten On-Premise und Online. Die Funktionalität können Sie sich auch nochmal im Webcast hier anschauen:

Erfahren Sie mehr auf unserer Produktseite. Haben Sie Fragen zum Produkt, möchten Sie eine Vorführung oder das Produkt beziehen, so sprechen Sie uns an.

Autor: Dirk Sarodnick und Melanie Wolf
Google+

bildteaser_blog_072013Kennen Sie das Problem bei allen üblichen Reporting Suites, dass exportierte Word-Dokumente schlecht bis garnicht bearbeitbar sind? Der Aufbau des Dokumentenlayouts wird mit Tabellen oder gar Frames zusammengehalten und der Benutzer hat seine Mühe, mal eben ein paar Zeilen einzufügen. Doch was ist, wenn der Kunde einen vollständigen Export benötigt, dessen Resultat (also das Word-Dokument) auch gut, wenn nicht sogar sehr gut, bearbeitbar ist? Was ist, wenn die Vorlage dafür auch noch vom Kunden änderbar sein soll? “Back to the roots” ist die Lösung, denn Microsoft bietet hierfür eine einfache, mächtige und kaum bekannte Möglichkeit: XML Mapping

Was ist XML Mapping?

Schwarze Magie! Doch schweifen wir für einen Moment ab. Der Weg zu diesem Lösungsansatz führte über den Gedanken der Word-Vorlagen und Serienbriefe. Es musste doch irgendwie möglich sein, einem Word-Dokument beizubringen, dass es Felder automatisch ausfüllt und die dafür nötigen Daten aus irgendeiner Datenquelle zieht. Grundsätzlich ist dies auch völlig problemlos möglich, wenn man ein paar einfache Daten anbinden will.

Doch in der Realität braucht man eben immer etwas mehr, als das schöne bunte Beispielprojekt einem zeigt. So auch hier, denn es musste auch möglich sein, anhand der Daten einzelne Tabellen oder Tabellenzeilen zu wiederholen. Der Ansatz des Serienbriefs zerschellte also in tausende kleine Teile. Auch die Word-Vorlagen führten nicht zum Ziel. Irgendwie muss das doch aber funktionieren? Vielleicht fügt man dem Dokument einfach ein wenig VBA hinzu? Klar, das würde auch funktionieren, aber wer möchte schon freiwillig die Ausführung von VBA in einem Word-Dokument aktivieren, welches man von einem Internetportal heruntergeladen hat? Und selbst wenn, will man sowas denn veröffentlichen? Eher nicht.

Fast schon aufgegeben, fand sich dann jedoch ein Menüpunkt “XML-Zuordnungsbereich” im Entwicklertools-Menü, welcher vielversprechend klingt und förmlich darauf wartete, dass man ihn klickt.

Wie genau funktioniert XML Mapping nun?


Mit einem Klick auf den genannten Knopf öffnet sich ein Menü “XML-Zuordnung” am rechten Bildschirmrand. In diesem sieht man eine Dropdown-Liste mit allen verfügbaren XMLs, welche im Dokument eingebettet sind, und deren inhaltliche Struktur. Standardmäßig sieht man daher erst einmal die üblichen Dokumenteigenschaften mit den Daten für Autor, Titel, Beschreibung, usw.

Es scheint also, als könne man eine XML-Struktur inkl. Daten in ein Word-Dokument einbetten. Da man .docx-Dateien problemlos mit dem OpenXML SDK bearbeiten kann, war dies also schonmal der erste Lichtblick. Sollte es tatsächlich möglich sein, dass man mit nur wenigen Zeilen C# ein ganzes serialisiertes BusinessObject in Word einbetten kann, welches wiederum im Word-Dokument vorgefertigte Felder ausfüllt? Ja, genau das sollte es.

Doch erst einmal müssen wir eine Vorlage erstellen. Dazu legen wir uns eine XML-Datei mit der gleichen Struktur wie unser zukünftiges serialisiertes BusinessObject an, jedoch erst einmal ohne Daten. Warum? Nun, es ist eben eine Vorlage. Das vorbereitete XML soll ja ersetzt werden. Ein Klick in die Dropdown-Liste zeigt uns einen Menüpunkt, mit welchem wir unsere XML-Struktur dem Word-Dokument bekannt machen können.


In meinem Beispiel verwende ich dazu dieses XML als Vorlage.

Ist das erledigt, haben wir unsere XML-Struktur zur Verfügung und können unsere Felder hinzufügen. Dabei kann man sogar zwischen unterschiedlichen Typen wählen und somit sogar eine Datumsauswahl direkt im Word-Dokument anbinden, was die Bearbeitbarkeit deutlich erhöht. Dazu Klicken wir einfach mit der rechten Maustaste auf das gewünschte XML-Element und es öffnet sich folgendes Menü.
Kleiner Tipp: Bei leeren XML-Feldern wird einem automatisch der Standardtext angezeigt. Diesen kann man ändern, wodurch auch bei leeren Feldern ein beliebiger Text als Fallback stehen kann.

Und was ist mit Wiederholungen?

Da sind wir auch schon beim Kern. Bis hier hin ist ja alles schön und gut, wäre aber auch mit einer einfachen Serienbrief-Datenbindung möglich gewesen. Doch wir wollen ja Wiederholungen in Wiederholungen in Wiederholungen in […]. Dazu klickt man einfach mit der rechten Maustaste auf das XML-Element, welches sich wiederholt, und verwendet den erscheinenden Menüpunkt. Der Einfachheit halber kann man sich auch eine paar Absätze, Tabellen und Texte vorbereiten, markieren und mit diesem Menüpunkt eine Wiederholung daraus erzeugen. Diese Wiederholungen lassen sich sogar noch sinnvoll benennen, wodurch der Nutzer nützliche Menüpunkt erhält.

Verarbeitung und Beispiel

Nun muss das Dokument nur noch nach den eigenen Vorstellungen gefüllt werden. Das war’s dann auch schon.
Die damit erstellte Vorlage, welche lediglich ein simples Word-Dokument (docx) mit einer vorbereiteten und eingebetteten XML-Struktur ist, muss nun nur noch mit dem OpenXML SDK bearbeitet werden. Es muss also das Dummy-XML, welches wir im obigen Schritt hinzugefügt haben, ersetzt werden. Entgegen der unten verlinkten Quelle, muss diese Ersetzung natürlich nicht mit VBA-Code innerhalb des Dokuments geschehen. In meinem gleich folgenden Beispiel habe ich dafür dieses XML mit Daten verwendet.

Den Rest erledigt Word beim Öffnen des Dokuments von selbst. Es füllt die Felder und erzeugt die einzelnen ausgefüllten Wiederholungen, wie man im Beispiel-Dokument wunderbar sehen kann. Hierfür habe ich natürlich wieder ein Beispiel vorbereitet, welches nur einen Klick entfernt ist.
Kleiner Tipp: Im Bearbeitungsmodus erkennt man die Magie des Ganzen erst richtig.

Fazit

Es ist also sehr einfach möglich, dem guten Microsoft Word beizubringen, wie es ein Dokument mit Daten zu füllen hat. Das enthaltene XML (bzw. das serialisierte BusinessObject) ist natürlich schnell und einfach mit C# und dem OpenXML SDK in das Dokument eingefügt. Ein komplettes Aufbauen des Dokuments mit dem OpenXML SDK oder aufwändigem Code bleibt einem erspart. Dadurch, dass das Dokument in Word selbst erstellt wird, ist es am Ende für den Nutzer genauso einfach zu bearbeiten, wie die Vorlage selbst. Aufgrund der Nützlichkeit der Wiederholungen ist es zudem noch einfacher für den Benutzer.
Und das Beste an dieser Methode ist, dass die geänderten Daten (inkl. der Wiederholungen) in die XML-Struktur zurück geschrieben werden, wenn der Nutzer auch die entsprechenden Felder verwendet. Dadurch wäre sogar ein Re-Import der Daten denkbar. Wenn das mal nicht nach schwarzer Magie klingt!

Quellen/Links: OpenXML SDK, XML Mapping, CustomXML mit dem OpenXML SDK
Autor: Dirk Sarodnick
Google+

bildteaser_validierungAls Zugabe zu meinem letzten Blog über “Lokalisierung aus der Datenbank in ASP.NET MVC“, geht es diesmal um Validierung. Praktischerweise lässt die nun folgende Implementierung zudem weitere Wege offen, verschiedenste Konfigurationen in diversen Datenquellen zu hinterlegen. Je nach gewählter Datenquelle (Datei, Datenbank, Azure Storage) lassen sich die Konfigurationen problemlos während der Laufzeit verändern. Daher die Wahl der Validierung als Beispiel, um die Mächtigkeit zu demonstrieren. Der Titel müsste korrekterweise also “Konfiguration aus einer beliebigen Datenquelle” heißen, aber das würde den Rahmen deutlich sprengen. Doch genug des Vorgeplänkels: “Developers, start your Environment!

Meistens integriert man die Validierung direkt im Code. Methoden prüfen die Werte der einzelnen Eingaben. Im ASP.NET MVC lässt sich das ja bereits mit Attributen am Model entschlacken. Problem ist hierbei allerdings, dass Attribute nicht ohne weiteres auf unterschiedliche Eigenschaften zugreifen können. So lässt sich bspw. mit einem Attribut an einer StartDate-Eigenschaft schwer prüfen, ob die entsprechende EndDate-Eigenschaft zeitlich später angegeben wurde. Unmöglich ist es nicht, aber bisher fand ich keinen sauberen Weg. Somit wählt man über kurz oder lang zumindest teilweise wieder den Weg der direkten Validierung ohne Attribute, wodurch am Ende ein noch viel schlimmerer Misch-Masch entsteht. Ein weiteres Thema ist außerdem die clientseitige Validierung, die bei Attributen recht praktisch mit erzeugt wird, wenn man die Macht des MVC korrekt nutzt. Doch wie Vereinheitlicht man diese ganzen Validierungen und fügt zudem die Flexibilität einer Konfiguration hinzu, die sich praktischerweise auch noch in einer Oberfläche konfigurieren lässt?

Schön und gut, aber was hilft uns nun?

Da sind wir auch schon beim Kern unseres Themas. Es mag sicherlich andere Möglichkeiten geben. Eventuell sogar bessere. Doch ich konzentriere mich hier auf Erprobtes und Gewohntes:
Die Nutzung der Enterprise Library mit einer eigenen ConfigurationSource. Das ist auch schon fast die gesamte Magie. Die Enterprise Library bringt, neben vielen anderen nützlichen Dingen, die Möglichkeit der konfigurierbaren Validierung mit sich. Dazu gibt es ein kleines Programm, mit welchem man ganz simpel seine Klassen  sowie Validatoren wählt und konfiguriert, plus am Ende eine ganze Validierung einstellt. Alternativ kann man sich auch manuell durch die XML Konfiguration hangeln.

Die Validierung der Enterprise Library funktioniert auch etwas anders, als man es bei Attributen gewohnt ist. Es lassen sich unterschiedliche Validatoren zusammensetzen und sogar And-/Or-Validatoren verwenden. Auch das Validieren von mehreren abhängigen Eigenschaften (StartDate, EndDate) stellt keine Probleme dar. Erweitern kann man diese natürlich auch mit eigenen Validatoren, wodurch auch jede andere denkbare Form der Validierung möglich wird. Das Ganze lässt sich mit etwas Code auch problemlos auf die clientseitige Validierung adaptieren, worauf ich jedoch erst im nächsten Blog eingehen möchte.
Zur Speicherung dieser Konfigurationen bringt die Enterprise Library unterschiedliche ConfigurationSources mit. Beispielsweise eine SqlConfigurationSource oder gar eine Azure BlobConfigurationSource. Doch was ist, wenn man sein Frontend mit einer Serviceschicht von diesen Teilen abgetrennt hat? Genau, man muss sich selbst eine ConfigurationSource bauen.

Unsere eigene ConfigurationSource

Als Erstes müssen wir unsere eigene ConfigurationSource vom Interface IConfigurationSource aus dem Namespace Microsoft.Practices.EnterpriseLibrary.Common.Configuration ableiten. Die im Interface enthaltenen Methoden müssen wir anschließend nicht vollständig implementieren. Uns werden nur die Methoden GetSection, Add und Remove interessieren, wobei genau genommen nur GetSection wirklich relevant für unseren Fall ist, außer man beabsichtigt das Konfigurationsprogramm direkt mit dieser ConfigurationSource zu verwenden. In diesem Blog beschränke ich mich erst einmal auf das Wesentliche, also nur auf GetSection, auch wenn die Implementierung für Add und Remove alles andere als kompliziert ist. In der angehangenen Solution sind diese natürlich beispielhaft mit implementiert.

Die Implementierung von GetSection ist, wie man hier deutlich sieht, ziemlich unspektakulär. Wir fragen lediglich unseren Service nach der gewünschten Section, deserialisieren diese und werfen sie zurück. Zur Deserialisierung benötigen wir allerdings bereits den korrekten Typ unserer Section, den wir uns mit Hilfe einer privaten Methode GetSectionByName holen. Diese sieht dann ganz schlicht wie folgt aus:

Dazu nun unser eigenes ConfigurationElement

Zur Vollständigkeit unseres Gesamtkunstwerks benötigen wir nun noch ein ConfigurationSourceElement, welches wir in unserer ConfigurationSource mit Hilfe des Attributs ConfigurationElementType verlinkt hatten. Dieses enthält eigentlich keinen ernsthaften Code und sieht entsprechend so aus:

Anbinden in der web.config und das wars, oder?

Fast! Aber alles zu seiner Zeit. Die Anbindung in der web.config ist auch keine große Sache. Das Konfigurationsprogramm der Enterprise Library würde dies sogar für uns erledigen. Allerdings achtet dieses nicht so wirklich auf Reihenfolge und Formatierung der web.config, die man sich möglicherweise vorher schön säuberlich aufgeräumt hatte. Wie auch immer, hier der entscheidende Code:


Man sollte meinen, wir sind nun fertig. Doch genau genommen haben wir bisher nur die Validierung der Enterprise Library vorbereitet und eine eigene Quelle für Konfigurationen erstellt. Das ist toll und reicht auch aus, wenn man die Validierung nur “manuell” ansteuern möchte. Im MVC ist es allerdings üblich die Validierung vom ModelValidator verrichten zu lassen, da dieser nicht ohne Grund dafür geschaffen wurde.

See you later, ModelValidator

Mit einem ModelValidator wird unsere Validierung beim Erhalt von Daten in einer Action des Controllers bereits ausgeführt, sodass wir direkt mit dem Ergebnis und dem entsprechenden Model arbeiten können. Zusätzlich wird natürlich auch bei TryUpdateModel und TryValidateModel unser ModelValidator aufgerufen, was uns erneut ein manuelles ansteuern der Enterprise Library Validierung erspart. Das ist fast wie Weihnachten :-)

Unser ModelValidator benötigt zur Einbindung ins MVC allerdings auch noch einen ModelValidatorProvider. Diesen implementieren wir kurz und schmerzlos folgendermaßen:

Der ModelValidator selbst ruft dann ohne Umwege die Validierung der Enterprise Library auf. Im nun folgenden Screenshot habe ich mich dabei auf den wesentlichen Teil beschränkt. In der angehangenen Solution ist im Provider zusätzlich ein Cache eingebaut, den man auch problemlos auf Dependency Injection (die Enterprise Library liefert dafür Unity) ummünzen kann. Zudem ist dort auch bereits die clientseitige Validierung angedeutet, die im nächsten Blog lediglich um die konkreten Adapter erweitert werden muss.

Nun implementieren wir nur noch die Validate-Methode, welche die Validierung der Enterprise Library aufruft und direkt dessen ValidationResults in für das MVC taugliche ModelValidationResults umwandelt.

Zu guter Letzt geben wir dem MVC noch unseren mühsam angelegten ModelValidator auf den Weg, sodass fortan die Validierung von der Enterprise Library übernommen wird.

Fazit

Nun haben wir unser Gerüst fertig gestellt. Die Validierung kann nun komfortabel konfiguriert und natürlich auch außerhalb des ModelValidators vom Code angesteuert werden, wodurch sich die gleiche Validierungslogik in der gesamten Anwendung wiederverwenden lässt. Fehlt eigentlich nur noch die clientseitige Validierung.

Als kleines Sahnehäubchen habe ich diesmal nicht nur den üblichen SourceCode in ein ZIP gepackt, sondern verweise zusätzlich auf ein sehr interessantes Projekt namens ElValWeb. In diesem ist die Validierung der Enterprise Library clientseitig umgesetzt. Etwas angepasst/ aktualisiert lässt es sich wunderbar inkl. CustomValidator-Unterstützung im MVC 4 einsetzen. Das möchte ich mir allerdings, wie bereits erwähnt, für einen späteren Blog aufheben. Dieses ganze Wissen in einen Topf geworfen und gut umgerührt, ergibt dann eine komplette konfigurierbare Validierung aus einer beliebigen Datenquelle (Datenbank, Azure Storage) inkl. clientseitiger Validierung. It’s magic!

Im Übrigen können die Meldungen unserer soeben implementierten Validierung auch, passend zu meinem letzten Blog, aus Resourcendateien und demzufolge auch aus der Datenbank kommen. Man könnte meinen, das ist Absicht. ;-)
Wie versprochen hier die gesamte Solution zum Download.

Quellen: Enterprise Library, MSDN – Configuring Enterprise Library, MSDN – Validation Application Block
Autor: Dirk Sarodnick
Google+

Es war einmal ein kleines Kind. Dieses lief seit einigen Monaten und erfreute sich großer Beliebtheit. Doch dieses Kind war nicht so einfach zu betreuen, wie der Herr Vater sich das vorstellte. Bei der Korrektur eines Sprachfehlers, musste man es ständig neu gebären, was auch die Frau Mutter nicht sehr erfreute. Also dachte sich der Herr Vater: “Es muss doch eine Möglichkeit geben, die Sprache des Kindes direkt in seinem Kopf zu korrigieren.”  So, oder so ähnlich, muss es wohl gewesen sein, als der Mensch lernte, seine Sprache in seinem Kopf zu speichern. Doch was ist, wenn das Kind ein Projekt ist? Ständig muss man die Anwendung neu deployen, obwohl man doch nur ein paar Texte und/oder Benennungen verändert hat. Oder man lagert Bereiche, welche sich häufiger ändern (könnten), einzeln in die Datenbank aus. Das klingt nicht nur unflexibel, es ist auch unflexibel. Gerade bei längeren Release-Zyklen oder ewig ladenden Azure-Instanzen wird so eine kleine Textänderung schnell zur Geduldsprobe. Also ab mit den Texten in die Datenbank… und zwar zackig!

Meist nutzt man Resourcendateien, um unterschiedliche Sprachen seiner Webanwendung bereitzustellen. So mancher hat dieses Problem sicherlich längst erkannt und greift die einzelnen Sprachelemente direkt aus der Datenbank ab, statt Resourcen zu verwenden. Doch was ist mit Fremdassemblies, die sich möglicherweise nur über Resourcen lokalisieren lassen? Hier kommt der Ansatz mit einer ResourceProviderFactory zum Zuge. Diese gibt einem die Freiheit, die angefragten Resourcenwerte bspw. aus einer Datenbank oder einem Service zu saugen. Ganz nebenbei lässt sich diese natürlich mit der manuellen Variante ansteuern, um ggf. mächtigere Abfragen zu tätigen. Doch bleiben wir beim Thema.

Schritt 1: Wie sieht so eine ResourceProviderFactory aus?

Bis dahin also noch nichts Spektakuläres. Die Factory erstellt in unserem einfachen Beispiel lediglich eine neue Klasse des ResourceProviders. Dieser enthält nun unsere Logik, um die entsprechenden Resourcen, möglichst geschickt, aus der Datenbank zu saugen. Dabei wird entweder lediglich der Klassenname bei globalen Resourcen oder der virtuelle Pfad bei lokalen Resourcen als ResourceSet übergeben, welches wir in unserem ResourceProvider halten werden. Je nach belieben kann dies für globale und lokale Resourcen in einzelne Klassen getrennt und/oder zusätzlich gefiltert werden.

Schritt 2: Der ResourceProvider verrichtet also das eigentliche Werk. Aber wie?

Dazu muss unser ResourceProvider lediglich die Interfaces “IResourceProvider” und “IImplicitResourceProvider” implementieren. Das sieht im Wesentlichen folgendermaßen aus:

Wie so oft, sagt sich das allerdings wesentlich einfacher, als es dann tatsächlich ist. Gleichermaßen sieht der entstandene Code viel komplexer aus, als er dann tatsächlich ist. Schwer, einfach, schwer, einfach, was denn nun? Angesichts des Gesamtkunstwerks, was uns schon bald erwartet, würde ich zu “Schw’einfach” tendieren. Aber sehen Sie selbst.

Zunächst implementieren wir die Methoden “GetObject” beider Interfaces. Auch hier machen wir kein großes Hexenwerk und verweisen auf eine allgemeingültige Methode “GetObjectInternal”. Lediglich die Methode “ConstructFullKey” zerlegt unseren ImplicitResourceKey, um den eigentlichen ResourceKey herauszufiltern.

Diese Methode “GetObjectInternal” hat eine einfache Aufgabe: Sie holt nun endlich unseren Text aus der Datenbank. Dies geschieht im Folgenden über einen “LocalizationService”, welcher dann direkt auf ein typisiertes DataSet zugreift. Für die Abfrage werden hier die drei Werte zur Identifikation eines Resourcevalues übergeben: Culture (bspw. “de-DE”), ResourceSet (bspw. “Errors” oder “/Views/Shared/Site.Master”) und ResourceKey (bspw. “SiteTitle”). Als Ergebnis dieser Methode erhält man den passenden String (bspw. “Startseite”).

Damit haben wir nun einen wichtigen Teil unserer Anwendung fertiggestellt. Doch aufmerksame Leser werden sicherlich bemerkt haben, dass wir noch nicht alles implementiert haben. Uns fehlt noch die Property “ResourceReader” und die Methode “GetImplicitResourceKeys”, welche eine ICollection zurückliefert. Zudem fällt im obigen Bild auf, dass die Methode “GetObjectInternal”, neben der Serviceanfrage in der Datenbank, zusätzlich eine Methode “GetResourceCache” anspricht.

Schritt 3: ResourceReader und ICollection? Das klingt verrückt.

Die nun angerichtete Verwirrung lässt sich ziemlich schnell wieder auflösen. Grundsätzlich unterscheidet man in diesem ganzen ResourceProvider zwischen zwei Varianten, um Resourcen abzuholen: Einen einzelnen Wert oder eine Auflistung von Werten eines bestimmten ResourceSets und/oder einer spezifischen Culture. Erstere haben wir in unserer Methode “GetObjectInternal” gebündelt abgehandelt. Zweitere werden wir nicht ganz so elegant bündeln, nutzen aber im Kern die gleiche Funktionalität. Doch genug des Vorgeplänkels und zurück in die Praxis.

Fangen wir mit der Methode “GetResourceCache” an. Diese holt uns nun die erwähnten Werte aus der Datenbank und sortiert sie fein säuberlich in unseren Cache. Dazu nutzt sie die übergebene Culture und das festgelegte ResourceSet. Wenn erledigt, gibt sie unseren Cache zurück, damit der Aufrufer damit arbeiten kann.

Und weil es gerade so spaßig ist, springen wir direkt zu der Methode “GetImplicitResourceKeys”. Der nun folgende Code mag durchaus Geschmackssache sein, sieht aber komplizierter aus, als er tatsächlich ist. Wir lesen lediglich unseren ResourceReader aus, filtern dabei nach unseren keyPrefix und trennen schlussendlich nur den ResourceKey unter Verwendung unseres keyPrefixes, um damit einen ImplicitResourceKey erstellen zu können. Zurückgegeben wird also letztlich nur eine ICollection von ImplicitResourceKeys. Nähere Infos dazu lassen sich im MSDN nachlesen.

Zu guter Letzt benötigen wir noch unseren ResourceReader, den wir bereits oft genug verwendet, aber bisher nicht implementiert haben. Groß angekündigt, aber weniger spektakulär: Unser herzallerliebster ResourceReader ist im Grunde nämlich nichts weiter, als ein kleiner Wrapper für unser ResourceCache-Dictionary. Dies sieht dann wie folgt aus.


Schritt 4: Und wie binde ich dieses Kunstwerk nun ein?

Das ist wohl mit Abstand der “schwierigste” Teil unseres Abenteuers. Man fügt einfach folgendes Schnipsel in seine web.config und schon kann sich gefreut werden. Kernbestandteil ist hier natürlich der Wert des Attributs “resourceProviderFactoryType” des Elements “globalization”.

Fazit

Ich hoffe, den meisten Lesern ist bis hierhin bereits klar geworden, welche Vorteile die Implementierung des ResourceProviders und der ResourceProviderFactory mit sich bringt. Es ist nun möglich, viele Stellen in gewohnter Weise zu lokalisieren. Selbst die guten alten meta:resourcekey-Angaben funktionieren damit. Zudem kann man, wie in diesem Beispiel, einen eigenen Service, den man vorher ggf. nur manuell angesprochen hat, zur Lokalisierung anbinden.

Trotz der ganzen Vorteile überkommt mich immer ein seltsames Gefühl, wenn ich mir den entstandenen Code anschaue. “Schw’einfach” trifft es, denn es ist schwer und einfach zugleich, was in meinem Fall aber hauptsächlich an der Verworrenheit der beiden Interfaces liegt. Aber es funktioniert, ist nützlich und kann mit ein wenig mehr Arbeit durchaus noch “sauberer” implementiert werden.

Zudem sollte noch erwähnt sein, dass die Auslagerung der Lokalisierung in die Datenbank, einen weiteren Vorteil mit sich bringt: Es kann problemlos eine Administrationsoberfläche (Web-/ Windowsanwendung) aufgesetzt werden. Mit dieser kann man sogar Resourceninhalte komfortabel mit HTML formatieren, was je nach Einbindung der Resource (<%: vs <%=) kodiert oder nicht kodiert wird. Auch denkbar wäre die Möglichkeit für vorhandene Benutzer, mit an der Übersetzung zu arbeiten.

Als kleiner Bonus zur Weihnachtszeit gibt es die gesamte Solution auch noch zum Download.
In diesem Sinne: Viel Spaß damit!

Quellen: MSDN
Autor: Dirk Sarodnick
Google+

Viele kleine und große Unternehmen leiden täglich unter dem alten Problem der Signatur. Immer wieder stellt sich die Frage, an welcher Stelle und auf welche Art soll die Signatur eingehangen werden? Direkt im Microsoft Outlook des Mitarbeiters? Aber was ist, wenn der Mitarbeiter extern ist und eine E-Mail mit vollwertiger Signatur über Outlook Web Access (OWA) oder ein per SMTP angebundenes Mobilgerät versenden muss? Wie stellt man sicher, dass bei einer Änderung der Anschrift oder der Telefonnummer jeder betroffene Mitarbeiter seine Signatur korrigiert? Und wie regelt man die Signatur mit internen E-Mails?
Diese und viele weitere Fragen tauchen in diesem Zusammenhang regelmäßig auf. Schauen wir uns doch einfach gemeinsam eine Lösung an, die all diese Probleme mit Leichtigkeit bewältigt: Exclaimer Mail Disclaimers.

Template Editor

Zu Beginn erstellt man ein sogenanntes Template mit dem Template Editor. Dabei besteht die Möglichkeit für jedes Absendeformat (HTML, RichText und PlainText) eine Signatur vorzubereiten. Die HTML-Vorlage kann je nach Belieben mit einem Designer oder direkt mit HTML erstellt werden. In allen Formaten können dynamische Felder eingefügt werden, mit denen man personalisierte Signaturen erzeugen kann. Diese dynamischen Felder umfassen einen Großteil der üblichen AD-Informationen, wie Namen, Adressen, Telefonnummern bis hin zum Foto, können aber auch Inhalte aus anderen Dateien nutzen.

Mail Disclaimer

Hat man seine gewünschte Signatur vorbereitet, muss diese nun noch im Mail Disclaimer als sogenannte Policy hinterlegt werden. In dieser Policy können nun verschiedenste Einstellungen hinterlegt werden, um die neue Signatur bspw. bei externen E-Mails oder nur einem bestimmten Nutzerkreis anhängen zu lassen. Bevor man diese Policy nun scharf schaltet, kann diese mit unterschiedlichsten Szenarien mit dem Policy Tester geprüft werden, wobei in diesem Fall keine echte E-Mail versendet wird. Natürlich ist es auch mit dieser Lösung empfehlenswert, die erstellte HTML-Signatur in verschiedenen E-Mail Clienten auf mögliche Layoutfehler zu prüfen.

Fazit

Mit Exclaimer Mail Disclaimers ist es also problemlos möglich, unternehmens- oder abteilungsweite E-Mail-Signaturen vom Microsoft Exchange anhängen zu lassen. Es müssen keine Signaturen im Microsoft Outlook, Outlook Web Access oder Mobilgeräten eingestellt oder angepasst werden. Änderungen sind problemlos möglich, da die Signatur nun zentralisiert verwaltet und vom Microsoft Exchange angehangen wird. Und über die Policy lässt sich nun spielend leicht einstellen, dass interne E-Mails grundsätzlich gekürzte oder keine Signaturen enthalten. Das klingt doch traumhaft, oder?

Sie haben noch keinen Microsoft Exchange, kein Microsoft Outlook oder benötigen Unterstützung bei der Einbindung von Exclaimer Mail Disclaimers in ihr bestehendes System? Kontaktieren Sie uns auf kurzem Wege per Telefon oder E-Mail und wir kümmern uns um Ihr Anliegen.

Autor: Dirk Sarodnick

Google+