Validierung in Unternehmens-Apps
Hinweis
Dieses eBook wurde im Frühjahr 2017 veröffentlicht und wurde seitdem nicht aktualisiert. Es gibt vieles im Buch, das wertvoll bleibt, aber ein Teil des Materials ist 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 angreifer böswillige Daten einschleusen.
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 Eigenschaften des Ansichtsmodells durch und benachrichtigt den Benutzer über validierungsfehler, indem das Steuerelement hervorgehoben wird, das die ungültigen Daten enthält, und Fehlermeldungen angezeigt werden, 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.
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 über das Ansichtsmodell aufgerufen, indem die Validate
Methode des ValidatableObject<T>
instance aufgerufen wird, die die Validierungsregeln abruft und für die ValidatableObject<T>
Value
-Eigenschaft ausführt. Alle Validierungsfehler werden in die Errors
Eigenschaft des ValidatableObject<T>
instance eingefügt, und die IsValid
Eigenschaft des instance wird aktualisiert, um anzugeben, ob die ValidatableObject<T>
Überprüfung erfolgreich war oder fehlgeschlagen ist.
Eigenschaftsänderungsbenachrichtigungen werden von der ExtendedBindableObject
-Klasse bereitgestellt. Daher kann ein Entry
-Steuerelement an die IsValid
Eigenschaft der ValidatableObject<T>
-Instanz in der Ansichtsmodellklasse gebunden werden, um benachrichtigt zu werden, ob die eingegebenen Daten gültig sind.
Angeben von Validierungsregeln
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 Validierungsregelklasse eine boolean
Check
Methode bereitstellen muss, die zum Ausführen der erforderlichen Überprüfung verwendet wird, und eine ValidationMessage
Eigenschaft, deren Wert die Validierungsfehlermeldung ist, die angezeigt wird, wenn die Überprüfung fehlschlägt.
Das folgende Codebeispiel zeigt die Validierungsregel IsNotNullOrEmptyRule<T>
, die verwendet wird, um die Überprüfung des Benutzernamens und Des Kennworts durchzuführen, der vom Benutzer für die LoginView
Verwendung von Pseudodiensten 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
zurück, der angibt, ob das Wertargument leer ist null
oder nur aus Leerzeichen besteht.
Obwohl nicht von der mobilen eShopOnContainers-App verwendet, zeigt das folgende Codebeispiel eine Validierungsregel zum Überprüfen 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
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. Ob das Muster des regulären Ausdrucks in der Eingabezeichenfolge gefunden wurde, kann durch Überprüfen des Werts der -Eigenschaft des Match
Success
Objekts bestimmt werden.
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 Validierungsregeln zu einer Eigenschaft
In der mobilen eShopOnContainers-App werden die Modelleigenschaften, die eine Überprüfung erfordern, als vom Typ ValidatableObject<T>
deklariert, wobei T
der Typ der zu überprüfenden Daten ist. 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 durchgeführt wird, müssen der Validations
Auflistung jeder ValidatableObject<T>
instance Überprüfungsregeln hinzugefügt werden, wie im folgenden Codebeispiel veranschaulicht:
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 Überprüfung einer Eigenschaft manuell auslösen und automatisch die Überprüfung 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 bei Verwendung von Pseudodiensten auf die LoginView
Schaltfläche Anmeldung tippen. 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 für den LoginView
eingegeben wurde, indem die Validate-Methode für jeden ValidatableObject<T>
instance aufgerufen 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 Validierungsregeln 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 bei Änderung der Eigenschaften
Die Überprüfung kann auch ausgelöst werden, wenn sich eine gebundene Eigenschaft ändert. 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 führt das als Antwort auf das ValidateUserNameCommand
[TextChanged
]-Ereignis aus, das auf Entry
ausgelöst wird, wenn sich der Text in der Entry
ä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 Validierungsfehlern
Die mobile eShopOnContainers-App benachrichtigt den Benutzer über validierungsfehler, indem das Steuerelement, das die ungültigen Daten enthält, mit einer roten Linie hervorgehoben wird, und eine Fehlermeldung angezeigt wird, 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 vorliegen.
Abbildung 6-2: Anzeigen von Validierungsfehlern 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 Validierungsfehler 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 gezeigt 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 und LineColor
die ApplyLineColor
angefügten Eigenschaften des LineColorBehavior
angefügten Verhaltens für das Entry
Steuerelement fest. Weitere Informationen zu Formatvorlagen finden Sie unter Styles (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, was im folgenden Codebeispiel gezeigt 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 bieten die instance des Steuerelements, 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 ist 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 werden im folgenden Codebeispiel dargestellt:
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. Ruft EntryLineColorEffect
den Basisklassenkonstruktor auf und übergibt einen Parameter, der aus einer Verkettung des Auflösungsgruppennamens und der eindeutigen ID besteht, 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
Überschreibung reagiert auf änderungen der bindungsfähigen Eigenschaft am Entry
Steuerelement, indem die Linienfarbe aktualisiert wird, wenn sich die angefügte LineColor
Eigenschaft ändert, oder 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 auf den unteren Rand des Steuerelements angewendet, um anzugeben, dass kein Validierungsfehler vorliegt. Abbildung 6-3 zeigt ein Beispiel dafür.
Abbildung 6-3: Schwarze Linie, die keinen Validierungsfehler anzeigt
Das Entry
Steuerelement hat seiner Auflistung auch eine DataTrigger
hinzugefügt Triggers
. 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 der Wert zu false
wird, wird der Setter
ausgeführt, wodurch die LineColor
angefügte Eigenschaft des LineColorBehavior
angefügten Verhaltens in Rot geändert wird. Abbildung 6-4 zeigt ein Beispiel dafür.
Abbildung 6-4: Rote Linie, die einen Validierungsfehler anzeigt
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 anzeigt, wenn der Benutzer keinen gültigen Benutzernamen eingegeben hat:
<Label Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}}"
Style="{StaticResource ValidationErrorLabelStyle}" />
Jede Label
Bindung an die Errors
Eigenschaft des Zuschaumodellobjekts, 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 Fehlermeldungen angezeigt werden, 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 Validierung wird über das Ansichtsmodell aufgerufen, indem die Validate
-Methode der ValidatableObject<T>
instance aufgerufen wird, die die Validierungsregeln abruft und für die ValidatableObject<T>
Value
-Eigenschaft ausführt. Alle Validierungsfehler werden in die Errors
Eigenschaft des ValidatableObject<T>
instance eingefügt, und die IsValid
Eigenschaft des instance wird aktualisiert, um anzugeben, ob die ValidatableObject<T>
Überprüfung erfolgreich war oder fehlgeschlagen ist.