Freigeben über


Aufrufen der Aktivitätsvalidierung

Die Aktivitätsvalidierung stellt eine Methode bereit, um Fehler in der Konfiguration einer Aktivität vor der Ausführung zu identifizieren und zu melden. Eine Validierung wird ausgeführt, wenn ein Workflow im Workflow-Designer geändert und Validierungsfehler oder -warnungen im Workflow-Designer angezeigt werden. Die Validierung findet auch zur Laufzeit statt, wenn ein Workflow aufgerufen wird. Wenn Validierungsfehler auftreten, löst die Standardvalidierungslogik eine InvalidWorkflowException aus. Windows Workflow Foundation (WF) stellt die ActivityValidationServices-Klasse bereit, mit der Entwickler von Workflowanwendungen und Tools eine Aktivität explizit validieren können. In diesem Thema wird beschrieben, wie Aktivitäten mit dem ActivityValidationServices-Objekt validiert werden.

Verwenden von ActivityValidationServices

ActivityValidationServices verfügt über zwei Validate-Überladungen, mit denen die Validierungslogik einer Aktivität aufgerufen wird. Die erste Überladung akzeptiert die Stammaktivität, die validiert werden soll, und gibt eine Auflistung von Validierungsfehlern und -warnungen zurück. Im folgenden Beispiel wird eine benutzerdefinierte Add-Aktivität verwendet, die über zwei erforderliche Argumente verfügt.

public sealed class Add : CodeActivity<int>  
{  
    [RequiredArgument]  
    public InArgument<int> Operand1 { get; set; }  
  
    [RequiredArgument]  
    public InArgument<int> Operand2 { get; set; }  
  
    protected override int Execute(CodeActivityContext context)  
    {  
        return Operand1.Get(context) + Operand2.Get(context);  
    }  
}  

Die Add-Aktivität wird in einem Sequence-Objekt verwendet, die zwei erforderlichen Argumente werden jedoch nicht gebunden, wie im folgenden Beispiel gezeigt.

Variable<int> Operand1 = new Variable<int>{ Default = 10 };  
Variable<int> Operand2 = new Variable<int>{ Default = 15 };  
Variable<int> Result = new Variable<int>();  
  
Activity wf = new Sequence  
{  
    Variables = { Operand1, Operand2, Result },  
    Activities =
    {  
        new Add(),  
        new WriteLine  
        {  
            Text = new InArgument<string>(env => "The result is " + Result.Get(env))  
        }  
    }  
};  

Dieser Workflow kann durch Aufrufen von Validate überprüft werden. Validate gibt eine Auflistung aller Validierungsfehler und -warnungen zurück, die in der Aktivität selbst oder in ihren untergeordneten Elementen enthalten sind, wie im folgenden Beispiel gezeigt.

ValidationResults results = ActivityValidationServices.Validate(wf);  
  
if (results.Errors.Count == 0 && results.Warnings.Count == 0)  
{  
    Console.WriteLine("No warnings or errors");  
}  
else  
{  
    foreach (ValidationError error in results.Errors)  
    {  
        Console.WriteLine("Error: {0}", error.Message);  
    }  
    foreach (ValidationError warning in results.Warnings)  
    {  
        Console.WriteLine("Warning: {0}", warning.Message);  
    }  
}  

Wenn Validate für diesen Beispielworkflow aufgerufen wird, werden zwei Validierungsfehler zurückgegeben.

Fehler: Für das erforderliche Aktivitätsargument „Operand2“ wurde kein Wert angegeben.
Fehler: Für das erforderliche Aktivitätsargument 'Operand1' wurde kein Wert angegeben. Bei Aufruf dieses Workflows würde ein InvalidWorkflowException-Objekt ausgelöst werden, wie im folgenden Beispiel gezeigt.

try  
{  
    WorkflowInvoker.Invoke(wf);  
}  
catch (Exception ex)  
{  
    Console.WriteLine(ex);  
}  

System.Activities.InvalidWorkflowException:
Beim Verarbeiten der Workflowstruktur sind folgende Fehler aufgetreten:'Hinzufügen': Der Wert für ein erforderliches Aktivitätsargument 'Operand2' wurde nicht angegeben.Hinzufügen': Der Wert für ein erforderliches Aktivitätsargument 'Operand1' wurde nicht angegeben. Damit dieser Beispielworkflow gültig ist, müssen die beiden erforderlichen Argumente der Add Aktivität gebunden sein. Im folgenden Beispiel werden die zwei erforderlichen Argumente zusammen mit dem Ergebniswert an Workflowvariablen gebunden. In diesem Beispiel wird das Result-Argument zusammen mit den zwei erforderlichen Argumenten gebunden. Das Result-Argument muss nicht gebunden werden und verursacht keine Validierungsfehler, wenn es nicht gebunden ist. Es ist die Aufgabe des Workflowautors, das Result-Objekt zu binden, wenn sein Wert noch an einer anderen Stelle im Workflow verwendet wird.

new Add  
{  
    Operand1 = Operand1,  
    Operand2 = Operand2,  
    Result = Result  
}  

Überprüfen der erforderlichen Argumente der Stammaktivität

Wenn die Stammaktivität eines Workflows über Argumente verfügt, werden diese erst gebunden, wenn der Workflow aufgerufen und die Parameter an den Workflow übergeben werden. Deshalb wird der folgende Workflow erfolgreich validiert. Es wird jedoch eine Ausnahme ausgelöst, wenn der Workflow aufgerufen wird, ohne dass die erforderlichen Argumente übergeben werden, wie im folgenden Beispiel gezeigt.

Activity wf = new Add();  
  
ValidationResults results = ActivityValidationServices.Validate(wf);  
// results has no errors or warnings, but when the workflow  
// is invoked, an InvalidWorkflowException is thrown.  
try  
{  
    WorkflowInvoker.Invoke(wf);  
}  
catch (Exception ex)  
{  
    Console.WriteLine(ex);  
}  

System.ArgumentException: Die Argumenteinstellungen der Stammaktivität sind falsch.
Beheben Sie entweder die Workflowdefinition, oder geben Sie Eingabewerte an, um diese Fehler zu beheben:'Hinzufügen': Wert für ein erforderliches Aktivitätsargument 'Operand2' wurde nicht angegeben.'Hinzufügen': Der Wert für ein erforderliches Aktivitätsargument 'Operand1' wurde nicht angegeben. Nachdem die richtigen Argumente übergeben wurden, wird der Workflow erfolgreich abgeschlossen, wie im folgenden Beispiel gezeigt.

Add wf = new Add();  
  
ValidationResults results = ActivityValidationServices.Validate(wf);  
// results has no errors or warnings, and the workflow completes  
// successfully because the required arguments were passed.  
try  
{  
    Dictionary<string, object> wfparams = new Dictionary<string, object>  
    {  
        { "Operand1", 10 },  
        { "Operand2", 15 }  
    };  
  
    int result = WorkflowInvoker.Invoke(wf, wfparams);  
    Console.WriteLine("Result: {0}", result);  
}  
catch (Exception ex)  
{  
    Console.WriteLine(ex);  
}  

Hinweis

In diesem Beispiel wurde die Stammaktivität als Add und nicht wie im vorherigen Beispiel als Activity deklariert. Deshalb kann die WorkflowInvoker.Invoke-Methode eine einzelne ganze Zahl zurückgeben, die die Ergebnisse der Add-Aktivität darstellt und kein Wörterbuch mit out-Argumenten. Die wf-Variable hätte auch als Activity<int> deklariert werden können.

Bei der Validierung von Stammargumenten ist es die Aufgabe der Hostanwendung, sicherzustellen, dass alle erforderlichen Argumente beim Aufruf des Workflows übergeben werden.

Aufrufen der imperativen codebasierten Validierung

Die imperative codebasierte Validierung stellt eine einfache Möglichkeit für eine Aktivität dar, eine Eigenvalidierung bereitzustellen. Dies ist für Aktivitäten verfügbar, die von CodeActivity, AsyncCodeActivity und NativeActivity abgeleitet werden. Der Validierungscode, der sämtliche Validierungsfehler und -warnungen bestimmt, wird der Aktivität hinzugefügt. Wenn die Validierung für die Aktivität aufgerufen wird, sind diese Warnungen oder Fehler in der Auflistung enthalten, die durch den Aufruf von Validate zurückgegeben wurde. Im folgenden Beispiel wird eine CreateProduct -Aktivität definiert. Wenn Cost größer als Price ist, wird den Metadaten in der CacheMetadata-Überschreibung ein Validierungsfehler hinzugefügt.

public sealed class CreateProduct : CodeActivity  
{  
    public double Price { get; set; }  
    public double Cost { get; set; }  
  
    // [RequiredArgument] attribute will generate a validation error
    // if the Description argument is not set.  
    [RequiredArgument]  
    public InArgument<string> Description { get; set; }  
  
    protected override void CacheMetadata(CodeActivityMetadata metadata)  
    {  
        base.CacheMetadata(metadata);  
        // Determine when the activity has been configured in an invalid way.  
        if (this.Cost > this.Price)  
        {  
            // Add a validation error with a custom message.  
            metadata.AddValidationError("The Cost must be less than or equal to the Price.");  
        }  
    }  
  
    protected override void Execute(CodeActivityContext context)  
    {  
        // Not needed for the sample.  
    }  
}  

In diesem Beispiel wird ein Workflow mit der CreateProduct-Aktivität konfiguriert. In diesem Workflow ist Cost größer als Price, und das erforderliche Description-Argument ist nicht festgelegt. Wenn die Validierung aufgerufen wird, werden die folgenden Fehler zurückgegeben.

Activity wf = new Sequence  
{  
    Activities =
    {  
        new CreateProduct  
        {  
            Cost = 75.00,  
            Price = 55.00  
            // Cost > Price and required Description argument not set.  
        },  
        new WriteLine  
        {  
            Text = "Product added."  
        }  
    }  
};  
  
ValidationResults results = ActivityValidationServices.Validate(wf);  
  
if (results.Errors.Count == 0 && results.Warnings.Count == 0)  
{  
    Console.WriteLine("No warnings or errors");  
}  
else  
{  
    foreach (ValidationError error in results.Errors)  
    {  
        Console.WriteLine("Error: {0}", error.Message);  
    }  
    foreach (ValidationError warning in results.Warnings)  
    {  
        Console.WriteLine("Warning: {0}", warning.Message);  
    }  
}  

Fehler: Die Kosten müssen kleiner oder gleich dem Preis sein.
Fehler: Für das erforderliche Aktivitätsargument 'Description' wurde kein Wert angegeben.

Hinweis

Autoren benutzerdefinierter Aktivitäten können in der CacheMetadata-Überschreibung einer Aktivität Validierungslogik bereitstellen. Von CacheMetadata ausgelöste Ausnahmen werden nicht als Validierungsfehler behandelt. Diese Ausnahmen werden im Aufruf von Validate nicht verarbeitet und müssen vom Aufrufer behandelt werden.

Verwenden von ValidationSettings

Standardmäßig werden alle Aktivitäten in der Aktivitätsstruktur ausgewertet, wenn die Validierung durch ActivityValidationServices aufgerufen wird. Mit ValidationSettings kann die Validierung auf unterschiedliche Weise angepasst werden, indem die zugehörigen drei Eigenschaften konfiguriert werden. SingleLevel gibt an, ob das Validierungssteuerelement die gesamte Aktivitätsstruktur durchlaufen oder nur Validierungslogik auf die angegebene Aktivität anwenden soll. Der Standardwert ist false. AdditionalConstraints gibt zusätzliche Einschränkungszuordnungen eines Typs für eine Liste von Einschränkungen an. Es gibt für den Basistyp jeder Aktivität in der Aktivitätsstruktur, die validiert wird, eine Suche in AdditionalConstraints. Wenn eine übereinstimmende Einschränkungsliste gefunden wird, werden alle Einschränkungen in der Liste für die Aktivität ausgewertet. OnlyUseAdditionalConstraints gibt an, ob das Validierungssteuerelement alle Einschränkungen oder nur die in AdditionalConstraints angegebenen Einschränkungen auswerten soll. Standardwert: false. AdditionalConstraints und OnlyUseAdditionalConstraints sind nützlich, wenn Workflowhostautoren zusätzliche Validierung für Workflows hinzufügen möchten, z. B. Richtlinieneinschränkungen für Tools wie FxCop. Weitere Informationen zu Einschränkungen finden Sie unter Deklarative Einschränkungen.

Um ValidationSettings zu verwenden, konfigurieren Sie die gewünschten Eigenschaften, und übergeben Sie diese in den Aufruf von Validate. In diesem Beispiel wird ein Workflow überprüft, der aus einem Sequence- Objekt mit einer benutzerdefinierten Add-Aktivität besteht. Die Add-Aktivität verfügt über zwei erforderliche Argumente.

public sealed class Add : CodeActivity<int>  
{  
    [RequiredArgument]  
    public InArgument<int> Operand1 { get; set; }  
  
    [RequiredArgument]  
    public InArgument<int> Operand2 { get; set; }  
  
    protected override int Execute(CodeActivityContext context)  
    {  
        return Operand1.Get(context) + Operand2.Get(context);  
    }  
}  

Die folgende Add-Aktivität wird in einem Sequence-Objekt verwendet, die zwei erforderlichen Argumente werden jedoch nicht gebunden.

Variable<int> Operand1 = new Variable<int> { Default = 10 };  
Variable<int> Operand2 = new Variable<int> { Default = 15 };  
Variable<int> Result = new Variable<int>();  
  
Activity wf = new Sequence  
{  
    Variables = { Operand1, Operand2, Result },  
    Activities =
    {  
        new Add(),  
        new WriteLine  
        {  
            Text = new InArgument<string>(env => "The result is " + Result.Get(env))  
        }  
    }  
};  

Im folgenden Beispiel wird die Validierung ausgeführt, während SingleLevel auf true festgelegt ist, sodass nur die Sequence-Stammaktivität validiert wird.

ValidationSettings settings = new ValidationSettings  
{  
    SingleLevel = true  
};  
  
ValidationResults results = ActivityValidationServices.Validate(wf, settings);  
  
if (results.Errors.Count == 0 && results.Warnings.Count == 0)  
{  
    Console.WriteLine("No warnings or errors");  
}  
else  
{  
    foreach (ValidationError error in results.Errors)  
    {  
        Console.WriteLine("Error: {0}", error.Message);  
    }  
    foreach (ValidationError warning in results.Warnings)  
    {  
        Console.WriteLine("Warning: {0}", warning.Message);  
    }  
}  

In diesem Code wird die folgende Ausgabe angezeigt:

Keine Warnungen oder FehlerDie Validierung ist auch dann erfolgreich, wenn die erforderlichen Argumente der Add-Aktivität nicht gebunden sind, da nur die Stammaktivität ausgewertet wird. Diese Art der Validierung ist nützlich, wenn nur bestimmte Elemente in einer Aktivitätsstruktur validiert werden, z. B. bei der Validierung einer Eigenschaftenänderung einer einzelnen Aktivität in einem Designer. Beachten Sie, dass beim Aufrufen dieses Workflows die vollständige Validierung, die im Workflow konfiguriert ist, ausgewertet wird, und dass InvalidWorkflowException ausgelöst würde. Mit ActivityValidationServices und ValidationSettings wird nur eine Validierung konfiguriert, die explizit vom Host aufgerufen wurde, und keine Validierung, die beim Aufruf eines Workflows auftritt.