Validation dans Les applications d’entreprise
Remarque
Ce livre électronique a été publié au printemps 2017 et n’a pas été mis à jour depuis. Il y a beaucoup dans le livre qui reste précieux, mais certains de la matière est obsolète.
Toute application qui accepte une entrée des utilisateurs doit s’assurer que l’entrée est valide. Une application peut, par exemple, rechercher une entrée qui contient uniquement des caractères dans une plage particulière, est d’une certaine longueur ou correspond à un format particulier. Sans validation, un utilisateur peut fournir des données qui provoquent l’échec de l’application. La validation applique des règles métier et empêche un attaquant d’injecter des données malveillantes.
Dans le contexte du modèle modèle-vue-vue modèle (MVVM), un modèle de vue ou un modèle est souvent nécessaire pour effectuer la validation des données et signaler les erreurs de validation à la vue afin que l’utilisateur puisse les corriger. L’application mobile eShopOnContainers effectue une validation synchrone côté client des propriétés du modèle d’affichage et avertit l’utilisateur des erreurs de validation en mettant en évidence le contrôle qui contient les données non valides et en affichant des messages d’erreur qui informent l’utilisateur de la raison pour laquelle les données ne sont pas valides. La figure 6-1 montre les classes impliquées dans l’exécution de la validation dans l’application mobile eShopOnContainers.
Figure 6-1 : Classes de validation dans l’application mobile eShopOnContainers
Les propriétés de modèle d’affichage qui nécessitent une validation sont de type ValidatableObject<T>
, et chaque instance ValidatableObject<T>
a des règles de validation ajoutées à sa propriété Validations
. La validation est appelée à partir du modèle de vue en appelant la Validate
méthode de l’instance ValidatableObject<T>
, qui récupère les règles de validation et les exécute sur la ValidatableObject<T>
Value
propriété. Toutes les erreurs de validation sont placées dans la Errors
propriété de l’instance ValidatableObject<T>
et la IsValid
propriété de l’instance ValidatableObject<T>
est mise à jour pour indiquer si la validation a réussi ou échoué.
La notification de modification de propriété est fournie par la classe ExtendedBindableObject
. Par conséquent, un contrôle Entry
peut être lié à la propriété IsValid
de l’instance ValidatableObject<T>
dans la classe de modèle de vue pour être informé de la validité ou non des données entrées.
Spécification de règles de validation
Les règles de validation sont spécifiées en créant une classe qui dérive de l’interface IValidationRule<T>
, comme illustré dans l’exemple de code suivant :
public interface IValidationRule<T>
{
string ValidationMessage { get; set; }
bool Check(T value);
}
Cette interface spécifie qu’une classe de règle de validation doit fournir une boolean
Check
méthode utilisée pour effectuer la validation requise et une ValidationMessage
propriété dont la valeur est le message d’erreur de validation qui s’affiche si la validation échoue.
L’exemple de code suivant montre la IsNotNullOrEmptyRule<T>
règle de validation, utilisée pour effectuer la validation du nom d’utilisateur et du mot de passe entrés par l’utilisateur lors de l’utilisation LoginView
de services fictifs dans l’application mobile eShopOnContainers :
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);
}
}
La Check
méthode retourne un boolean
indicateur indiquant si l’argument valeur est null
, vide ou se compose uniquement de caractères d’espace blanc.
Bien qu’il ne soit pas utilisé par l’application mobile eShopOnContainers, l’exemple de code suivant montre une règle de validation pour la validation des adresses e-mail :
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;
}
}
La Check
méthode retourne un boolean
indicateur indiquant si l’argument valeur est une adresse e-mail valide. Pour ce faire, recherchez la première occurrence du modèle d’expression régulière spécifié dans le constructeur Regex
dans l’argument value. Si le modèle d’expression régulière a été trouvé dans la chaîne d’entrée peut être déterminé en vérifiant la valeur de la propriété de Success
l’objetMatch
.
Remarque
La validation de propriété peut parfois impliquer des propriétés dépendantes. Un exemple de propriétés dépendantes est lorsque l’ensemble de valeurs valides pour la propriété A dépend de la valeur particulière qui a été définie dans la propriété B. Pour vérifier que la valeur de la propriété A est l’une des valeurs autorisées, vous devez récupérer la valeur de la propriété B. En outre, lorsque la valeur de la propriété B change, la propriété A doit être revalidée.
Ajout de règles de validation à une propriété
Dans l’application mobile eShopOnContainers, affichez les propriétés de modèle qui nécessitent la validation sont déclarées comme de type ValidatableObject<T>
, où T
est le type des données à valider. L’exemple de code suivant montre un exemple de deux propriétés de ce type :
public ValidatableObject<string> UserName
{
get
{
return _userName;
}
set
{
_userName = value;
RaisePropertyChanged(() => UserName);
}
}
public ValidatableObject<string> Password
{
get
{
return _password;
}
set
{
_password = value;
RaisePropertyChanged(() => Password);
}
}
Pour que la validation se produise, les règles de validation doivent être ajoutées à la Validations
collection de chaque ValidatableObject<T>
instance, comme illustré dans l’exemple de code suivant :
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."
});
}
Cette méthode ajoute la règle de validation IsNotNullOrEmptyRule<T>
à la collection Validations
de chaque instance ValidatableObject<T>
, en spécifiant des valeurs pour la propriété ValidationMessage
de la règle de validation, qui spécifie le message d’erreur de validation qui s’affichera en cas d’échec de la validation.
Déclenchement de la validation
L’approche de validation utilisée dans l’application mobile eShopOnContainers peut déclencher manuellement la validation d’une propriété et déclencher automatiquement la validation lorsqu’une propriété change.
Déclenchement manuel de la validation
La validation peut être déclenchée manuellement pour une propriété de modèle de vue. Par exemple, cela se produit dans l’application mobile eShopOnContainers lorsque l’utilisateur appuie sur le bouton Connexion sur le , lors de l’utilisation LoginView
de services fictifs. Le délégué de commande appelle la méthode MockSignInAsync
dans le modèle de vue LoginViewModel
, qui appelle la validation en exécutant la méthode Validate
, ce qui est illustré dans l’exemple de code suivant :
private bool Validate()
{
bool isValidUser = ValidateUserName();
bool isValidPassword = ValidatePassword();
return isValidUser && isValidPassword;
}
private bool ValidateUserName()
{
return _userName.Validate();
}
private bool ValidatePassword()
{
return _password.Validate();
}
La Validate
méthode effectue la validation du nom d’utilisateur et du mot de passe entrés par l’utilisateur sur le LoginView
, en appelant la méthode Validate sur chaque ValidatableObject<T>
instance. L’exemple de code suivant montre la méthode Validate de la ValidatableObject<T>
classe :
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;
}
Cette méthode efface la Errors
collection, puis récupère toutes les règles de validation qui ont été ajoutées à la collection de l’objet Validations
. La méthode Check
pour chaque règle de validation récupérée est exécutée et la valeur de propriété ValidationMessage
pour toute règle de validation qui ne parvient pas à valider les données est ajoutée à la collection Errors
de l’instance ValidatableObject<T>
. Enfin, la propriété IsValid
est définie et sa valeur est retournée à la méthode appelante, indiquant si la validation a réussi ou échoué.
Déclenchement de la validation lorsque les propriétés changent
La validation peut également être déclenchée chaque fois qu’une propriété liée change. Par exemple, lorsqu’une liaison bidirectionnelle dans la vue LoginView
définit la propriété UserName
ou Password
, la validation est déclenchée. L’exemple de code suivant montre comment cela se produit :
<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
<Entry.Behaviors>
<behaviors:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding ValidateUserNameCommand}" />
</Entry.Behaviors>
...
</Entry>
Le contrôle Entry
est lié à la propriété UserName.Value
de l’instance ValidatableObject<T>
et une instance EventToCommandBehavior
est ajoutée à la collection Behaviors
du contrôle. Ce comportement exécute la ValidateUserNameCommand
réponse à l’événement [TextChanged
] qui se déclenche sur le Entry
, qui est déclenché lorsque le texte dans les Entry
modifications est déclenché. À son tour, le délégué ValidateUserNameCommand
exécute la méthode ValidateUserName
, qui exécute la méthode Validate
sur l’instance ValidatableObject<T>
. Par conséquent, chaque fois que l’utilisateur entre un caractère dans le contrôle Entry
pour le nom d’utilisateur, la validation des données entrées est effectuée.
Pour plus d’informations sur les comportements, consultez Implémentation de comportements.
Affichage des erreurs de validation
L’application mobile eShopOnContainers informe l’utilisateur de toutes les erreurs de validation en mettant en surbrillance le contrôle qui contient les données non valides avec une ligne rouge et en affichant un message d’erreur qui informe l’utilisateur pourquoi les données ne sont pas valides sous le contrôle contenant les données non valides. Lorsque les données non valides sont corrigées, la ligne passe en noir et le message d’erreur est supprimé. La figure 6-2 montre l’objet LoginView dans l’application mobile eShopOnContainers lorsque des erreurs de validation sont présentes.
Figure 6-2 : Affichage des erreurs de validation lors de la connexion
Mise en surbrillance d’un contrôle qui contient des données non valides
Le LineColorBehavior
comportement attaché est utilisé pour mettre en évidence Entry
les contrôles où des erreurs de validation se sont produites. L’exemple de code suivant montre comment le LineColorBehavior
comportement attaché est attaché à un Entry
contrôle :
<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>
Le Entry
contrôle utilise un style explicite, illustré dans l’exemple de code suivant :
<Style x:Key="EntryStyle"
TargetType="{x:Type Entry}">
...
<Setter Property="behaviors:LineColorBehavior.ApplyLineColor"
Value="True" />
<Setter Property="behaviors:LineColorBehavior.LineColor"
Value="{StaticResource BlackColor}" />
...
</Style>
Ce style définit les ApplyLineColor
LineColor
propriétés et les propriétés jointes du LineColorBehavior
comportement attaché sur le Entry
contrôle. Pour plus d’informations sur les styles, consultez Styles.
Lorsque la valeur de la ApplyLineColor
propriété jointe est définie ou change, le LineColorBehavior
comportement attaché exécute la OnApplyLineColorChanged
méthode, qui est illustrée dans l’exemple de code suivant :
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);
}
}
}
}
Les paramètres de cette méthode fournissent l’instance du contrôle auquel le comportement est attaché, ainsi que les anciennes et nouvelles valeurs de la ApplyLineColor
propriété jointe. La EntryLineColorEffect
classe est ajoutée à la collection du Effects
contrôle si la ApplyLineColor
propriété jointe est , sinon elle est true
supprimée de la collection du Effects
contrôle. Pour plus d’informations sur les comportements, consultez Implémentation de comportements.
La EntryLineColorEffect
sous-classe de la RoutingEffect
classe est illustrée dans l’exemple de code suivant :
public class EntryLineColorEffect : RoutingEffect
{
public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")
{
}
}
La RoutingEffect
classe représente un effet indépendant de la plateforme qui encapsule un effet interne spécifique à la plateforme. Cela simplifie le processus de suppression de l’effet, car il n’y a pas d’accès au moment de la compilation aux informations de type pour un effet propre à la plateforme. L’appel EntryLineColorEffect
du constructeur de classe de base, en passant un paramètre constitué d’une concaténation du nom du groupe de résolution et de l’ID unique spécifié sur chaque classe d’effet spécifique à la plateforme.
L’exemple de code suivant montre l’implémentation eShopOnContainers.EntryLineColorEffect
pour 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
{
}
}
}
La OnAttached
méthode récupère le contrôle natif du Xamarin.FormsEntry
contrôle et met à jour la couleur de ligne en appelant la UpdateLineColor
méthode. Le OnElementPropertyChanged
remplacement répond aux modifications de propriété pouvant être liées sur le Entry
contrôle en mettant à jour la couleur de ligne si la propriété jointe LineColor
change ou la Height
propriété des Entry
modifications. Pour plus d’informations sur les effets, consultez Effets.
Lorsque les données valides sont entrées dans le Entry
contrôle, elles appliquent une ligne noire au bas du contrôle pour indiquer qu’il n’y a aucune erreur de validation. La figure 6-3 montre un exemple de ceci.
Figure 6-3 : Ligne noire indiquant aucune erreur de validation
Le Entry
contrôle a également ajouté DataTrigger
à sa Triggers
collection. L’exemple de code suivant montre les DataTrigger
éléments suivants :
<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>
Cela DataTrigger
surveille la UserName.IsValid
propriété et, si sa valeur devient false
, elle exécute le Setter
, qui modifie la LineColor
propriété jointe du LineColorBehavior
comportement attaché en rouge. La figure 6-4 montre un exemple de ceci.
Figure 6-4 : Ligne rouge indiquant l’erreur de validation
La ligne du Entry
contrôle reste rouge alors que les données entrées ne sont pas valides. Sinon, elle passe en noir pour indiquer que les données entrées sont valides.
Pour plus d’informations sur les déclencheurs, consultez Déclencheurs.
Affichage des messages d’erreur
L’interface utilisateur affiche des messages d’erreur de validation dans les contrôles Label sous chaque contrôle dont la validation des données a échoué. L’exemple de code suivant montre comment Label
afficher un message d’erreur de validation si l’utilisateur n’a pas entré de nom d’utilisateur valide :
<Label Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}}"
Style="{StaticResource ValidationErrorLabelStyle}" />
Chacune Label
est liée à la Errors
propriété de l’objet de modèle d’affichage en cours de validation. La propriété Errors
est fournie par la classe ValidatableObject<T>
et est de type List<string>
. Étant donné que la propriété Errors
peut contenir plusieurs erreurs de validation, l’instance FirstValidationErrorConverter
est utilisée pour récupérer la première erreur de la collection pour affichage.
Résumé
L’application mobile eShopOnContainers effectue une validation synchrone côté client des propriétés du modèle d’affichage et avertit l’utilisateur des erreurs de validation en mettant en évidence le contrôle qui contient les données non valides et en affichant des messages d’erreur qui informent l’utilisateur pourquoi les données ne sont pas valides.
Les propriétés de modèle d’affichage qui nécessitent une validation sont de type ValidatableObject<T>
, et chaque instance ValidatableObject<T>
a des règles de validation ajoutées à sa propriété Validations
. La validation est appelée à partir du modèle de vue en appelant la Validate
méthode de l’instance ValidatableObject<T>
, qui récupère les règles de validation et les exécute sur la ValidatableObject<T>
Value
propriété. Toutes les erreurs de validation sont placées dans la Errors
propriété de l’instance ValidatableObject<T>
et la IsValid
propriété de l’instance ValidatableObject<T>
est mise à jour pour indiquer si la validation a réussi ou échoué.