Überprüfung in Enterprise-Apps

Hinweis

Dieses eBook wurde im Frühjahr 2017 veröffentlicht und wurde seitdem nicht aktualisiert. Es gibt viel in dem Buch, das wertvoll bleibt, aber einige der Materialien sind veraltet.

Jede App, die Eingaben von Benutzern akzeptiert, sollte sicherstellen, dass die Eingabe gültig ist. Eine App könnte beispielsweise auf Eingaben prüfen, die nur Zeichen in einem bestimmten Bereich enthalten, eine bestimmte Länge haben oder einem bestimmten Format entsprechen. Ohne Validierung kann ein Benutzer Daten bereitstellen, die dazu führen, dass die App fehlschlägt. Die Überprüfung erzwingt Geschäftsregeln und verhindert, dass ein Angreifer schädliche Daten eingibt.

Im Kontext des MVVM-Musters (Model-View-ViewModel) ist häufig ein Ansichtsmodell oder Modell erforderlich, um die Datenvalidierung durchzuführen und alle Validierungsfehler an die Ansicht zu melden, damit der Benutzer sie korrigieren kann. Die mobile eShopOnContainers-App führt eine synchrone clientseitige Überprüfung der Ansichtsmodelleigenschaften durch und benachrichtigt den Benutzer über Überprüfungsfehler, indem das Steuerelement hervorgehoben wird, das die ungültigen Daten enthält, und durch Anzeigen von Fehlermeldungen, die den Benutzer darüber informieren, warum die Daten ungültig sind. Abbildung 6-1 zeigt die Klassen, die an der Überprüfung in der mobilen eShopOnContainers-App beteiligt sind.

Validierungsklassen in der mobilen eShopOnContainers-App

Abbildung 6-1: Validierungsklassen in der mobilen eShopOnContainers-App

Ansichtsmodelleigenschaften, die eine Validierung erfordern, sind vom Typ ValidatableObject<T>, und jede ValidatableObject<T>-Instanz verfügt über Validierungsregeln, die ihrer Validations-Eigenschaft hinzugefügt wurden. Die Überprüfung wird aus dem Ansichtsmodell aufgerufen, indem die Validate Methode der ValidatableObject<T> Instanz aufgerufen wird, die die Gültigkeitsprüfungsregeln abruft und für die ValidatableObject<T> Value Eigenschaft ausgeführt wird. Alle Überprüfungsfehler werden in die Errors Eigenschaft der ValidatableObject<T> Instanz eingefügt, und die IsValid Eigenschaft der ValidatableObject<T> Instanz wird aktualisiert, um anzugeben, ob die Überprüfung erfolgreich war oder fehlgeschlagen ist.

Eigenschaftsänderungsbenachrichtigungen werden von der ExtendedBindableObject-Klasse bereitgestellt. Daher kann ein Entry-Steuerelement an die IsValidEigenschaft der ValidatableObject<T>-Instanz in der Ansichtsmodellklasse gebunden werden, um benachrichtigt zu werden, ob die eingegebenen Daten gültig sind.

Angeben von Gültigkeitsregeln

Validierungsregeln werden durch Erstellen einer Klasse angegeben, die von der IValidationRule<T>-Schnittstelle abgeleitet wird, was im folgenden Codebeispiel gezeigt wird:

public interface IValidationRule<T>  
{  
    string ValidationMessage { get; set; }  
    bool Check(T value);  
}

Diese Schnittstelle gibt an, dass eine Gültigkeitsprüfungsregelklasse eine boolean Check Methode bereitstellen muss, die zum Ausführen der erforderlichen Überprüfung verwendet wird, und eine ValidationMessage Eigenschaft, deren Wert die Überprüfungsfehlermeldung ist, die angezeigt wird, wenn die Überprüfung fehlschlägt.

Das folgende Codebeispiel zeigt die IsNotNullOrEmptyRule<T> Gültigkeitsprüfungsregel, die verwendet wird, um die Überprüfung des Benutzernamens und kennworts durchzuführen, der vom Benutzer LoginView bei verwendung von simulierten Diensten in der mobilen eShopOnContainers-App eingegeben wird:

public class IsNotNullOrEmptyRule<T> : IValidationRule<T>  
{  
    public string ValidationMessage { get; set; }  

    public bool Check(T value)  
    {  
        if (value == null)  
        {  
            return false;  
        }  

        var str = value as string;  
        return !string.IsNullOrWhiteSpace(str);  
    }  
}

Die Check Methode gibt einen boolean Wert zurück, der angibt, ob das Wertargument leer ist nulloder nur aus Leerzeichen besteht.

Obwohl nicht von der mobilen eShopOnContainers-App verwendet wird, zeigt das folgende Codebeispiel eine Gültigkeitsprüfungsregel für die Überprüfung von E-Mail-Adressen:

public class EmailRule<T> : IValidationRule<T>  
{  
    public string ValidationMessage { get; set; }  

    public bool Check(T value)  
    {  
        if (value == null)  
        {  
            return false;  
        }  

        var str = value as string;  
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");  
        Match match = regex.Match(str);  

        return match.Success;  
    }  
}

Die Check Methode gibt einen boolean Wert zurück, der angibt, ob das Wertargument eine gültige E-Mail-Adresse ist. Dies wird erreicht, indem das Wertargument nach dem ersten Vorkommen des im Regex-Konstruktor angegebenen Musters für reguläre Ausdrücke durchsucht wird. Gibt an, ob das Muster für reguläre Ausdrücke in der Eingabezeichenfolge gefunden wurde, indem der Wert der Eigenschaft des Match Objekts Success überprüft wird.

Hinweis

Die Validierung von Eigenschaften kann manchmal abhängige Eigenschaften umfassen. Ein Beispiel für abhängige Eigenschaften ist, wenn die Menge der gültigen Werte für Eigenschaft A von dem bestimmten Wert abhängt, der in Eigenschaft B festgelegt wurde. Um zu prüfen, ob der Wert von Eigenschaft A einer der zulässigen Werte ist, müsste der Wert von Eigenschaft B abgerufen werden. Wenn sich der Wert von Eigenschaft B ändert, müsste außerdem die Eigenschaft A erneut validiert werden.

Hinzufügen von Gültigkeitsregeln zu einer Eigenschaft

In der mobilen eShopOnContainers-App werden Ansichtsmodelleigenschaften, die eine Überprüfung erfordern, als Typ ValidatableObject<T>deklariert. T Dabei handelt es sich um den Typ der zu überprüfenden Daten. Das folgende Codebeispiel zeigt ein Beispiel für zwei solcher Eigenschaften:

public ValidatableObject<string> UserName  
{  
    get  
    {  
        return _userName;  
    }  
    set  
    {  
        _userName = value;  
        RaisePropertyChanged(() => UserName);  
    }  
}  

public ValidatableObject<string> Password  
{  
    get  
    {  
        return _password;  
    }  
    set  
    {  
        _password = value;  
        RaisePropertyChanged(() => Password);  
    }  
}

Damit die Überprüfung ausgeführt wird, müssen der Validations Auflistung jeder ValidatableObject<T> Instanz Gültigkeitsprüfungsregeln hinzugefügt werden, wie im folgenden Codebeispiel gezeigt:

private void AddValidations()  
{  
    _userName.Validations.Add(new IsNotNullOrEmptyRule<string>   
    {   
        ValidationMessage = "A username is required."   
    });  
    _password.Validations.Add(new IsNotNullOrEmptyRule<string>   
    {   
        ValidationMessage = "A password is required."   
    });  
}

Diese Methode fügt die IsNotNullOrEmptyRule<T>-Validierungsregel der Validations-Sammlung jeder ValidatableObject<T>-Instanz hinzu und gibt Werte für die ValidationMessage-Eigenschaft der Validierungsregel an, die die Validierungsfehlermeldung angibt, die angezeigt wird, wenn die Validierung fehlschlägt.

Auslösen der Überprüfung

Der in der mobilen eShopOnContainers-App verwendete Validierungsansatz kann die Validierung einer Eigenschaft manuell auslösen und die Überprüfung automatisch auslösen, wenn sich eine Eigenschaft ändert.

Manuelles Auslösen der Überprüfung

Validierung kann manuell für eine Ansichtsmodelleigenschaft ausgelöst werden. Dies tritt beispielsweise in der mobilen eShopOnContainers-App auf, wenn der Benutzer auf die Schaltfläche "Anmelden" auf der LoginViewSchaltfläche "Anmelden" tippt, wenn simulierte Dienste verwendet werden. Der Befehlsdelegat ruft die MockSignInAsync-Methode im LoginViewModel auf, wodurch die Validierung durch Ausführen der Validate-Methode aufgerufen wird.Dies wird im folgenden Codebeispiel gezeigt:

private bool Validate()  
{  
    bool isValidUser = ValidateUserName();  
    bool isValidPassword = ValidatePassword();  
    return isValidUser && isValidPassword;  
}  

private bool ValidateUserName()  
{  
    return _userName.Validate();  
}  

private bool ValidatePassword()  
{  
    return _password.Validate();  
}

Die Validate Methode führt die Überprüfung des Benutzernamens und des Kennworts durch, der vom Benutzer in der LoginViewDatei eingegeben wurde, indem die Validate-Methode für jede ValidatableObject<T> Instanz aufruft wird. Das folgende Codebeispiel zeigt die Validate-Methode aus der ValidatableObject<T> Klasse:

public bool Validate()  
{  
    Errors.Clear();  

    IEnumerable<string> errors = _validations  
        .Where(v => !v.Check(Value))  
        .Select(v => v.ValidationMessage);  

    Errors = errors.ToList();  
    IsValid = !Errors.Any();  

    return this.IsValid;  
}

Diese Methode löscht die Errors Auflistung und ruft dann alle Gültigkeitsprüfungsregeln ab, die der Auflistung des Validations Objekts hinzugefügt wurden. Die Check-Methode für jede abgerufene Validierungsregel wird ausgeführt, und der Wert der ValidationMessage-Eigenschaft für jede Validierungsregel, die die Daten nicht validieren kann, wird der Errors-Sammlung der ValidatableObject<T>-Instanz hinzugefügt. Schließlich wird die IsValid-Eigenschaft festgelegt, und ihr Wert wird an die aufrufende Methode zurückgegeben. Dieser Wert gibt an, ob die Validierung erfolgreich war oder fehlgeschlagen ist.

Auslösen der Überprüfung, wenn Eigenschaften geändert werden

Die Überprüfung kann auch ausgelöst werden, wenn eine gebundene Eigenschaft geändert wird. Wenn eine bidirektionale Bindung beispielsweise in der LoginView die UserName- oder Password-Eigenschaft festlegt, wird Validierung ausgelöst. Das folgende Codebeispiel veranschaulicht, wie dies erreicht wird:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">  
    <Entry.Behaviors>  
        <behaviors:EventToCommandBehavior  
            EventName="TextChanged"  
            Command="{Binding ValidateUserNameCommand}" />  
    </Entry.Behaviors>  
    ...  
</Entry>

Das Entry-Steuerelement wird an die UserName.Value-Eigenschaft der ValidatableObject<T>-Instanz gebunden, und der Behaviors-Sammlung des Steuerelements wird eine EventToCommandBehavior-Instanz hinzugefügt. Dieses Verhalten wird ValidateUserNameCommand als Reaktion auf das [TextChanged] Ereignis ausgelöst Entry, das ausgelöst wird, wenn sich der Text in den Entry Änderungen ändert. Der ValidateUserNameCommand-Delegat wiederum führt die ValidateUserName-Methode aus, die die Validate-Methode für die ValidatableObject<T>-Instanz ausführt. Daher wird jedes Mal, wenn der Benutzer ein Zeichen in das Entry-Steuerelement für den Benutzernamen eingibt, eine Validierung der eingegebenen Daten durchgeführt.

Weitere Informationen zu Verhaltensweisen finden Sie unter Implementieren von Verhaltensweisen.

Anzeigen von Überprüfungsfehlern

Die mobile eShopOnContainers-App benachrichtigt den Benutzer über Überprüfungsfehler, indem das Steuerelement hervorgehoben wird, das die ungültigen Daten mit einer roten Linie enthält, und durch Anzeigen einer Fehlermeldung, die den Benutzer darüber informiert, warum die Daten unterhalb des Steuerelements ungültig sind, das die ungültigen Daten enthält. Wenn die ungültigen Daten korrigiert werden, ändert sich die Zeile in Schwarz, und die Fehlermeldung wird entfernt. Abbildung 6-2 zeigt die LoginView in der mobilen eShopOnContainers-App, wenn Validierungsfehler vorhanden sind.

Anzeigen von Überprüfungsfehlern während der Anmeldung

Abbildung 6-2: Anzeigen von Überprüfungsfehlern während der Anmeldung

Hervorheben eines Steuerelements, das ungültige Daten enthält

Das LineColorBehavior angefügte Verhalten wird verwendet, um Steuerelemente hervorzuheben Entry , bei denen Überprüfungsfehler aufgetreten sind. Das folgende Codebeispiel zeigt, wie das LineColorBehavior angefügte Verhalten an ein Entry Steuerelement angefügt wird:

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
    <Entry.Style>
        <OnPlatform x:TypeArguments="Style">
            <On Platform="iOS, Android" Value="{StaticResource EntryStyle}" />
            <On Platform="UWP" Value="{StaticResource UwpEntryStyle}" />
        </OnPlatform>
    </Entry.Style>
    ...
</Entry>

Das Entry Steuerelement verwendet eine explizite Formatvorlage, die im folgenden Codebeispiel dargestellt wird:

<Style x:Key="EntryStyle"  
       TargetType="{x:Type Entry}">  
    ...  
    <Setter Property="behaviors:LineColorBehavior.ApplyLineColor"  
            Value="True" />  
    <Setter Property="behaviors:LineColorBehavior.LineColor"  
            Value="{StaticResource BlackColor}" />  
    ...  
</Style>

Diese Formatvorlage legt die ApplyLineColor und LineColor angefügten Eigenschaften des LineColorBehavior angefügten Verhaltens für das Entry Steuerelement fest. Weitere Informationen zu Formatvorlagen finden Sie unter -Formatvorlagen.

Wenn der Wert der ApplyLineColor angefügten Eigenschaft festgelegt oder geändert wird, führt das LineColorBehavior angefügte Verhalten die OnApplyLineColorChanged Methode aus, die im folgenden Codebeispiel dargestellt wird:

public static class LineColorBehavior  
{  
    ...  
    private static void OnApplyLineColorChanged(  
                BindableObject bindable, object oldValue, object newValue)  
    {  
        var view = bindable as View;  
        if (view == null)  
        {  
            return;  
        }  

        bool hasLine = (bool)newValue;  
        if (hasLine)  
        {  
            view.Effects.Add(new EntryLineColorEffect());  
        }  
        else  
        {  
            var entryLineColorEffectToRemove =   
                    view.Effects.FirstOrDefault(e => e is EntryLineColorEffect);  
            if (entryLineColorEffectToRemove != null)  
            {  
                view.Effects.Remove(entryLineColorEffectToRemove);  
            }  
        }  
    }  
}

Die Parameter für diese Methode stellen die Instanz des Steuerelements bereit, an das das Verhalten angefügt ist, sowie die alten und neuen Werte der ApplyLineColor angefügten Eigenschaft. Die EntryLineColorEffect Klasse wird der Auflistung des Steuerelements Effects hinzugefügt, wenn die ApplyLineColor angefügte Eigenschaft lautet true, andernfalls wird sie aus der Auflistung des Steuerelements Effects entfernt. Weitere Informationen zu Verhaltensweisen finden Sie unter Implementieren von Verhaltensweisen.

Die EntryLineColorEffect Unterklassen der RoutingEffect Klasse und werden im folgenden Codebeispiel gezeigt:

public class EntryLineColorEffect : RoutingEffect  
{  
    public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")  
    {  
    }  
}

Die RoutingEffect Klasse stellt einen plattformunabhängigen Effekt dar, der einen inneren Effekt umschließt, der plattformspezifisch ist. Dadurch wird das Entfernen eines Effekts vereinfacht, da während der Kompilierzeit nicht auf die Typinformationen für einen plattformspezifischen Effekt zugegriffen werden kann. Der EntryLineColorEffect Basisklassenkonstruktor wird aufgerufen, wobei ein Parameter übergeben wird, der aus einer Verkettung des Auflösungsgruppennamens besteht, und der eindeutigen ID, die für jede plattformspezifische Effektklasse angegeben ist.

Das folgende Codebeispiel zeigt die eShopOnContainers.EntryLineColorEffect Implementierung für iOS:

[assembly: ResolutionGroupName("eShopOnContainers")]  
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]  
namespace eShopOnContainers.iOS.Effects  
{  
    public class EntryLineColorEffect : PlatformEffect  
    {  
        UITextField control;  

        protected override void OnAttached()  
        {  
            try  
            {  
                control = Control as UITextField;  
                UpdateLineColor();  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("Can't set property on attached control. Error: ", ex.Message);  
            }  
        }  

        protected override void OnDetached()  
        {  
            control = null;  
        }  

        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)  
        {  
            base.OnElementPropertyChanged(args);  

            if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName ||  
                args.PropertyName == "Height")  
            {  
                Initialize();  
                UpdateLineColor();  
            }  
        }  

        private void Initialize()  
        {  
            var entry = Element as Entry;  
            if (entry != null)  
            {  
                Control.Bounds = new CGRect(0, 0, entry.Width, entry.Height);  
            }  
        }  

        private void UpdateLineColor()  
        {  
            BorderLineLayer lineLayer = control.Layer.Sublayers.OfType<BorderLineLayer>()  
                                                             .FirstOrDefault();  

            if (lineLayer == null)  
            {  
                lineLayer = new BorderLineLayer();  
                lineLayer.MasksToBounds = true;  
                lineLayer.BorderWidth = 1.0f;  
                control.Layer.AddSublayer(lineLayer);  
                control.BorderStyle = UITextBorderStyle.None;  
            }  

            lineLayer.Frame = new CGRect(0f, Control.Frame.Height-1f, Control.Bounds.Width, 1f);  
            lineLayer.BorderColor = LineColorBehavior.GetLineColor(Element).ToCGColor();  
            control.TintColor = control.TextColor;  
        }  

        private class BorderLineLayer : CALayer  
        {  
        }  
    }  
}

Die OnAttached Methode ruft das systemeigene Steuerelement für das Xamarin.FormsEntry Steuerelement ab und aktualisiert die Linienfarbe durch Aufrufen der UpdateLineColor Methode. Die OnElementPropertyChanged Außerkraftsetzung reagiert auf Bindungseigenschaftenänderungen für das Entry Steuerelement, indem die Linienfarbe aktualisiert wird, wenn sich die angefügte LineColor Eigenschaft ändert, oder auf die Height Eigenschaft der Entry Änderungen. Weitere Informationen zu Effekten finden Sie unter Effekte.

Wenn gültige Daten in das Entry Steuerelement eingegeben werden, wird eine schwarze Linie am unteren Rand des Steuerelements angewendet, um anzugeben, dass kein Überprüfungsfehler vorliegt. Abbildung 6-3 zeigt ein Beispiel hierfür.

Schwarze Linie, die angibt, dass kein Überprüfungsfehler auftritt

Abbildung 6-3: Schwarze Linie, die keinen Überprüfungsfehler angibt

Das Entry Steuerelement verfügt außerdem über ein DataTrigger Hinzugefügtes zu seiner Triggers Sammlung. Das folgende Codebeispiel zeigt folgendes:DataTrigger

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">  
    ...  
    <Entry.Triggers>  
        <DataTrigger   
            TargetType="Entry"  
            Binding="{Binding UserName.IsValid}"  
            Value="False">  
            <Setter Property="behaviors:LineColorBehavior.LineColor"   
                    Value="{StaticResource ErrorColor}" />  
        </DataTrigger>  
    </Entry.Triggers>  
</Entry>

Dadurch DataTrigger wird die UserName.IsValid Eigenschaft überwacht, und wenn dieser Wert wird false, wird sie ausgeführt Setter, wodurch die LineColor angefügte Eigenschaft des LineColorBehavior angefügten Verhaltens rot geändert wird. Abbildung 6-4 zeigt ein Beispiel hierfür.

Rote Linie, die den Überprüfungsfehler angibt

Abbildung 6-4: Rote Linie, die den Überprüfungsfehler angibt

Die Zeile im Entry Steuerelement bleibt rot, während die eingegebenen Daten ungültig sind, andernfalls wird sie in Schwarz geändert, um anzugeben, dass die eingegebenen Daten gültig sind.

Weitere Informationen zu Triggern finden Sie unter Trigger.

Anzeigen von Fehlermeldungen

Die Benutzeroberfläche zeigt Validierungsfehlermeldungen in Label-Steuerelementen unter jedem Steuerelement an, dessen Daten die Validierung nicht bestanden haben. Das folgende Codebeispiel zeigt, Label dass eine Überprüfungsfehlermeldung angezeigt wird, wenn der Benutzer keinen gültigen Benutzernamen eingegeben hat:

<Label Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}}"  
       Style="{StaticResource ValidationErrorLabelStyle}" />

Jede Label Bindung wird an die Errors Eigenschaft des Ansichtsmodellobjekts gebunden, das überprüft wird. Die Errors-Eigenschaft wird von der ValidatableObject<T>-Klasse bereitgestellt und ist vom Typ List<string>. Da die Errors-Eigenschaft mehrere Validierungsfehler enthalten kann, wird die FirstValidationErrorConverter-Instanz verwendet, um den ersten Fehler aus der Sammlung zur Anzeige abzurufen.

Zusammenfassung

Die mobile eShopOnContainers-App führt eine synchrone clientseitige Überprüfung der Ansichtsmodelleigenschaften durch und benachrichtigt den Benutzer über Überprüfungsfehler, indem das Steuerelement hervorgehoben wird, das die ungültigen Daten enthält, und durch Anzeigen von Fehlermeldungen, die den Benutzer darüber informieren, warum die Daten ungültig sind.

Ansichtsmodelleigenschaften, die eine Validierung erfordern, sind vom Typ ValidatableObject<T>, und jede ValidatableObject<T>-Instanz verfügt über Validierungsregeln, die ihrer Validations-Eigenschaft hinzugefügt wurden. Die Überprüfung wird aus dem Ansichtsmodell aufgerufen, indem die Validate Methode der ValidatableObject<T> Instanz aufgerufen wird, die die Gültigkeitsprüfungsregeln abruft und für die ValidatableObject<T> Value Eigenschaft ausgeführt wird. Alle Überprüfungsfehler werden in die Errors Eigenschaft der ValidatableObject<T>Instanz eingefügt, und die IsValid Eigenschaft der ValidatableObject<T> Instanz wird aktualisiert, um anzugeben, ob die Überprüfung erfolgreich war oder fehlgeschlagen ist.