{"id":32763,"date":"2017-08-08T12:25:02","date_gmt":"2017-08-08T19:25:02","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=32763"},"modified":"2019-04-04T07:49:03","modified_gmt":"2019-04-04T14:49:03","slug":"validation-xamarin-forms-enterprise-apps","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/validation-xamarin-forms-enterprise-apps\/","title":{"rendered":"Validation in Xamarin.Forms Enterprise Apps"},"content":{"rendered":"<p>\t\t\t\t<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/validationanimation.gif\" alt=\"animation\" align=\"right\" style=\"padding:10px\">We <a href=\"https:\/\/blog.xamarin.com\/developing-enterprise-apps-using-xamarin-forms\/\" target=\"_blank\">released an eBook<\/a> this past May on <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/enterprise-application-patterns\/\" target=\"_blank\"><em>Enterprise Application Patterns using Xamarin.Forms<\/em><\/a>.\u00a0The eBook focuses on core patterns and architectural guidance for developing Xamarin.Forms enterprise apps that are easier to test, maintain, and evolve. Guidance is provided on how to implement the Model-View-ViewModel (MVVM) pattern, dependency injection, navigation, validation, and configuration management, while maintaining loose coupling. In addition, there\u2019s also guidance on performing authentication and authorization with IdentityServer, accessing remote data from containerized microservices, and unit testing.<\/p>\n<p>This blog post explores validation in Xamarin.Forms enterprise apps. There are, of course, many approaches that can be taken to validation. What&#8217;s presented here is the validation approach taken in the <a href=\"https:\/\/github.com\/dotnet-architecture\/eShopOnContainers\" target=\"_blank\"><em>eShopOnContainers mobile app<\/em><\/a>, which is extensible, easily unit testable, and supports data binding and property change notification.<\/p>\n<h2>Introduction to Validation<\/h2>\n<p>Any app that accepts input from users should ensure that the input is valid. An app could, for example, check for input that contains only characters in a particular range, is of a certain length, or matches a particular format. Without validation, a user can supply data that causes the app to fail. Validation enforces business rules and prevents an attacker from injecting malicious data.<\/p>\n<p>In the context of the Model-ViewModel-Model (MVVM) pattern, a view model or model will often be required to perform data validation and signal any validation errors to the view so that the user can correct them. The eShopOnContainers mobile app performs synchronous client-side validation of view model properties and notifies the user of any validation errors by highlighting the control that contains the invalid data, and by displaying error messages that inform the user of why the data is invalid. The following diagram shows\u00a0the classes involved in performing validation in the eShopOnContainers mobile app:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-32765\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/validation.png\" alt=\"\" width=\"874\" height=\"576\" \/><\/p>\n<p>View model properties that require validation are of type <code>ValidatableObject&lt;T&gt;<\/code>, and each <code>ValidatableObject&lt;T&gt;<\/code> instance has validation rules added to its <code>Validations<\/code> property. Validation is invoked from the view model by calling the <code>Validate<\/code> method of the <code>ValidatableObject&lt;T&gt;<\/code> instance, which retrieves the validation rules and executes them against the <code>ValidatableObject&lt;T&gt; Value<\/code> property. Any validation errors are placed into the <code>Errors<\/code> property of the <code>ValidatableObject&lt;T&gt;<\/code> instance, and the <code>IsValid<\/code> property of the <code>ValidatableObject&lt;T&gt;<\/code> instance is updated to indicate whether validation succeeded or failed.<\/p>\n<p>Property change notification is provided by the <code>ExtendedBindableObject<\/code> class, and so an <code>Entry<\/code> control can bind to the <code>IsValid<\/code> property of the <code>ValidatableObject&lt;T&gt;<\/code> instance in the view model class to be notified of whether or not the entered data is valid.<\/p>\n<h2>Specifying Validation Rules<\/h2>\n<p>Validation rules are specified by creating a class that derives from the <code>IValidationRule&lt;T&gt;<\/code> interface, which is shown in the following code example:<\/p>\n<pre class=\"lang:c# decode:true \">public\u00a0interface\u00a0IValidationRule&lt;T&gt;\n{\n\u00a0\u00a0\u00a0\u00a0string\u00a0ValidationMessage\u00a0{\u00a0get;\u00a0set;\u00a0}\n\u00a0\u00a0\u00a0\u00a0bool\u00a0Check(T\u00a0value);\n}<\/pre>\n<p>This interface specifies that a validation rule class must provide a <code>boolean Check<\/code> method that is used to perform the required validation, and a <code>ValidationMessage<\/code> property whose value is the validation error message that will be displayed if validation fails.<\/p>\n<p>The following code example shows the <code>IsNotNullOrEmptyRule&lt;T&gt;<\/code> validation rule, which is used to perform validation of the username and password entered by the user on the <code>LoginView<\/code> when the eShopOnContainers mobile app is configured to use mock services:<\/p>\n<pre class=\"lang:c# decode:true \">public\u00a0class\u00a0IsNotNullOrEmptyRule&lt;T&gt;\u00a0:\u00a0IValidationRule&lt;T&gt;\n{\n\u00a0\u00a0\u00a0\u00a0public\u00a0string\u00a0ValidationMessage\u00a0{\u00a0get;\u00a0set;\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0public\u00a0bool\u00a0Check(T\u00a0value)\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(value\u00a0==\u00a0null)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0false;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var\u00a0str\u00a0=\u00a0value\u00a0as\u00a0string;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0!string.IsNullOrWhiteSpace(str);\n\u00a0\u00a0\u00a0\u00a0}\n}<\/pre>\n<p>The <code>Check<\/code> method returns a <code>boolean<\/code> indicating whether the value argument is <code>null<\/code>, empty, or consists only of whitespace characters.<\/p>\n<h2>Adding Validation Rules to a Property<\/h2>\n<p>In the eShopOnContainers mobile app, view model properties that require validation are declared to be of type <code>ValidatableObject&lt;T&gt;<\/code>, where <code>T<\/code> is the type of the data to be validated. The following code example shows an example of one such property:<\/p>\n<pre class=\"lang:c# decode:true \">public\u00a0ValidatableObject&lt;string&gt;\u00a0UserName\n{\n\u00a0\u00a0\u00a0\u00a0get\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return\u00a0_userName;\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0set\n\u00a0\u00a0\u00a0\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0_userName\u00a0=\u00a0value;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0RaisePropertyChanged(()\u00a0=&gt;\u00a0UserName);\n\u00a0\u00a0\u00a0\u00a0}\n}<\/pre>\n<p>For validation to occur, validation rules must be added to the <code>Validations<\/code> collection of the\u00a0<code>ValidatableObject&lt;T&gt;<\/code> instance, as demonstrated in the following code example:<\/p>\n<pre class=\"lang:c# decode:true \">private\u00a0void\u00a0AddValidations()\n{\n\u00a0\u00a0\u00a0\u00a0_userName.Validations.Add(new\u00a0IsNotNullOrEmptyRule&lt;string&gt;\u00a0\n\u00a0\u00a0\u00a0\u00a0{\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ValidationMessage\u00a0=\u00a0\"A\u00a0username\u00a0is\u00a0required.\"\u00a0\n\u00a0\u00a0\u00a0\u00a0});\n}<\/pre>\n<p>This method adds the <code>IsNotNullOrEmptyRule&lt;T&gt;<\/code> validation rule to the <code>Validations<\/code> collection of the <code>ValidatableObject&lt;T&gt;<\/code> instance, including a value for the\u00a0<code>ValidationMessage<\/code> property, which specifies the validation error message that will be displayed if validation fails.<\/p>\n<h2>Triggering Validation<\/h2>\n<p>Validation can be triggered manually for a view model property. For example, this occurs in the eShopOnContainers mobile app when the user taps the <strong>Login<\/strong> button on the <code>LoginView<\/code>, when using mock services. The command delegate calls the <code>MockSignInAsync<\/code> method in the <code>LoginViewModel<\/code>, which invokes validation by executing the <code>Validate<\/code> method, which in turn invokes the <code>ValidateUserName<\/code> method:<\/p>\n<pre class=\"lang:c# decode:true \">private\u00a0bool\u00a0ValidateUserName()\n{\n\u00a0\u00a0\u00a0\u00a0return\u00a0_userName.Validate();\n}<\/pre>\n<p>The <code>ValidateUserName<\/code> method performs validation of the username entered by the user on the <code>LoginView<\/code>, by invoking the <code>Validate<\/code> method on the <code>ValidatableObject&lt;T&gt;<\/code> instance. The following code example shows the <code>Validate<\/code> method from the <code>ValidatableObject&lt;T&gt;<\/code> class:<\/p>\n<pre class=\"lang:c# decode:true \">public\u00a0bool\u00a0Validate()\n{\n\u00a0\u00a0\u00a0\u00a0Errors.Clear();\n\n\u00a0\u00a0\u00a0\u00a0IEnumerable&lt;string&gt;\u00a0errors\u00a0=\u00a0_validations\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Where(v\u00a0=&gt;\u00a0!v.Check(Value))\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.Select(v\u00a0=&gt;\u00a0v.ValidationMessage);\n\n\u00a0\u00a0\u00a0\u00a0Errors\u00a0=\u00a0errors.ToList();\n\u00a0\u00a0\u00a0\u00a0IsValid\u00a0=\u00a0!Errors.Any();\n\n\u00a0\u00a0\u00a0\u00a0return\u00a0this.IsValid;\n}<\/pre>\n<p>This method clears the <code>Errors<\/code> collection, and then retrieves any validation rules that were added to the object&#8217;s <code>Validations<\/code> collection. The <code>Check<\/code> method for each retrieved validation rule is executed, and the <code>ValidationMessage<\/code> property value for any validation rule that fails to validate the data is added to the <code>Errors<\/code> collection of the <code>ValidatableObject&lt;T&gt;<\/code> instance. Finally, the <code>IsValid<\/code> property is set, and its value is returned to the calling method, indicating whether validation succeeded or failed.<\/p>\n<p>Validation is also automatically triggered whenever a bound property changes. For more information, see <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/enterprise-application-patterns\/validation\/#Triggering_Validation_when_Properties_Change\" target=\"_blank\">Triggering Validation when Properties Change<\/a>.<\/p>\n<h2>Displaying Validation Errors<\/h2>\n<p>The eShopOnContainers mobile app notifies the user of any validation errors by highlighting the control that contains the invalid data with a red line, and by displaying an error message that informs the user why the data is invalid below the control containing the invalid data. The following screenshot shows\u00a0part of the <code>LoginView<\/code> in the eShopOnContainers mobile app when a validation error is present:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-32769\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/validation-cropped.png\" alt=\"\" width=\"559\" height=\"103\" \/><\/p>\n<h3>Highlighting a Control that Contains Invalid Data<\/h3>\n<p>The <code>LineColorBehavior<\/code> attached behavior is used to highlight <code>Entry<\/code> controls where validation errors have occurred. The following code example shows how the <code>LineColorBehavior<\/code> attached behavior is attached to an <code>Entry<\/code> control:<\/p>\n<pre class=\"lang:xml decode:true\" title=\"Entry with Style\">&lt;Entry\u00a0Text=\"{Binding\u00a0UserName.Value,\u00a0Mode=TwoWay}\"&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;Entry.Style&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;OnPlatform\u00a0x:TypeArguments=\"Style\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0iOS=\"{StaticResource\u00a0EntryStyle}\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Android=\"{StaticResource\u00a0EntryStyle}\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0WinPhone=\"{StaticResource\u00a0UwpEntryStyle}\"\/&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/Entry.Style&gt;\n\u00a0\u00a0\u00a0\u00a0...\n&lt;\/Entry&gt;<\/pre>\n<p>The <code>Entry<\/code> control consumes an explicit style, which is shown in the following code example:<\/p>\n<pre class=\"lang:xml decode:true\" title=\"Style with attached behavior\">&lt;Style\u00a0x:Key=\"EntryStyle\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TargetType=\"{x:Type\u00a0Entry}\"&gt;\n\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0&lt;Setter\u00a0Property=\"behaviors:LineColorBehavior.ApplyLineColor\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Value=\"True\"\u00a0\/&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;Setter\u00a0Property=\"behaviors:LineColorBehavior.LineColor\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Value=\"{StaticResource\u00a0BlackColor}\"\u00a0\/&gt;\n\u00a0\u00a0\u00a0\u00a0...\n&lt;\/Style&gt;<\/pre>\n<p>This style sets the <code>ApplyLineColor<\/code> and <code>LineColor<\/code> attached properties of the <code>LineColorBehavior<\/code> attached behavior on the <code>Entry<\/code> control. When the value of the <code>ApplyLineColor<\/code> attached property is set, or changes, the <code>LineColorBehavior<\/code> attached behavior executes the <code>OnApplyLineColorChanged<\/code> method, which adds or removes the <code>EntryLineColorEffect<\/code> class to the <code>Entry<\/code>&#8216;s <code>Effects<\/code> collection. For more information about the <code>EntryLineColorEffect<\/code> class, see <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/enterprise-application-patterns\/validation\/#Highlighting_a_Control_that_Contains_Invalid_Data\" target=\"_blank\">Highlighting a Control that Contains Invalid Data<\/a>.<\/p>\n<p>The <code>Entry<\/code> control also has a <code>DataTrigger<\/code> added to its <code>Triggers<\/code> collection. The following code example shows the <code>DataTrigger<\/code>:<\/p>\n<pre class=\"lang:xml decode:true\" title=\"Entry with DataTrigger\">&lt;Entry\u00a0Text=\"{Binding\u00a0UserName.Value,\u00a0Mode=TwoWay}\"&gt;\n\u00a0\u00a0\u00a0\u00a0...\n\u00a0\u00a0\u00a0\u00a0&lt;Entry.Triggers&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;DataTrigger\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TargetType=\"Entry\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Binding=\"{Binding\u00a0UserName.IsValid}\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Value=\"False\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;Setter\u00a0Property=\"behaviors:LineColorBehavior.LineColor\"\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Value=\"{StaticResource\u00a0ErrorColor}\"\u00a0\/&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/DataTrigger&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/Entry.Triggers&gt;\n&lt;\/Entry&gt;<\/pre>\n<p>This <code>DataTrigger<\/code> monitors the <code>UserName.IsValid<\/code> property, and if it&#8217;s value becomes <code>false<\/code>, it executes the <code>Setter<\/code>, which changes the <code>LineColor<\/code> attached property of the <code>LineColorBehavior<\/code> attached behavior to red.<\/p>\n<h3>Displaying Error Messages<\/h3>\n<p>The UI displays validation error messages in <code>Label<\/code> controls below each control whose data failed validation. The following code example shows the <code>Label<\/code> that displays a validation error message if the user has not entered a valid username:<\/p>\n<pre class=\"lang:xml decode:true\" title=\"Displaying validation error message\">&lt;Label\u00a0Text=\"{Binding\u00a0UserName.Errors,\u00a0Converter={StaticResource\u00a0FirstValidationErrorConverter}\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Style=\"{StaticResource\u00a0ValidationErrorLabelStyle}\"\u00a0\/&gt;<\/pre>\n<p>Each <code>Label<\/code> binds to the <code>Errors<\/code> property of the view model object that&#8217;s being validated. The <code>Errors<\/code> property is provided by the <code>ValidatableObject&lt;T&gt;<\/code> class, and is of type <code>List&lt;string&gt;<\/code>. Because the <code>Errors<\/code> property can contain multiple validation errors, the <code>FirstValidationErrorConverter<\/code> instance is used to retrieve the first error from the collection for display.<\/p>\n<h2>Summary<\/h2>\n<p><a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/enterprise-application-patterns\/\" target=\"_blank\"><em>Enterprise Application Patterns using Xamarin.Forms<\/em><\/a> focuses on core patterns and architectural guidance for developing Xamarin.Forms Enterprise Apps that are easier to test, maintain, and evolve.\u00a0The eBook also ships with a sample application, the <a href=\"https:\/\/github.com\/dotnet-architecture\/eShopOnContainers\" target=\"_blank\">eShopOnContainers mobile app<\/a>, which\u00a0performs synchronous client-side validation of view model properties and notifies the user of any validation errors by highlighting the control that contains the invalid data, and by displaying error messages that inform the user why the data is invalid.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We released an eBook this past May on Enterprise Application Patterns using Xamarin.Forms.\u00a0The eBook focuses on core patterns and architectural guidance for developing Xamarin.Forms enterprise apps that are easier to test, maintain, and evolve. Guidance is provided on how to implement the Model-View-ViewModel (MVVM) pattern, dependency injection, navigation, validation, and configuration management, while maintaining loose [&hellip;]<\/p>\n","protected":false},"author":543,"featured_media":32807,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2,3],"tags":[4,16],"class_list":["post-32763","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","category-enterprise","tag-xamarin-platform","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>We released an eBook this past May on Enterprise Application Patterns using Xamarin.Forms.\u00a0The eBook focuses on core patterns and architectural guidance for developing Xamarin.Forms enterprise apps that are easier to test, maintain, and evolve. Guidance is provided on how to implement the Model-View-ViewModel (MVVM) pattern, dependency injection, navigation, validation, and configuration management, while maintaining loose [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/32763","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/543"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=32763"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/32763\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=32763"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=32763"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=32763"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}