I'm trying to make a nodejs\ExpressJs backend for a small project. The backend is split into services, controllers and router files. While testing the updateProduct (to update the fields of a product that already exists in database) function on postman using a x-www-form-urlencoded body, I got the following error:
{
"err": {
"stringValue": "\"{ name: 'Hp', description: 'Pavillion', price: '20000' }\"",
"valueType": "Object",
"kind": "ObjectId",
"value": {
"name": "Hp",
"description": "Pavillion",
"price": "20000"
},
"path": "_id",
"reason": {},
"name": "CastError",
"message": "Cast to ObjectId failed for value \"{ name: 'Hp', description: 'Pavillion', price: '20000' }\" (type Object) at path \"_id\" for model \"Product\""
}
}
Screen of postman form : This is the code I used in their respective files, I tried logging a message into the console to see whether they are called upon, and yes they were called as intended.
//service file
const updateProduct = async(product)=>{
return await Product.findByIdAndUpdate(product._id, product)
}
//controller file
const updateProduct = async(req, res)=>{
try{
const result = await productService.updateProduct(req.body)
res.status(200).json(result)
}
catch(error){
res.status(500).json({err:error})
}
}
//router file
router.put("/:id", productController.updateProduct)
I tried changing the code in the service layer to the following, it didn't work, but it not generate the same problem.
const updateProduct = async(product) => {
return await Product.findByIdAndUpdate(
product._id,
{
$set: {
name: product.name,
price: product.price,
description: product.description
}
},
{ new: true }
);
};
If relevant I'm using Mongoose and other methods such as adding or deleting work as intended. Thanks
CodePudding user response:
Problem:
You have to get the _id
of the desired product from the params
not from the req.body
which return null
like:
this:
return await Product.findByIdAndUpdate(product._id, product);
would turn into:
return await Product.findByIdAndUpdate(undefined, {
"name": "Hp",
"description": "Pavillion",
"price": "20000"
})
and of course, the record won't get updated.
Solution:
your controller should look like this (I've used the path
):
//controller file
const updateProduct = async(req, res)=>{
try{
const result = await productService.updateProduct(req.params.id, req.body)
res.status(200).json(result)
}
catch(error){
res.status(500).json({err:error})
}
}
and your service should look like this:
//service file
const updateProduct = async(id, product)=>{
return await Product.findByIdAndUpdate(id, product)
}
``