Form validation in ASP.NET & DotVVM
Tags: webdev, html, dotnet, csharp
Published: 2021-05-20 20:26:27

Hey, there! Nice to say hello. When working with web forms in applications with ASP.NET, it is important to be able to validate the data that can be sent to the server for storage or modification. 

In this new entry, we'll learn how to validate forms set with DotVVM so that asterisks or validation messages can be displayed for a specified field. 

###**Example for validations on forms**###

To understand how validations work on forms in an ASP.NET DotVVM, let's look at an example. Let's say we have a page for registering and authentication users, and we want you to validate the fields in these forms. 

The page would be displayed as follows:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f3irti7466lh9jq39ovb.png)

However, as it is well known, DotVVM is based on the MVVM pattern (Model, View, ViewModel), when using classes with C- and visual elements with HTML. In this sense, let's look at each of these parts. 

####**Model**

First, in this section, we can establish data models that represent the information that users will send to the application through a web form. This 'Model' shall provide as much validation information as possible about the data that comprises it through the use of metadata definition attributes (`DataAnnotations`).

Given these considerations, we may encounter one model for the user authentication section, and another for registration. With regard to the registration model, this would look like this:

```csharp
public class CreateAccountForm : IValidatableObject
{
    [Required]
    public string Name { get; set; }

    [Required]
    [EmailAddress]
    public string Email { get; set; }

    [Required]
    [MinLength(8)]
    public string Password { get; set; }

    [Required]
    [Compare(nameof(Password))]
    public string Password2 { get; set; }

    public bool AgreeWithConditions { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!AgreeWithConditions)
        {
            yield return new ValidationResult(
                "You need to agree with terms & conditions.",
                new[] { nameof(AgreeWithConditions) }
            );
        }
    }
}
```

With ASP.NET data annotations, we can find for example the annotation `[Required]`, which allows you to set an attribute to be required when filling out a form. We can also set the minimum or maximum length that an attribute can have, validate that the field has a certain format, for example, email formats, credit cards, phone numbers, among others. 

All the annotations that we can consider in .NET 5 can be queried at the following address: [System.ComponentModel.DataAnnotations Namespace](https://docs.microsoft.com/en-US/dotnet/api/system.componentmodel.dataannotations?redirectedfrom=MSDN&view=net-5.0).

Within the model, we can also establish our own validations, for example, in this case, it can be verified that the user is in accordance with the terms and conditions at the time of registration. If validation is not met, a custom error message can be set.

####**ViewModel**

Now, in the ViewModel we need to set the objects that will allow us to store the collected data in the login and registration forms:

```csharp
public SignInForm SignInForm { get; set; } = new SignInForm();

public CreateAccountForm CreateAccountForm { get; set; } = new CreateAccountForm();
```
Finally, we will also have to set the methods that allow us to perform the user-startup and registration operation. With regard to the method to start the session, in the project we can find something like this:

```csharp
public void SignIn()
{
    // this code actually doesn't sign anyone in - it's just a validation demo
    // you can use e.g. SignInManager.PasswordSignInAsync from ASP.NET Core Identity

    if (SignInForm.Email == "info@dotvvm.com" && SignInForm.Password == "Password1234")
    {
        Context.RedirectToRoute("Success");
    }
    else
    {
        // TODO: report invalid credentials
        Context.ModelState.Errors.Add(new ViewModelValidationError()
        {
            ErrorMessage = "Incorrect credentials."
        });
        Context.FailOnInvalidModelState();
    }
}
```

An interesting aspect to mention is that we can work with a `ModelState`. This object allows us to perform additional validation checks on the method itself, and report additional validation errors to the user. This is used to perform validations that require access to the SQL database, for example, to review a user's credentials are correct (this is an example for illustrative purposes). 

####**View**

With models and view models set, we can now structure our HTML forms with DotVVM controls set for this purpose. For this case, let's look at the code for the login form:

```csharp
<form DataContext="{value: SignInForm}">
    <div class="form-group">
        <label for="signin-email">E-mail address</label>
        <dot:TextBox Type="email"
                        ID="signin-email"
                        class="form-control"
                        Text="{value: Email}"                                         
                        Validator.Value="{value: Email}"
                        placeholder="Enter your e-mail" />

    </div>
    <div class="form-group">
        <label for="signin-password">Password</label>
        <dot:TextBox Type="Password"
                        ID="signin-password"
                        class="form-control" 
                        Text="{value: Password}"
                        Validator.Value="{value: Password}"
                        placeholder="Password" />
    </div>
                        
    <dot:ValidationSummary Validation.Target="{value: _this}"
                            IncludeErrorsFromTarget="true"
                            HideWhenValid="true"
                            class="alert alert-danger"/>

    <dot:Button IsSubmitButton="true" 
                ButtonTagName="button"
                class="btn btn-primary"
                Click="{command: _root.SignIn()}"
                Validation.Target="{value: _this}">
        Sign In
    </dot:Button>
</form>
```

Here we can find two TextBoxes, the first for email, and the second for the user's password. In this type of control, we can put the Validator attribute, where we must specify the value that we want to validate, for example: `Validator.Value="{value: Email}`. Here validation will be performed in accordance with the provisions of the model.

We can also display an error summary with the `ValidationSummary` control, according to the `Validators` set within the form. 

In an example scenario we might encounter the following case:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7et0eyo415c7dcyuvk0n.png)

Where the email entered is not in the correct format, and the password field is empty. These validations have been performed in accordance with the annotations in the model.

In another scenario, we might encounter the following:

![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2lavsmketpstapss4p2r.png)

In this case, it was because the credentials entered are incorrect. This validation was done in the method to log in with the 'ModelState' for custom validations.  

And in this quick and easy way, we will be able to validate our web forms within ASP.NET with DotVVM.

The source code for this example is available in this GitHub repository: [DotvvmValidationSample](https://github.com/riganti/dotvvm-minutes/tree/master/09_Validation/DotvvmValidationSample). 

###**Additional Resources** 

If you like to continue acquiring or reinforcing knowledge in this area, here are some additional resources that can be very useful:

+ [Building a Dashboard with ASP.NET Core and DotVVM](https://dev.to/esdanielgomez/building-a-dashboard-with-asp-net-core-and-dotvvm-349).
+ [HTML templates for repetitive elements in ASP.NET & DotVVM](https://dev.to/esdanielgomez/html-templates-for-repetitive-elements-in-asp-net-dotvvm-1670)
+ [Working with web services through ASP.NET Core and DotVVM (A step-by-step guide)](https://dev.to/dotvvm/working-with-web-services-through-asp-net-core-and-dotvvm-a-step-by-step-guide-2le).

Thank you very much for reading this article, I hope that this demo can be of help for the organization and dissemination of events. If you have any questions or ideas that you need to discuss, it will be nice to be able to collaborate and together exchange knowledge with each other.

If you like, we can stay in touch on [Twitter](https://twitter.com/esDanielGomez), or in [Telegram](https://t.me/esdanielgomez) too. :)