Express应用添加Delete路由时出现Cast to ObjectId错误求助
问题描述
尝试为Express应用添加Delete路由,代码如下:
const express = require('express'); const mongoose = require('mongoose'); const app = express(); const path = require('path'); const campground = require('./models/campground'); const methodOverride = require('method-override'); mongoose.connect('mongodb://127.0.0.1:27017/yelpcamp', { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => { console.log("CONNECTION OPEN!!!") }) .catch(err => { console.log("OH NO ERROR!!!!") console.log(err) }); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.use(express.urlencoded({ extended: true })); app.use(methodOverride('_method')) app.get('/', (req, res) => { res.render('home') }); app.get('/campgrounds', async (req, res) => { const campgrounds = await campground.find({}); res.render('campgrounds/index', { campgrounds }); }); app.get('/campgrounds/new', (req, res) => { res.render('campgrounds/new'); }); app.post('/campgrounds', async (req, res) => { const camp = await new campground(req.body.campground); await camp.save(); res.redirect('/campgrounds'); }); app.delete('/campgrounds/:id', async (req, res) => { const { id } = req.params; await campground.findByIdAndDelete(id); res.redirect('/campgrounds'); }); app.get('/campgrounds/:id', async (req, res) => { const { id } = req.params; const foundCampground = await campground.findById(id); res.render('campgrounds/show', { foundCampground }); }); app.get('/campgrounds/:id/edit', async (req, res) => { const { id } = req.params; const foundCampground = await campground.findById(id); res.render('campgrounds/edit', { foundCampground }); }); app.put('/campgrounds/:id', async (req, res) => { const { id } = req.params; const campgroundBody = req.body; console.log(campgroundBody); await campground.findByIdAndUpdate(id, campgroundBody.foundCampground); const foundCampground = await campground.findById(id); res.render('campgrounds/show', { foundCampground }); }); app.listen('3000', () => { console.log('Serving on Port 3000'); });
运行时持续遇到错误:
CastError: Cast to ObjectId failed for value "_method=DELETE" (type string) at path "_id" for model "Campground"
调整路由顺序后问题依旧,需要解决该错误。
错误原因
这个错误是因为请求的URL路径中,:id参数被错误地设置为了_method=DELETE,而非MongoDB文档的合法ObjectId。这通常是由于提交删除请求的表单配置错误导致的:
- 表单的
action属性未正确指向对应营地的ID路径 - 错误地将
_method参数嵌入到URL路径中,而非作为表单隐藏字段或查询参数传递
解决方法
修正删除表单的配置
在对应的EJS视图(比如show.ejs或index.ejs)中,确保删除表单的action指向当前营地的ID,同时通过隐藏字段传递_method=DELETE:<form action="/campgrounds/<%= foundCampground._id %>" method="POST"> <input type="hidden" name="_method" value="DELETE"> <button type="submit">删除营地</button> </form>要确保
action属性中的<%= foundCampground._id %>能正确渲染出营地的ObjectId,而非其他错误值。确认路由顺序的正确性
当前代码中app.delete('/campgrounds/:id')路由位于app.get('/campgrounds/:id')之前,这个顺序是正确的——Express会按从上到下的顺序匹配路由,确保DELETE请求不会被GET路由错误拦截。修复PUT路由的潜在bug
虽然这不是当前错误的直接原因,但PUT路由中存在参数错误:// 原错误代码 await campground.findByIdAndUpdate(id, campgroundBody.foundCampground); // 修正为(和POST路由保持一致,使用req.body.campground) await campground.findByIdAndUpdate(id, req.body.campground);因为新建营地时使用的是
req.body.campground,编辑表单的字段也应该是name="campground[title]"这类结构,所以更新时要对应使用req.body.campground作为更新内容。
内容的提问来源于stack exchange,提问作者aemf

