Validation

Uno.Extensions.Validation provides an IValidator service which enforces that properties of an object follow a set of characteristics or behaviors represented by attributes declaratively applied to them. This is useful for ensuring that data entered by users is valid before it is saved to a database or sent to a web service.

Service registration

An extension method for IHostBuilder is provided to register the IValidator service with the DI container.

protected override void OnLaunched(LaunchActivatedEventArgs e){
    var appBuilder = this.CreateBuilder(args)
        .Configure(host => {
            host
            .UseValidation();
        });
...

By default, enabling validation will register the default Validator type with the DI container. This class implements IValidator and provides functionality to execute validation rules on validatable entities.

Using the validation service

The IValidator service is injected into the constructor of view models which specifies the IValidator service as a dependency. View models that need to validate data can then use the ValidateAsync method to execute validation rules on an object. The ValidateAsync method returns a ValueTask<T> that completes when validation is complete. The ValueTask result is an IEnumerable<ValidationResult> which contains elements that indicate whether the object is valid or not.

The following example shows how to use the service to validate a Person object:

public class PersonViewModel
{
    private readonly IValidator _validator;

    public PersonViewModel(IValidator validator)
    {
        _validator = validator;
        Person = new Person()
        {
            FirstName = "John",
            // Leaving this out will cause validation to fail
            // LastName = "Doe",
            Age = 50
        };
    }

    public Person Person { get; private set; }

    public async Task ValidatePersonAsync()
    {
        var results = await _validator.ValidateAsync(Person);
        if (results.Any())
        {
            // Handle validation errors
        }
    }
}

The service checks whether the Person object is valid and handles calling the correct validator registered for the object type. It returns a ValueTask<T> that completes when validation is complete. The ValueTask result is an IEnumerable<ValidationResult> which contains elements that indicate whether the object is valid or not. Uno Extensions enables fine-grained control over how validation is performed by allowing systematic use of a number of patterns from the .NET ecosystem. This is done by offering customization of both the validatable entity and within a validator service itself.

Validatable entities

Instances of a class that are passed into the ValidateAsync method of the default validator have three primary implementation options to allow for validation:

A common choice for entities that need to implement validation is the INotifyDataErrorInfo interface. Internally, the GetErrors method exposed by these objects is called by the validator. The .NET Community Toolkit provides an ObservableValidator class that implements this interface and provides the base functionality to execute validation rules on properties that have been decorated with validation attributes. ObservableValidator is a good choice for objects that need to be observable because it also implements ObservableObject.

Code example

An example using validation attributes is shown below:

public class Person : ObservableValidator
{
    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }

    [Range(0, 100)]
    public int Age { get; set; }
}

It is also possible to define custom validation attributes by deriving from the ValidationAttribute class. More information on custom validation can be found here.

For more information, see the reference documentation about INotifyDataErrorInfo and ObservableValidator.

See also