NestJS提取请求参数时同步实现验证的方案问询
Hey there, let's fix your issue with validating the BeneficiaryHashIdDto alongside extracting route params. The problem with your current code is that when you pass a specific field name to @Param('beneficiaryId'), you're only binding that single string value to your DTO—so the ValidationPipe can't properly validate the DTO's structure or rules. Here are a few clean ways to solve this:
1. Bind Full Route Params to DTO + Validate
The simplest approach is to let Nest bind all route parameters directly to your DTO, then apply the ValidationPipe to validate the entire DTO.
First, make sure your BeneficiaryHashIdDto uses class-validator decorators to define validation rules:
import { IsString, IsNotEmpty, Matches } from 'class-validator'; export class BeneficiaryHashIdDto { // Add validation rules that match your requirements @IsString() @IsNotEmpty() @Matches(/^[a-f0-9]{32}$/) // Example: Enforce 32-character hex hash format beneficiaryId: string; }
Then update your controller method to bind the full params object to the DTO and validate it:
@Post('beneficiaries/:beneficiaryId/bankDetails') @HttpCode(HttpStatus.OK) async addBankDetails( // Remove the specific field name, let Nest bind all params to the DTO @Param(new ValidationPipe({ transform: true, // Convert plain object to DTO instance whitelist: true, // Strip any extra fields not defined in the DTO abortEarly: false // Return all validation errors at once })) beneficiaryHash: BeneficiaryHashIdDto, @Body() body, @Headers() headers ) { // Now beneficiaryHash is fully validated! const beneficiary = await this.beneficiaryService.getBeneficiaryIdFromHash(beneficiaryHash, ['beneficiaryId', 'currencyCode', 'countryCode']); // ... rest of your code }
2. Handle Additional Request Params (clientId, customerId)
Since you mentioned your request includes clientId and customerId, you can extend this pattern to validate those too:
- If they're route params, add them to
BeneficiaryHashIdDtowith validation rules. - If they're query params, create a separate DTO and use
@Query()with aValidationPipe:
// Example Query DTO export class RequestQueryDto { @IsString() @IsNotEmpty() clientId: string; @IsString() @IsNotEmpty() customerId: string; } // Updated controller method async addBankDetails( @Param(new ValidationPipe({ transform: true, whitelist: true })) beneficiaryHash: BeneficiaryHashIdDto, @Query(new ValidationPipe({ transform: true, whitelist: true })) query: RequestQueryDto, @Body() body, @Headers() headers ) { // Both beneficiaryHash and query are validated now const { clientId, customerId } = query; // ... rest of your code }
3. Why This Works
transform: true: Tells Nest to convert the plain JavaScript object from the request into an instance of your DTO, ensuring validation decorators are recognized.whitelist: true: Automatically removes any fields from the request that aren't defined in your DTO, preventing unexpected data from slipping through.- The
ValidationPipewill throw aBadRequestExceptionwith all validation errors if any rules are violated, so you don't need to write manual checks for basic validation.
内容的提问来源于stack exchange,提问作者Dylan Rodriguez




