Dieser Artikel beschreibt schnell die Schritte, die Sie ausführen müssen, um die Unterstützung für die Windows Workflow Foundation (WF) in ASP.NET (Classic oder MVC) zu ermöglichen. Lassen Sie uns eine sehr kleine Demo -Anwendung verwenden, um Ihnen zu zeigen, wie Sie dies tun können.
Das Integrieren von WF in ASP.NET war etwas, das ich in den letzten Projekten machen musste, an denen ich gearbeitet habe. Deshalb dachte ich, ich würde eine kleine Beispielanwendung erstellen, die Ihnen das nötige Minimum an Code zeigt, der erforderlich ist, um dies zu erreichen. Erstellen wir Schritt für Schritt eine Beispielanwendung ...
Bemerkung : Dieser Artikel ist keine Grundierung auf WF. Ein grundlegendes Verständnis von WF ist erforderlich.
Starten Sie SQL Server Management Studio und erstellen Sie eine neue Datenbank namens "Workflow". Sie müssen ein paar Tabellen und Logik (gespeicherte Verfahren und dergleichen) erstellen, um die Persistenz für WF zu unterstützen. Im Verzeichnis "C: Windows Microsoft.net Framework V3.0 Windows Workflow Foundation SQL en" finden Sie 4 SQL -Dateien. Führen Sie die folgenden zwei in dieser Reihenfolge aus:
Dadurch werden zwei Tabellen und 10 gespeicherte Prozeduren erstellt, die erforderlich sind, um die Persistenz für WF in einer SQL -Server -Datenbank zu unterstützen. Laden Sie nun den Quellcode für diesen Artikel herunter, extrahieren Sie ihn und führen Sie das DDL.SQL -Skript aus. Dieses Skript erstellt eine Tabelle namens Customer.
Sie sollten mit einer Datenbankstruktur enden, die so aussieht:
Abbildung 1 - Workflow -Datenbank

Wenn Sie die Beispiellösung dieses Artikels öffnen, finden Sie ein Code -Bibliotheksprojekt namens "Datenbank". Alles, was es enthält, ist eine LINQ -für SQL -Klassendatei, die eine Entität enthält, nämlich Kunde.
Abbildung 2 - Kundeneinheit

Mit der Beispielanwendung können Sie Kunden erstellen. Alles, was Sie tun müssen, ist einen Benutzernamen einzugeben. Danach wird ein neuer Workflow gestartet und Sie können den Kunden genehmigen, ihn ablehnen oder nichts tun. Wenn Sie keine Maßnahmen ergreifen, wird der Kunde nach einer bestimmten Auszeit gelöscht.
Abbildung 3 - Der Workflow

In dieser Stichprobe gibt es einen Zustandsmaschinenworkflow. Für einen solchen Workflow müssen Sie einen Anfang und einen abgeschlossenen Zustand anbieten. Wie Sie in der obigen Abbildung sehen können, enthält sie nur zwei Zustände, die angemessen benannt sind.
Dieser Workflow erfordert einen Parameter namens Benutzername. Wenn es in den Anfangszustand eintrifft, wird die staateinitialisierende Aktivität ausgeführt und ein neuer Kunde erstellt und in der Kundentabelle fortgesetzt. Standardmäßig benötigen alle Kunden die Genehmigung.
Abbildung 4 - Kunden, die auf die Genehmigung warten

Ich habe diesen Workflow in ein separates Projekt eingefügt.
Abbildung 5 - Die Lösung

Wenn die staateinitialisierende Aktivität die Ausführung des Workflows beendet hat, hört sich eines von 3 möglichen Ereignissen an:
Das Timeout -Ereignis basiert auf einer Verzögerung. Sie müssen dieses Ereignis nicht selbst abfeuern, aber Sie sind verantwortlich für die Entlassung der beiden anderen Ereignisse. Deshalb habe ich einen lokalen Dienst erstellt.
Listing 1 - IcustomerService -Schnittstelle
[ ExternalDataExchange ]
public interface ICustomerService
{
event EventHandler < ExternalDataEventArgs > Approved ;
event EventHandler < ExternalDataEventArgs > Rejected ;
}Sie können nur eine Implementierung für einen lokalen Service in der Workflow -Laufzeit registrieren, und die Implementierung für den Customerservice sieht Folgendes aus:
Listing 2 - Customerservice
public class CustomerService : ICustomerService
{
public event EventHandler < ExternalDataEventArgs > Approved ;
public event EventHandler < ExternalDataEventArgs > Rejected ;
private bool FireEvent ( EventHandler < ExternalDataEventArgs > theEvent , ExternalDataEventArgs args )
{ //...}
public bool OnApproved ( Guid instanceId )
{
return FireEvent ( Approved , new ExternalDataEventArgs ( instanceId ) ) ;
}
public bool OnRejected ( Guid instanceId )
{
return FireEvent ( Rejected , new ExternalDataEventArgs ( instanceId ) ) ;
}
}Mit diesem lokalen Service können Sie das genehmigte oder abgelehnte Ereignis auslösen, indem Sie die Instanz -ID (Richtlinie) des Workflows angeben, die Sie weiter ausführen möchten.
Es ist nicht viel Logik, Kunden zu erstellen, zu genehmigen oder abzulehnen, aber ich habe alle in der Kundendienstklasse eingerichtet. Die Methoden sind selbsterklärend. Mit dieser Klasse können Sie eine Liste aller Kunden abrufen, neue Kunden hinzufügen, Kunden genehmigen, ablehnen und löschen.
Listing 3 - CustomerManager -Klasse
public class CustomerManager
{
public IEnumerable < Customer > GetCustomers ( ) { //... }
public Customer GetCustomerById ( Guid customerId ) { //... }
public void ApproveCustomer ( Guid customerId ) { //... }
public void RejectCustomer ( Guid customerId ) { //... }
public void DeleteCustomer ( Guid customerId ) { //... }
public void AddCustomer ( Guid customerId , string userName ) { //... }
}Der Workflow verwendet diesen CustomerManager -Typ, um die gesamte Arbeit auszuführen.
Voila, die Fundamente sind festgelegt. Sie haben eine Datenbank eingerichtet, die die WF -Persistenz unterstützt, einen Workflow zum Erstellen, Genehmigung und Ablehnen von Kunden erstellt und einen lokalen Service erstellt hat, der Ihnen bei der Anweisung Ihrer Workflow -Instanzen hilft, was zu tun ist.
Lassen Sie uns eine neue ASP.NET -Webanwendung erstellen, mit der all dies funktioniert. Ich habe den ursprünglichen Namen "WebApplication" für das ASP.NET -Projekt erstellt.
Abbildung 6 - Webapplication -Projekt

Die Website enthält nur eine Seite namens default.aspx. Auf dieser Seite werden eine Liste von Kunden angezeigt, ermöglicht es Ihnen, neue Kunden hinzuzufügen und vorhandene zu genehmigen oder abzulehnen.
Abbildung 7 - Standard.aspx Seite

Konfigurieren wir die Webanwendung so, dass sie WF unterstützt. Der in diesem Artikel gezeigte Konfigurationscode wird zur Lesbarkeit abgekürzt. Laden Sie den Beispielquellcode für die Vollversion herunter.
Öffnen Sie Ihre Anwendungskonfigurationsdatei (web.config) und fügen Sie den Abschnitt ConfigSactions die folgende Zeile hinzu.
< configSections >
<!-- ... -->
< section name = " WorkflowRuntime "
type = " System.Workflow.Runtime.Configuration.WorkflowRuntimeSection...etc. " />
</ configSections >Sie müssen diese Zeile dem Konfigurationsknoten hinzufügen, damit .NET weiß, dass sie den WorkflowRuntIMEction -Typ verwenden muss, um das folgende Bit der Konfiguration zu lesen, das Sie dem Konfigurationsknoten hinzufügen müssen.
< WorkflowRuntime >
< CommonParameters >
< add name = " ConnectionString " value = " your connection string " />
</ CommonParameters >
< Services >
< add type = " System.Workflow.Runtime.Hosting.ManualWorkflowSchedulerService,...etc. "
useActiveTimers = " true " />
< add type = " System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService,...etc. "
UnloadOnIdle = " true " LoadIntervalSeconds = " 5 " />
</ Services >
</ WorkflowRuntime >Der Workflowruntime -Knoten lädt die Handbuch -Workflowsschsplanungsservice- und SQLWORKFlowPersistenceservice -Dienste für die Workflow -Laufzeit. Sie müssen den SQLWORKFLOWPERSISTENCESVICE laden, wenn Sie Ihre Workflows bestehen möchten, und für ASP.NET ist es ratsam, den Manual WorkFlowsSchedulerService anstelle des StandardsWorkFlowSchedulerService -Dienstes zu verwenden.
Jede Workflow -Instanz führt in einem separaten Thread aus. Die Workflow -Laufzeit verwaltet dies mit einem Workflow -Scheduler -Dienst. Standardmäßig verwendet die Laufzeit den Standard -WorkFlowSchedulerService -Typ. Alle Workflow -Instanzen werden asynchron ausgeführt.
Für ASP.NET ist es am besten, den Manual WorkFlowSchedulerService zu verwenden, da Sie Workflows synchron ausführen können. Die Workflow -Laufzeit verwendet in diesem Fall den aufrufenden Thread aus der Host -Anwendung.
Auf diese Weise können Sie auf eine Antwort vom Workflow warten, bevor ASP.NET eine Antwort sendet. Natürlich ist es nicht ratsam, in diesem Fall langlebige Aufgaben in Ihren Workflows auszuführen. (PS: Weitere Informationen zu diesem Thema finden Sie in diesem Blog -Beitrag.)
Stellen Sie bei Verwendung des Manual WorkFlowSchedulerService sicher, dass Sie die Eigenschaft Useactivetimers auf true einstellen. Wenn Sie diese Einstellung auf ihren Standardwert von FALSCH einstellen lassen, werden alle Verzögerungsaktivitäten nach Ablauf der Ablauf nicht automatisch wieder aufgenommen. Wenn die Workflow-Laufzeit eingestellt ist, wird ein Timer in Memory verwendet, um regelmäßig nach abgelaufenen Verzögerungen zu überprüfen.
Nachdem Ihre Anwendung auf der Nutzung der Workflow Foundation konfiguriert wurde, müssen Sie die Workflow -Laufzeit hosten.
In ASP.NET ist der ideale Ort dafür in der global.asax -Datei. Fügen Sie einfach den folgenden Code zum Ereignishandler von Application_Start (...) hinzu.
Listing 4 - global.asax application_start
protected void Application_Start ( object sender , EventArgs e )
{
WorkflowRuntime runtime = new WorkflowRuntime ( "WorkflowRuntime" ) ;
ExternalDataExchangeService exchangeService = new ExternalDataExchangeService ( ) ;
runtime . AddService ( exchangeService ) ;
CustomerService customerService = new CustomerService ( ) ;
exchangeService . AddService ( customerService ) ;
runtime . StartRuntime ( ) ;
Application [ "WorkflowRuntime" ] = runtime ;
}Eine neue Instanz des Workflowruntime wird erstellt, dann wird der ExternaldataExchangeService erstellt und zur Laufzeit hinzugefügt. Als nächstes erstellen wir eine Instanz unseres lokalen Service IcustomerService und fügen sie zur Instanz von ExternaldataExchangeservice hinzu. Schließlich wird die Laufzeit gestartet und im Zustand der Anwendung gespeichert.
Ebenso müssen Sie die Workflow -Laufzeit stoppen, wenn die Anwendung wie in Listing 5 gezeigt endet.
Listing 5 - Global.asax Application_end
protected void Application_End ( object sender , EventArgs e )
{
WorkflowRuntime runtime = Application [ "WorkflowRuntime" ] as WorkflowRuntime ;
if ( runtime != null )
{
runtime . StopRuntime ( ) ;
runtime . Dispose ( ) ;
}
} Wenn Sie auf die Schaltfläche Hinzufügen klicken, müssen Sie einen neuen Workflow starten. Bei Verwendung des Manual WorkFlowsSchedulerService haben Sie die totale Kontrolle über die Ausführung Ihrer Workflow -Instanzen. In Listing 6 können Sie feststellen, dass Sie diese Schritte ausführen müssen:
Listing 6 - Erstellen Sie einen neuen Kunden
WorkflowRuntime runtime = ( WorkflowRuntime ) Application [ "WorkflowRuntime" ] ;
Dictionary < string , object > arguments = new Dictionary < string , object > ( ) ;
arguments . Add ( "UserName" , txtUserName . Text . Trim ( ) ) ;
WorkflowInstance workflow = runtime . CreateWorkflow ( typeof ( CustomerApprovalWorkflow ) , arguments ) ;
workflow . Start ( ) ;
ManualWorkflowSchedulerService scheduler =
( ManualWorkflowSchedulerService ) runtime . GetService ( typeof ( ManualWorkflowSchedulerService ) ) ;
scheduler . RunWorkflow ( workflow . InstanceId ) ; Nachdem Sie einen Kunden erstellt haben, können Sie sein Konto genehmigen oder ablehnen. Mit anderen Worten, Sie müssen den Workflow fortsetzen, der mit seinem Konto gestartet wurde.
Der in Auflistung 7 angezeigte Code ähnelt dem der Auflistung 6. Der einzige Unterschied besteht darin, dass Sie die Instanz Ihres lokalen Service (Customerservice) abrufen und die von der Methode (...) angegebene Methode anrufen müssen. Die nicht anerkannte Methode löst das genehmigte Ereignis aus. Nach erfolgreicher Lieferung können Sie den Scheduler anweisen, den Workflow weiter auszuführen.
Listing 7 - Genehmigen Sie einen Kunden
WorkflowRuntime runtime = ( WorkflowRuntime ) Application [ "WorkflowRuntime" ] ;
ManualWorkflowSchedulerService scheduler =
( ManualWorkflowSchedulerService ) runtime . GetService ( typeof ( ManualWorkflowSchedulerService ) ) ;
CustomerService customerService = ( CustomerService ) runtime . GetService < ICustomerService > ( ) ;
if ( customerService . OnApproved ( customerId ) )
{
scheduler . RunWorkflow ( customerId ) ;
}Das Ablehnen eines Kundenkontos ist ähnlich. Sie müssen das abgelehnte Ereignis nur anstelle des genehmigten Ereignisses senden. Wenn Sie keine Maßnahmen ergreifen, wird die Verzögerung nach einer Minute ausgelöst und das Konto des Kunden wird automatisch gelöscht.
Und das ist alles, was es gibt.