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

Express应用添加Delete路由时出现Cast to ObjectId错误求助

为Express应用添加Delete路由时遇到的CastError问题解决方法

问题描述

尝试为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路径中,而非作为表单隐藏字段或查询参数传递

解决方法

  1. 修正删除表单的配置
    在对应的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,而非其他错误值。

  2. 确认路由顺序的正确性
    当前代码中app.delete('/campgrounds/:id')路由位于app.get('/campgrounds/:id')之前,这个顺序是正确的——Express会按从上到下的顺序匹配路由,确保DELETE请求不会被GET路由错误拦截。

  3. 修复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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:55:02