SharePoint 2010 Workflow mit Visual Studio 2010 und InfoPath 2010 (Part 3)

4. April 2011

Dies ist der dritte und letzte Teil einer kleinen Reihe zu dem Thema SharePoint 2010 Workflows mit Visual Studio 2010 und InfoPath 2010.

Es soll ein Workflow für eine Dokumentenliste einer SharePoint 2010 Site erstellt werden, welcher eine Association Form, eine Initiation Form sowie eine Task Form verwendet. Alle Formulare sollen mit Hilfe des InfoPath Designers 2010 erzeugt werden und in einem Visual Studio 2010 Workflow Projekt verwendet werden. Fachlich handelt es sich auch um einen Freigabeprozess für Dokumente. Dabei soll der Workflow bei der Zuordnung zu einer Liste eine Association Form anzeigen, in der bereits Felder vorbelegt sind. Des Weiteren sollen dann die Daten aus der Association Form an die Initiation Form übergeben werden und ggfs. vom Anwender verändert werden können. Abschließend werden dann die Daten in der Task Form dem Bearbeiter angezeigt.

Ein sehr guter Beitrag zu diesem Thema ist in einer Blogreihe von Reiner Ganser (1st Quad Blog) zu finden. Diese Blogreihe ist eine Schritt für Schritt Anleitung für die Erstellung eines Workflows, allerdings werden in diesem Beispiel für Association und Initiation Form ASPX Seiten verwendet. Das Hauptaugenmerk in meiner dreiteiligen Blogreihe liegt auf dem Datenaustausch zwischen den Formularen und dem Workflow. Ansonsten  sind nur die wesentlichen Schritte beschrieben. Dabei behandeln die Blogbeiträge folgende Themen

  1. Datenübergabe an Association Form
  2. Datenübergabe von Association Form an Initiation Form
  3. Datenaustausch mit dem Workflow und Task Form

Datenaustausch mit dem Workflow und Task Form

Im ersten Teil der Reihe habe ich aufgezeigt wie Datenfelder in einer Association Form über die Metadaten des Workflows vorbelegt werden können. Im zweiten Teil wurden dann die Daten an die Initiation Form weitergereicht. Nun möchte ich im dritten und letzten Schritt zeigen, wie diese Daten in dem Workflow verwendet werden können und wie der Datenaustausch mit einer Task Form erreicht werden kann.

Die Daten der Association Form und der Initiation Form stehen der Workflow-Instanz als Properties AssociationData und InitiationData zur Verfügung, denn im MSDN Artikel How to: Design a Workflow Form to Use Association and Initiation Data heißt es:

“When a workflow instance starts, this data is also passed into the workflow via the AssociationData property of the SPWorkflowActivationProperties object.”

“After the workflow starts, the initiation data is stored in the InitiationData property of the SPWorkflowActivationProperties object returned by the WorkflowProperties property of the OnWorkflowActivated activity.”

Diese beiden Eigenschaften sind vom Typ string und beinhalten XML. Um an die einzelnen Feldinhalte zu gelangen stehen 2 Möglichkeiten zur Verfügung:

1.) Einlesen in ein XmlDocument und Auslesen über XPath-Ausdrücke, wobei die Namespaces beachtet und gegebenenfalls Datenkonvertierungen vorgenommen werden müssen.

2.) Deserialisierung in eine Klasseninstanz, die auf den Schemata der Formulare basiert.

Eine Schritt für Schritt Anleitung der Möglichkeit 2 ist hier How to: Access Association and Initiation Form Data in a Workflow nachzulesen. Anschließend stehen die Informationen typisiert für die Aufgaben des Workflows zur Verfügung.

Fehlt noch der Datenaustausch zwischen dem Workflow und einer Task Form. Eine Task Form kommt zum Einsatz, wenn durch den Workflow eine “Create Task Acitivity” verwendet wird. Möchte man hier eine InfoPath Form verwenden, so wird die InfoPath Form zum Beispiel auf Basis des “Blank Form” Templates erstellt. Da die Form Daten erhalten soll, muss eine Data Connection erstellt werden, die Daten entgegen nehmen kann. Dafür modelliert man sämtliche Daten für den Austausch in einer Datei namens ItemMetadata.xml, die lediglich eine XML Tag namens <z:row xmlns:z=”#RowsetSchema” /> beinhaltet und die für jedes Datenfeld ein Attribute namens “ows_NameDatenfeld” mit sich bringt.

   1: <z:row xmlns:z="#RowsetSchema"

   2:  ows_Instructions=""

   3:  ows_ReviewHints=""

   4:  ows_ReviewComment=""

   5:  ows_ReviewStatus=""

   6:  /> 

Im obigen Bespiel sind die Datenfelder “Instructions”, “ReviewHints”, “ReviewComment” und “ReviewStatus” definiert. Der Präfix “ows_” ist aus historischen Gründen zu verwenden. Die so definierte ItemMetadata.xml ist in der InfoPath Form Data Connection vom Typ “Retrieve data” zu definieren. Sind Felder im InfoPath Formular vorzubelegen, dann kann dies über das Setzen eines Default Values erreicht werden.

image

Nun muss das Formular publiziert (Network Location) werden, die publizierte XSN-Datei unterhalb des Workflows in das Projekt aufgenommen werden und der Deployment Type auf “ElementFile” zu setzen. Zur Verwendung des Formulars ist dann noch die Metadatendatei “Elements.xml” des Workflows an zwei Stellen anzupassen.

   1: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">

   2:   <Workflow

   3:      Name="HowToWorkflow - ReviewWorkflow"

   4:      Description="My SharePoint Workflow"

   5:      Id="64261495-cba6-417c-bc7d-83ec41fd0cec"

   6:      AssociationUrl="_layouts/CstWrkflIP.aspx"

   7:      InstantiationUrl="_layouts/IniWrkflIP.aspx"

   8:      TaskListContentTypeId="0x01080100C9C9515DE4E24001905074F980F93160"

   9:      CodeBesideClass="HowToWorkflow.ReviewWorkflow.ReviewWorkflow"

  10:      CodeBesideAssembly="$assemblyname$">

  11:     <AssociationData>...</AssociationData>

  12:     <MetaData>

  13:       <AssociationCategories>List</AssociationCategories>

  14:       <!-- Tags to specify InfoPath forms for the workflow; delete tags for forms that you do not have -->

  15:       <Association_FormURN>...</Association_FormURN>

  16:       <Instantiation_FormURN>...</Instantiation_FormURN>

  17:       <Task0_FormURN>urn:schemas-microsoft-com:office:infopath:TaskForm:-myXSD-2011-03-07T09-52-14</Task0_FormURN>

  18:       <StatusPageUrl>_layouts/WrkStat.aspx</StatusPageUrl>

  19:     </MetaData>

  20:   </Workflow>

  21: </Elements>

In Zeile 8 wird ein TaskListContentTypeId Attribut auf den Wert “0x01080100C9C9515DE4E24001905074F980F93160” gesetzt und in Zeile 17 wird die URN gesetzt, die im InfoPath Designer über File –> Form Template Properties –> ID ermittelt wird. Die ContentTypeId ist der von SharePoint definierte Wert für Tasks. Das <TaskX_FormURN> Tag verweist auf die URN der zu verwendenden Task Form. Hierbei ist X ein Numerierung, die bei der Create Task Activity eine Rolle spielt. Denn hier wird zum Beispiel codiert:

   1: private void OnCreateReviewTask(object sender, EventArgs e)

   2: {

   3:   XmlSerializer serializer = 

   4:     new XmlSerializer(typeof(SDX.Workflows.myFields));

   5:   XmlTextReader reader = 

   6:     new XmlTextReader(new System.IO.StringReader(workflowProperties.InitiationData));

   7:   SDX.Workflows.myFields initform = 

   8:     (SDX.Workflows.myFields)serializer.Deserialize(reader);

   9:  

  10:   string assignedTo = initform.Reviewer[0].AccountId;

  11:  

  12:   this.createReviewTaskId = Guid.NewGuid();

  13:   this.createReviewTaskProperties.Title = "Review des Dokuments";

  14:   this.createReviewTaskProperties.AssignedTo = assignedTo;

  15:   this.createReviewTaskProperties.DueDate = DateTime.Today.AddDays(5);

  16:   this.createReviewTaskProperties.TaskType = 0; // Nr. des Formulars 

  17:   this.createReviewTaskProperties.ExtendedProperties["Instructions"] 

  18:     = initform.Instructions;

  19:   this.createReviewTaskProperties.ExtendedProperties["ReviewHints"] 

  20:     = initform.ReviewHints;

  21: }

In Zeile 16 wird die Nummer des Formulars verwendet, welches bei der Anzeige des Tasks verwendet werden soll. Die Felder aus der ItemMetadata.xml werden über die Hashtable “ExtendedProperties” gefüllt, wobei der Name des Feldes der Schlüsselwert ist (siehe Zeilen 17 – 20). Entsprechend stehen Werte, die im Formular durch den Anwender und das Formular selbst gesetzt werden, wieder in den ExtendedProperties im Rahmen einer OnTaskChanged Activity in deren AfterProperties wieder zur Verfügung (siehe unten Zeilen 3 und 11).

   1: private void OnReviewTaskChanged(object sender, ExternalDataEventArgs e)

   2: {

   3:   switch (this.onReviewTaskChangedAfterProperties.ExtendedProperties["ReviewStatus"].ToString())

   4:   {

   5:     case "freigegeben":

   6:       this.documentAccepted = true;

   7:       break;

   8:     case "zurückgewiesen":

   9:       this.documentAccepted = false;

  10:       this.reviewerComment

  11:         = this.onReviewTaskChangedAfterProperties.ExtendedProperties["ReviewComment"].ToString();

  12:       break;

  13:     default:

  14:       this.documentAccepted = false;

  15:       break;

  16:   }

  17: }

Fazit

Die Daten der Association Form und der Initiation Form im Workflow stehen über die Properties AssociationData und InitiationData zur Verfügung. Diese können per XPath oder per Deserialisierung ausgelesen werden. Um Daten mit Task Forms auszutauschen bedarf es einer ItemMetadata.xml als Data Connection in der InfoPath Form und der Verwendung der Hashtable ExtendedProperties bei Task Activities.