In this guide, we will learn how to validate ExpressWebJs REST API using DTO Validator.
DTO Validator is one of the validation features added to ExpressWebJs version 4.2 in addition to the already existing validation features (inline and external validation) in ExpressWebJs
Before we continue, what is DTO and why do we use it?
What is DTO?
DTO stands for "Data Transfer Object." It is a design pattern used in software development to transfer data between software application subsystems, layers, or components. The primary purpose of DTOs is to encapsulate and transfer data between different parts of an application without exposing the internal details of the data structures.
Key characteristics and reasons for using DTOs include:
Encapsulation: DTOs encapsulate the data to be transferred, providing a well-defined and consistent interface. This helps hide the internal details and structure of the data from other parts of the system.
Data Transformation: DTOs often involve transforming data from one format to another. This transformation may include filtering out unnecessary information, aggregating data, or converting data types to match the requirements of the sending or receiving components.
Reducing Coupling: By using DTOs, you can reduce coupling between different layers or components of your application. For example, the data structure used in the database layer might differ from what is needed in the presentation layer. DTOs provide an abstraction that allows these layers to evolve independently.
Optimizing Communication: In distributed systems or microservices architectures, DTOs are frequently used to optimize data sent over the network. By sending only the necessary data and avoiding unnecessary fields, you can improve performance and reduce network bandwidth.
Versioning: DTOs can aid in versioning of APIs or services. As requirements evolve, new versions of DTOs can be introduced without affecting the existing consumers, allowing for backward compatibility.
Why do we need validation in DTO?
DTO (Data Transfer Object) validation is essential for several reasons in software development:
Input Sanitization and Data Integrity:
Validation ensures that the data being transferred conforms to a predefined set of rules and constraints.
It helps prevent malicious input or unintentional errors that could compromise data integrity.
Business Rule Enforcement:
DTO validation allows the enforcement of business rules at the entry point of the application.
Business rules, such as required fields, data format, and length constraints, can be checked and enforced during validation.
Avoiding Invalid State:
Validating DTOs helps prevent the application from entering an invalid or inconsistent state due to incorrect or unexpected data.
By catching invalid input early in the process, you can avoid downstream issues and maintain the application's correctness.
Security:
Proper validation is crucial for security, especially when handling user input.
It helps prevent common security vulnerabilities such as injection attacks, cross-site scripting (XSS), and other forms of input-based exploits.
Improved Error Handling:
- Validation allows for more granular error handling. Instead of encountering a runtime error later in the application, you can catch validation errors early and provide meaningful error messages to users.
API Contract Compliance:
In API development, DTO validation ensures that the input received from clients adheres to the specified contract.
It helps maintain consistency and prevents clients from sending incorrect or unexpected data.
Compatibility and Interoperability:
When different components or services communicate, DTO validation ensures that the data exchanged is compatible and adheres to agreed-upon standards.
It improves interoperability between different parts of a system or between microservices.
Documentation and Communication:
Validation rules documented in the DTO serve as a clear communication tool among team members.
Developers can easily understand the expected format and constraints for data by reviewing the DTO definition.
Now that we know the meaning of DTO and why we need to validate our DTO data, let's quickly create a UserDTO in ExpressWebJs and apply validation to it.
I believe you already have your ExpressWebJs project setup, if not refer to my previous tutorial on how to install and set up ExpressWebJs or you can visit ExpressWebJs official documentation site to get started.
In your App directory, create a DTO folder. Once that is done, create a UserDTO.ts file inside the DTO folder.
import { Validate } from "Elucidate/Validator/Validate";
import "App/Rules/UUID";
export class UserDto {
@Validate(["required", "UUID"])
public id!: string;
@Validate(["required","string", "min:2", "max:35"])
public userName!: string;
@Validate(["required", "email"])
public email!: string;
@Validate(["required", "string", "min:6", "max:80"])
public password!: string;
constructor(data:UserDto){
this.id = data.id;
this.userName = data.userName;
this.email = data.email;
this.password = data.password;
}
}
In the UserDto class, we imported the Validate annotation from Elucidate, we also imported UUID. The UUID is a custom rule I created for handling UUID. You can read up on How to Create Custom Rule In ExpressWebJs From The Official Documentation site.
Before we continue, there are other features in the Validate annotation I would like to share:
- Validating an object:
@Validate([{ object: { year: ["required", "numeric"], month: ["required", "numeric"] } }])
public section!: {year:number,month:number};
- Validating array:
@Validate([{ array:["required", "numeric"] }])
public userIds!: string[];
- Validating array of objects:
@Validate([{ arrayOfObject:{userName:["required", "string"],age:["required", "numeric"]} }])
public userIds!: {userName:string,age:number}[];
Using DTO In Controller:
Now that we've created our UserDTO, let's use it in our userController register method
export class UserController extends BaseController {
constructor(private userService: UserService) {
super();
}
public async register(req: Request, res: Response) {
const user = new UserDto(req.body);
const result = await this.userService.registerUser(user);
return this.response.setStatusCode(res, result.code, result);
}
}
Conclusion:
Congratulations! You've successfully created a DTO (UserDTO), applied validation to it, and used it in our UserController register method.
Kindly:
Star to support ExpressWebJs on GitHub