Manche Leute sehen SharePoint einfach gesagt als Datenspeicher mit einem Web-Frontend. Das stimmt soweit: denn die Datenspeicherung mit den Listen und Document Libraries ist elegant gelöst und das Aussehen des konfortablen ASP .NET 2.0 User Interfaces kann hervorragend an Kundenwünsche angepasst werden.
Dadurch ist man versucht, die Anforderungen an SharePoint hoch anzusetzen: Man könnte ja fortan jede datenzentrische Applikation mit SharePoint implementieren. Das User Interface, das man vorher umständlich selber entwickeln musste, gibt es nun quasi "gratis" mitgeliefert.
SharePoint darf jedoch nicht auf die gleiche Stufe wie ein relationales Datenbanksystem gestellt werden. SharePoint benutzt zwar unter der Haube den MS SQL Server um Daten zu speichern, gibt aber die "Datenbank-Features", wie etwa die referentielle Integrität, nicht weiter. Was in den SharePoint Listen eindeutig fehlt sind Constraints (z.Bsp. Unique Key Constraints) und Fremdschlüssel.
Fazit: Mit den Bordmitteln von SharePoint können wir keine Eindeutigkeit und keine referentielle Integrität garantieren.
Dies wurde mit heute (anlässlich der TechEd in Barcelona) von den beiden SharePoint Profis Ben Robb (cScape) und Jan Tielens (u2u) bestätigt.
Die Lösung dieses Problems ist naheliegend, denn SharePoint ist mit seinem Objektmodell gut erweiterbar: das Mittel heisst Events. Mit den vorbereiteten Event Receivern, z.Bsp. der SPItemEventReceiver Klasse, können synchron Events abgefangen, ausgewertet und wenn nötig abgebrochen werden, denn das übergebene properties Argument enthält ein Cancel Property.
Wir haben keine Wahl: wir müssen die Lücke selber füllen und können nur hoffen, dass Microsoft unser Anliegen kennt und in der nächsten SharePoint Version eine Lösung anbietet.
Es gibt diese frustrierenden Momente wo man einen Workflow einfach nicht zum Laufen bringt. Man glaubt alles korrekt eingestellt zu haben: die beiden Deployment Files: feature.xml und workflow.xml wurden schon tausend Mal kontrolliert, der Workflow Designer in Visual Studio 2005 zeigt keine Fehler, alle Tasks werden im Code korrekt erstellt, die InfoPath Formulare sind bereit und die Class Library kompiliert.
Und trotzdem beendet sich der Workflow zur Laufzeit kurz nach der Initialisierung. Erster Anlaufpunkt ist die Workflow History Liste. Nichts. Dann die Event-Logs. Nichts. Schlussendlich wird man in den SharePoint Logs (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\LOGS) fündig: Sucht man nach "Workflow Infrastructure" finden sich einige Fehler in der Log-Datei. Beispielsweise: System.InvalidOperationException: The event receiver context for Workflow is invalid.
Diesen Text kopiert; in Google Groups eingefügt und los geht's mit der Suche. Beim Duchsehen der Resultate werde ich auf einen Eintrag im MSDN Forum von Microsoft aufmerksam: "The issue with the correlation token, the correlation token for the task needs to be different from the workflow!! Remember this guys, and avoid the turmoil ive been through."
Vermutlich wird in jedem SharePoint Workflow Buch x- Mal darauf hingewiesen und doch geht dieser Punkt immer wieder vergessen: Der "CorrelationToken" des Workflows darf nicht für die Tasks (wieder-) verwendet werden!
Die einfache Lösung des Problems: Einfach für jeden Task einen neuen CorrelationToken definieren oder in dem bestehenden Workflow den Wert mit einem neuen Text überschreiben. That's it...
Wird in Visual Studio 2005 in einem SharePoint Workflow Projekt über den Workflow Designer (siehe Referenzen) mit Hilfe der CreateTask Aktivität ein neuer Task erstellt, müssen im Source Code die TaskId und die TaskProperties gesetzt werden:
taskId = Guid.NewGuid();
taskProperties.Title = "my Title";
taskProperties.Description = "my Description";
taskProperties.AssignedTo = "Administrator";
taskProperties.PercentComplete = 0;
taskProperties.StartDate = DateTime.Today;
taskProperties.DueDate = DateTime.Today.AddDays(2);
taskProperties.ExtendedProperties["Instructions"] = "my Instructions ";
Wird zum Beispiel ein InfoPath Formular verwendet um den Task zu editieren, kann über die ExtendedProperties HashTable Werte (z.B. Instructions) an das Formular übergeben werden. Sind diese Werte leer (null) wird folgender Fehler in der Workflow History geloggt:
User ID: 'System Account'
Outcome: 'mscorlib'
Description: 'Exception has been thrown by the target of an invocation.'
Data:
at System.RuntimeMethodHandle._InvokeMethodFast(Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeTypeHandle typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.Workflow.Activities.CallExternalMethodActivity.Execute(ActivityExecutionContext executionContext)
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)
at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)
at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)
at System.Workflow.Runtime.Scheduler.Run()
Dieser nichts sagende Fehler kann vermieden werden, indem der ExtendedProperties HashTable keine null Werte übergeben werden!
Referenzen:
-
Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation) -->
Download
-
Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions -->
Download
Gerade im Zusammenhang mit SharePoint Workflows ist es unabdingbar, dass sich die Workflow Variablen serialisieren lassen, weil sich der Workflow ab und zu schlafen legt (Serialisierung der Variablen), bis ein gewisses Ereignis, beispielsweise das Abschliessen einer Aufgabe, eintritt und der Workflow fortgeführt wird (Deserialisierung der Variablen).
Microsoft gibt uns zwar mit den Workflow Properties (SPWorkflowActivationProperties) ein Objekt in die Hand, das von der Ereignis Aktivität OnWorkflowActivated abgefüllt wird. Wir müssen uns nicht um die Serialisierung der Properties (wie Site, Web, List, Item) kümmern. Dies wird automatisch für uns gemacht.
Wenn wir nun aber in unserem Workflow eine weitere Variable vom Typ SPListItem benötigen, die nicht über die Workflow Properties erreichbar ist, müssen wir selber dafür sorgen, dass die Variable beim Fortführen des Workflows korrekt initialisiert wird. Dazu ein kleiner Code Ausschnitt:
public int ItemID = -1;
[NonSerialized()]
private SPListItem _item;
public SPListItem DuplicateItem
{
get
{
if (_item == null && ItemID != -1)
_item = LoadListItem(ItemID); // ToDo: Implement LoadListItem()
return _item;
}
set
{
_item = value;
if (_item != null)
ItemID = _item.ID;
}
}
Zuerst benötigen wir eine Integer Variable ItemID für die eindeutige Identifikation des Items. Um die Serialisierung dieser Variable brauchen wir uns nicht zu kümmern.
Danach deklarieren wir eine private Variable _item vom Typ SPListItem, die das List Item zur Laufzeit zur Verfügung stellt, die aber nicht serialisierbar ist. Darum wird die Variable mit dem NonSerialized Attribut dekoriert.
Schlussendlich müssen wir noch eine Property Item implementieren, die bei Bedarf das List Item nachlädt (nämlich genau dann, wenn der Workflow fortgeführt wird und alle Variablen deserialisert werden). Zu diesem Zweck muss noch die LoadListItem Funktion implementiert werden, die anhand der List Item ID ein List Item zurückgibt.
SharePoint zeigt nirgends eine Liste mit der Workflow History.
Dabei gibt es diese auf Stufe Site; Sie wird nur nicht angezeigt (auch nicht in All Site Content).
Die URL lautet: http://localhost/Lists/Workflow%20History
Diese Liste zeigt die Spalte Data, die normalerweise in der Workflow History nicht zu finden ist.
Data kann in eigenen Visual Studio 2005 Workflows benutzt werden, um Texte oder Fehlermeldungen anzuzeigen, die in Outcome und Description nicht Platz finden (diese beiden sind auf 256 Zeichen limitiert).
Aktivität: LogToHistoryListActivity. Eigenschaft: OtherData.