DEV Community

loading...
DotVVM

DotVVM:Build Conditional Validation Attribute

miroprocessor profile image Amir Ismail Updated on ・3 min read

Validation in DotVVM

Validation in DotVVM is very similar to validation in ASP.Net MVC and ASP.Net Core.
You can validate your view model by using validation attributes. DotVVM do client side validation for only the following attributes

  • Required
  • Compare
  • EmailAddress
  • Range
  • RegularExporession

If the user input is not valid you have two controls you can use to show error messages

  • Validator Control : shows error message against the target input control
  • VaicationSummary Control: shows the summary for all errors in your view model.

Straight Validation

Suppose we have a small registaration form that requires the user to enter his/her name, gender, and age. All fields are required. To validate user's input we just need to annotate our viewmodel properties with Required attribute. Our ViewModel class will be like

[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }

public string Gender { get; set; }

[Required(ErrorMessage = "Age is required")]
public int? Age { get; set; }

In our view we will use only Validator control to show error messages.

<dot:Literal class="control-label col-md-3" Text="Name"></dot:Literal>
<dot:TextBox Text="{value: Name}" class="form-control" Type="Normal"></dot:TextBox>
<dot:Validator HideWhenValid="true" Value="{value: Name}" ShowErrorMessageText="true"></dot:Validator>
<br /><br />
<dot:Literal class="control-label col-md-3" Text="Gender"></dot:Literal>
<dot:RadioButton CheckedItem="{value: Gender}" CheckedValue="{value: "1"}" Text="Male"></dot:RadioButton>
<dot:RadioButton CheckedItem="{value: Gender}" CheckedValue="{value: "2"}" Text="Female"></dot:RadioButton>
<br /><br />
<dot:Literal class="control-label col-md-3" Text="Age"></dot:Literal>
<dot:TextBox Text="{value: Age}" class="form-control" Type="Number"></dot:TextBox>
<dot:Validator HideWhenValid="true" Value="{value: Age}" ShowErrorMessageText="true"></dot:Validator>
<br /><br />
<dot:Button Click="{command: Save()}" Text="Save" class="btn btn-outline-secondary btn-sm"></dot:Button>

Foucs on validator control we set

  • HideWhenValid to true to show error message only if the user's input is not valid
  • ShowErrorMessageText to true to show error message that comes from our ViewModel

Conditional Validation

We know women don't like to tell their real age so we want to respect this in our registeration form by validating the age feild only if the user selected male as his gender but if gender was female will not force her to enter her age.

In DotVVM there is no conditional Required validation, so we need to build our custom validation attribute.
What we actually need is just a new class that inherts ValidationAttribute class and override IsValid method with our logic.

public class RequiredIfAttribute : ValidationAttribute
{
    public string PropertyName { get; set; }
    public object Value { get; set; }

    public RequiredIfAttribute(string propertyName, object value, string errorMessage = "")
    {
        PropertyName = propertyName;
        ErrorMessage = errorMessage;
        Value = value;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var instance = validationContext.ObjectInstance;
        var type = instance.GetType();
        var proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
        if (proprtyvalue.ToString() == Value.ToString() && value == null)
        {
            return new ValidationResult(ErrorMessage);
        }
        return ValidationResult.Success;
    }
}

First we added a PropertyName property to check its value to start validation of skip it and Value property that will check against it.
Inside IsValid() method we are using reflection to get that value of the property and check if its value is equal to the provided value in the attribute and the value of the current field is null then the field value is not valid otherwise the field is not required.

In our ViewModel we will replace Required attribute that decorate Age property with our new custom attribute RequiredIf.

 [RequiredIf(nameof(Gender), "1", ErrorMessage = "Age is required")]
 public int? Age { get; set; }

Frist parameter is the PropertyName and second paramter is the Value of the Gender that makes Age field is required (I used 1 and 2 for simpilcity).

Restriction

Our custom validation is server side validation. DotVVM need you to submit your form to be able to run your custom validation.

Summary

In this post we validated our ViewModel like we used to do in ASP.Net MVC or ASP.Net Core and also created our custom validation to validate fields based on another field value.
You can find the full source code on github.

Discussion (0)

pic
Editor guide