You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 15:39:02