Data Validation in C# - JU-DEV-Bootcamps/ERAS GitHub Wiki

Introduction

Validating user input is fundamental to build a secure and reliable application. In C#, there are multiple ways to validate the data our API receives, but we are going to focus on two approaches: built-in validation with Data Annotations and third-party validations with FluentValidation.

Alternatives

Data Annotations

Data Annotations are attributes applied to model properties that enforce validation rules, set data formatting, and configure database mapping. C# has a comprehensive list of built-in data annotations that fit most of the basic validation scenarios.

Using data annotations is simple and direct as the only needed action is to add the specific attribute to the model property and set up the setting for that attribute, if required. In the following example, we are using the [Required] and the [StringLength] annotations on the Answer property to ensure that it has a value which length should be between 1 and 500 characters.

One of the advantages of data annotations is that we can build custom validation attributes to fit a project's specific requirements. For instance, we use the [NoSqlInjection] custom validator in the Answer property to prevent SQL Injection attacks to the server. This custom attribute was built by extending the ValidationAttribute abstract class.

For more complex validations, the IValidatableObject interface allows to define custom validation rules inside of a model. This is useful, for example, for cross-field validations.

FluentValidation

FluentValidation is a .NET library for building strongly-typed validation rules. It provides a cleaner way to define rules while following a separation of concerns as validators are separate classes that extend the AbstractValidator<T> class. It is faster than built-in data annotations and it is useful for complex and conditional validations. It also supports validation chaining and inheritance for more complex scenarios.

For example, the AssessementValidator class defines a set of rules for validating the values of the Assessment entity. As this entity has nested Interventions we can set validators for the nested entities and get an in-depth validation for the base entity.

Data Validation in ERAS Backend

The current context of ERAS backend follows a mixed approach where most of the validations are done using Data Annotations. For more complex validations, especially related to Assessments and Interventions, FluentValidation is used to keep validations clean, readable and maintainable.

Although a migration from Data Annotations to FluentValidation would fit better the principles of separation of concerns and testability, the current mixed approach is suitable for the ERAS entities context. Adding FluentValidation to all the entities entails rewriting working code, losing OpenAPI/Swagger reflection, and introducing more complexity into the application without a tangible improvement.

As a recommendation, new DTOs and purpose-oriented DTOs (like CreateEntityDTO and UpdateEntityDTO) must implement FluentValidation as well as complex new use cases in the application. But, unless Data Annotations are actively becoming an obstacle in the development process, no migration should be made.

References