Nestjs Dto校验失败返回JSON时如何将错误传递到EJS页面渲染
实现方案
NestJS默认的DTO校验抛出BadRequestException后,会走默认异常过滤器返回JSON格式响应,你可以通过自定义异常过滤器捕获校验异常,主动渲染EJS模板并传递错误信息,具体实现步骤如下:
1. 提前配置EJS模板引擎
确保项目已开启EJS渲染支持,在main.ts中添加如下配置:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { NestExpressApplication } from '@nestjs/platform-express'; import { join } from 'path'; async function bootstrap() { // 注意要指定泛型为NestExpressApplication才能调用模板相关方法 const app = await NestFactory.create<NestExpressApplication>(AppModule); // 配置静态资源目录,可根据实际路径调整 app.useStaticAssets(join(__dirname, '..', 'public')); // 配置EJS模板存放目录,默认放在根目录的views文件夹下 app.setBaseViewsDir(join(__dirname, '..', 'views')); app.setViewEngine('ejs'); await app.listen(3000); } bootstrap();
2. 自定义校验异常过滤器
创建ValidationExceptionFilter过滤器,专门捕获DTO校验抛出的BadRequestException,提取错误信息后渲染EJS页面:
import { ExceptionFilter, Catch, ArgumentsHost, BadRequestException } from '@nestjs/common'; import { Response } from 'express'; import { ValidationError } from 'class-validator'; @Catch(BadRequestException) export class ValidationExceptionFilter implements ExceptionFilter { catch(exception: BadRequestException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const statusCode = exception.getStatus(); const resData = exception.getResponse(); // 提取class-validator生成的校验错误数组 let validationErrors: ValidationError[] = []; if (typeof resData === 'object' && 'message' in resData) { validationErrors = resData.message as ValidationError[]; } // 渲染EJS模板,第一个参数为views目录下的ejs文件名,第二个参数为传递到模板的变量 response.status(statusCode).render('validation-error', { errors: validationErrors }); } }
3. 注册过滤器
你可以按需选择全局注册或者局部注册:
- 全局注册:所有路由的DTO校验失败都会返回EJS页面,在
main.ts的bootstrap函数中添加如下代码:
import { ValidationPipe } from '@nestjs/common'; import { ValidationExceptionFilter } from './filters/validation-exception.filter'; // 开启全局DTO校验 app.useGlobalPipes(new ValidationPipe()); // 注册全局校验异常过滤器 app.useGlobalFilters(new ValidationExceptionFilter());
- 局部注册:仅给指定控制器/路由生效,使用
@UseFilters装饰器绑定即可:
import { Controller, Post, Body, UseFilters } from '@nestjs/common'; import { CreateUserDto } from './dto/create-user.dto'; import { ValidationExceptionFilter } from './filters/validation-exception.filter'; @Controller('user') @UseFilters(ValidationExceptionFilter) // 绑定到控制器,当前控制器所有路由生效 export class UserController { @Post() create(@Body() createUserDto: CreateUserDto) { return '操作成功'; } }
4. EJS模板中调用错误信息
在views目录下创建validation-error.ejs文件,示例代码如下:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>参数校验失败</title> </head> <body> <h2>提交信息有误,请检查后重试:</h2> <ul> <% errors.forEach(item => { %> <li> 字段 <b><%= item.property %></b> 校验不通过: <% Object.values(item.constraints).forEach(errMsg => { %> <p><%= errMsg %></p> <% }) %> </li> <% }) %> </ul> </body> </html>
如果你需要同时兼容页面和JSON返回,可以在过滤器内判断请求头的
Accept字段,值为text/html时渲染页面,否则返回默认JSON格式即可。
内容的提问来源于stack exchange,提问作者erfan hekmati
相关产品推荐
相关产品推荐

