如何使用params动态创建链接,解决新建博客ID未生成导致的类型转换错误
错误原因
你遇到的类型转换报错是Express路由匹配顺序不合理导致的:
你代码中先定义了动态参数路由/blog/:id,后定义静态路由/blog/posted。Express会按照路由的书写顺序逐行匹配,当你发布完博客请求/blog/posted时,会被/blog/:id路由优先捕获,路径中的posted会被当做id参数传入MongoDB查询逻辑。MongoDB的_id要求为合法的ObjectId格式,普通字符串posted无法完成类型转换,因此触发报错。
修复方案
- 调整路由定义顺序,将静态路由
/blog/posted移到动态参数路由/blog/:id之前,确保静态路由优先匹配:
// 先定义静态路由 router.get("/blog/posted", ensureAuthenticated, (req, res) => { res.render("blogPosted", { user:req.user, }); }); // 再定义动态参数路由 router.get("/blog/:id", ensureAuthenticated, (req, res) => { let id = req.params.id; console.log(`id is ${id}`) Blog.findOne({_id: id}) .then((result) => { console.log(`result: ${result}`) res.render("viewPost", { post: result, user: req.user, }); }) .catch((error) => { console.log(error) }) });
- 新增id合法性校验,避免无效的数据库查询,提前拦截非法参数:
const { Types } = require('mongoose'); router.get("/blog/:id", ensureAuthenticated, (req, res) => { let id = req.params.id; // 校验id格式合法性 if (!Types.ObjectId.isValid(id)) { return res.status(404).render('404'); // 或者跳转到你自定义的错误页 } // 后续查询逻辑不变 Blog.findOne({_id: id}) // ... 原有逻辑 })
- 如果你需要发布完成后直接跳转到新博客的详情页,可以修改保存成功后的跳转逻辑,直接使用数据库返回的生成后的id跳转:
router.post("/blog-new", (req, res) => { const blog = new Blog({ title: req.body.title, snippet: req.body.snippet, body: req.body.blog, }) blog.save() .then((result) => { // 直接跳转到新发布的博客详情页 res.redirect(`/blog/${result._id}`); }) .catch((error) => { console.log(error); }) })
内容的提问来源于stack exchange,提问作者Peter Gibbons
相关产品推荐
相关产品推荐

