Integration von Dynamics CRM 4.0 in MS Office InfoPath 2007 – Teil 5 Submit-Methode und Deployment der Formularvorlage
Im fünften und gleichzeitig letzten Teil der InfoPath-Reihe behandeln wir die Implementierung der Submit Methode und das Deployment der Formularvorlage am Server. In Umsetzung unserer Anforderungen wird die Submit Methode zwei Fälle unterscheiden: Einmal, wenn der InfoPath-Benutzer auch gleichzeitig der Projekteigner ist. Dann soll in CRM ein neuer Spesenbericht angelegt werden. Andererseits, ist der Benutzer ein anderer als der Eigentümer, soll unser InfoPath-Formular diesem „geschickt“ werden. Wir lösen das, indem wir das XML als Dokument an eine Notiz zu einem Projekt hinzufügen und den Projekteigner darüber in Kenntnis setzen.
Als erstes müssen wir daher das Formular – das ja als „string“ an die Submit-Methode übergeben wird – analysieren. Wir wandeln es in ein XML Dokument um (das es ja ohnehin ist), navigieren uns durch die einzelnen Knoten und schreiben uns die Werte der einzelnen Formularfelder in Variablen. Das Konstrukt, das wir dafür verwenden ist eine verschachtelte do/while-Schleife, mit der wir uns zuerst den Knoten "my:meineFelder" raussuchen (der enthält die Daten!) und diesen dann Kindknoten für Kindknoten durchgehen.
XmlDocument doc = new XmlDocument();
// lade die Eingangsdaten in das XML-Dokument
doc.LoadXml(data);
XPathNavigator nav = doc.CreateNavigator();
nav.MoveToFirstChild();
do
{
if (nav.Name == "my:meineFelder" && nav.HasChildren)
{
nav.MoveToFirstChild();
do
{
if (nav.Name == "my:ProjectName")
{
projectid = nav.Value;
}
else if (nav.Name == "my:Titel")
{
spesenTitel = nav.Value;
}
[…]
else if (nav.Name == "my:txtUser")
{
spesenUserId = nav.Value;
}
} while (nav.MoveToNext());
// wenn alle Datenknoten durch sind, brich ab
break;
}
} while (nav.MoveToNext());
Wenn Benutzer == Projekteigner: Lege Spesenbericht an
Als nächstes vergleichen wir die IDs von Benutzer und Projekteigner. Stimmen diese überein, legen wir einen neuen Spesenbericht in CRM an. Dafür erzeugen wir uns eine Variable vom Typ new_spesenbericht (über die Webservice-API stehen uns ja auch benutzerdefinierte Entitäten als Objekte zur Verfügung) und legen die entsprechenden Werte fest:
new_spesenbericht spesenbericht = new new_spesenbericht();
spesenbericht.new_ausgabendatum = new CrmDateTime();
spesenbericht.new_ausgabendatum.Value = spesenDatum;
spesenbericht.new_begrndung = spesenBegruendung;
spesenbericht.new_name = spesenTitel;
spesenbericht.new_spesentitel = spesenTitel;
spesenbericht.new_betrag = new CrmMoney();
spesenbericht.new_betrag.Value = decimal.Parse(spesenBetrag);
spesenbericht.new_freigegeben = new CrmBoolean();
spesenbericht.new_freigegeben.Value = spesenFreigegeben;
spesenbericht.new_spesenzuprojektid = new Lookup();
spesenbericht.new_spesenzuprojektid.Value = new Guid(projectid);
// erzeuge ein neues Service für ausgelesenen Benutzer
CrmService myService =
CrmServiceUtility.GetCrmService(
"https://10.10.10.2:5555",
"MicrosoftCRM",
new Guid(spesenUserId));
// lege neuen Spesenbericht an
Guid spesenGuid = myService.Create(spesenbericht);
Sonst: Lade InfoPath Formular hoch
Sind Benutzer und Projekteigner unterschiedlich, müssen wir das InfoPath Formular als Notiz dem entsprechenden Projekt hinzufügen. Dafür wählen wir einen dreiteiligen Weg, den wir ganz ähnlich aus dem Word-Beispiel kennen:
- Schreibe das XML-Dokument temporär ins Dateisystem
- Lese die Datei per Filestream als Bytestream und verwandle die Daten in einen 64-bit String
- Hänge die derart codierten Daten als Dokument an eine neue Annotation an
Im Code schaut unsere Umwandlung dann wie folgt aus:
// schreib dir mal auf, was da zurückgekommen ist
string pathXmlFile = "C:\\inetpub\\wwwroot\\DataProvider\\text_"
+ projectid + "_" + DateTime.Now.Millisecond + ".xml";
StreamWriter writer = new StreamWriter(pathXmlFile);
writer.WriteLine(data);
writer.Close();
// verwandle das ganze in einen 64-bit String
byte[] byteData;
using (FileStream readerCode = new FileStream(pathXmlFile, FileMode.Open))
{
byteData = new byte[readerCode.Length];
readerCode.Read(byteData, 0, (int)readerCode.Length);
}
string encodedData = System.Convert.ToBase64String(byteData);
Beim Erzeugen der Notiz und dem Anhängen des Dokuments halten wir uns ebenfalls recht streng an das Word Beispiel. Als zusätzlichen Schritt müssen wir jedoch die Notiz einem anderen Benutzer zuweisen, als jenem, in dessen Namen die Notiz gerade erstellt wurde. Wem? Dem Eigentümer des Projektes, eh klar :)! Dieser soll schließlich über den neuen Anhang zu seinem Projekt informiert werden.
Wir erzeugen also einen neuen CrmService, diesmal mit Administratorenrechten, um sicher zu gehen, dass wir die erforderliche Berechtigung für die Zuweisung haben. Dieses Service lassen wir dann den Assign-Request ausführen bevor wir es sofort wieder zerstören – sicher ist sicher!
// weise die neue Notiz dem user zu, dem das Projekt gehört…
// … dafür brauchen wir aber die entsprechenden Rechte
// … also auch ein neus Service mit Adminrechten
string adminGuid = "F09418EE-5C7B-DD11-9C68-0003FF2BC9B2";
CrmService adminService =
CrmServiceUtility.GetCrmService(
"https://10.10.10.2:5555",
"MicrosoftCRM",
new Guid(adminGuid));
// erzeuge einen Zuzuweisenden :)
SecurityPrincipal asignee = new SecurityPrincipal();
asignee.Type = SecurityPrincipalType.User;
asignee.PrincipalId = new Guid(spesenProjectOwnerId);
// erzeuge ein Ziel für den Request
TargetOwnedAnnotation target = new TargetOwnedAnnotation();
target.EntityId = annotationGuid;
// erzeuge den Request
AssignRequest assignRequest = new AssignRequest();
assignRequest.Assignee = asignee;
assignRequest.Target = target;
// führe die Zuweisung durch...
try
{
adminService.Execute(assignRequest);
}
catch (Exception e)
{
// [...]
}
adminService.Dispose();
Damit ist nicht nur unser Formular am Server, die Notiz ist auch der richtigen Person zugeordnet. Damit der Projekteigner das Dokument nun öffnen kann, muss unser (ausgefülltes) InfoPath-Formular auf seine Formularvorlage zugreifen können. Dafür müssen wir diese an einen Ort veröffentlichen, auf den alle CRM-Benutzer zugreifen dürfen!
InfoPath Deployment
Zurück in unserem InfoPath Projekt müssen wir zwei Dinge sicherstellen, um eine ausführbare Formularvorlage zu erhalten:
- Wir müssen der Vorlage vertrauen indem wir ihr erlauben, mit „full trust“ ausgeführt zu werden
- Müssen wir die Vorlage mit einem Zertifikat signieren
Beides dürfen wir unter dem Menüpunkt Tools (bzw. Extras)/Formularoptionen. Im Dialogfenster wählen wir den Unterpunkt „Sicherheit und Vertrauensstellung“ und legen beide Optionen fest.
Dann sind wir so weit, unser Formular zu veröffentlichen (Build/Publish (Veröffentlichen)). Das wollen wir an einer Netzwerkadresse tun, die wir als absoluten Dateipfad (hier: c:\inetpub\wwwroot\Vorlagen\InfoPathCrm.xsn) im entsprechenden Dialog angeben. In meinem Fall habe ich ein Unterverzeichnis des wwwroot gewählt, um sicher zu stellen, dass auch Benutzer außerhalb des Serverkontextes ohne weiteres und via http darauf zugreifen können.
Nach Abschluss des Veröffentlichungs-Assistenten können wir auch gleich einmal testen, indem wir unsere Vorlage von https://localhost/Vorlagen/InfoPathCrm.xsn abrufen. Wenn wir nun für ein Projekt, das nicht uns als angemeldeten Benutzer gehört, einen Spesenbericht ausfüllen und auf „Einreichen“ klicken, sollten wir diesen als Notiz beim entsprechenden Projekt finden. Öffnen wir als Projekteigner einen Spesenbericht, der zu einem unserer Projekte von einem anderen Benutzer hinzugefügt wurde, müsste durch klicken auf den Speichern Button des InfoPath-Formulars die Freigabe insofern erfolgen, als dass wir damit einen neuen Spesenbericht in CRM erzeugen.
Workflow in CRM
Zur Abrundung des ganzen habe ich in CRM noch einen Workflow für Notizen definiert, der genau dann startet, wenn eine Annotation zugewiesen wurde und ein Dokument enthält. Sind beide Kriterien erfüllt, wird für den Projekteigner ein Task erzeugt, der auf die Einreichung eines neuen Spesenberichts hinweist.
Abschließende Bemerkungen
Na wenn’s weiter nichts ist? Nun, für den Echt-Betrieb sind sicher an der einen oder anderen Stelle Optimierungen notwendig! Um exemplarisch zu zeigen, wie CRM in InfoPath integriert und InfoPath als Formularbereitsteller für CRM dienen kann, sollte das gezeigte aber ausreichen.
Ähnliches erwarten wir von unserem nächsten Beitrag, in dem wir versuchen werden, CRM in Excel zu integrieren – mit dem Ziel, Abrechnungen für Projekte (und deren Phasen) mehr oder minder automatisch zu erstellen … Bis dann, danke für die Mitarbeit ;)
_____________________________________________________________
Alexander Brandstätter, Microsoft Consulting Services