yamakai
@yamakai

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

CastError: Cast to ObjectId failed が発生する原因と解決方法について

解決したいこと

プログラミングをはじめて1ヶ月半ぐらいのものです。
udemyのweb-developer-bootcampという講義でNode.jsとExpressを使って、MongoDBでデータを管理するYelpCampというキャンプ場管理アプリを開発しています。
新規登録フォームからキャンプ場を追加し、その詳細ページに遷移することはできるのですが、詳細ページから編集ページに移動しようとするエラーが発生します。
質問
・なぜreq.params.idに不正な値(例えば画像URL)が入ってしまうのか、原因が分かりません。
・このエラーを防ぐためのルーティングやバリデーションのベストプラクティスがあれば教えてください。
・MongoDBのObjectIdとして正しくIDを受け取る方法についてアドバイスをお願いします。

発生している問題・エラー

エラー発生場所:
編集ページのルート app.get("/campgrounds/:id/edit", ...) にアクセスしたとき
現象:
req.params.idの値がMongoDBのObjectIdとして認識されず、画像URLなどのような不正な文字列がIDとして扱われてしまい、CastErrorが発生しているようです。
期待する動作:
/campgrounds/:id/editの:id部分にMongoDBのObjectIdが入るべきですが、フォームから送信したデータや他のフィールドと混同されている可能性があります。
出ているエラーメッセージを入力


CastError: Cast to ObjectId failed for value "nfjewnafienfiawnfiene" (type string) at path "_id" for model "Campground"

該当するソースコード

app.get("/campgrounds/:id/edit", async (req, res) => {
    console.log(req.params); // ここでIDを確認しています
    try {
        const editCampground = await Campground.findById(req.params.id);
        if (!editCampground) {
            return res.status(404).send('Campground not found');
        }
        res.render("campgrounds/edit", { editCampground });
    } catch (e) {
        res.status(500).send(e.message);
    }
});

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。
・**console.log(req.params)**でreq.params.idを確認したところ、期待しているObjectIdではなく、画像URLのような文字列が出力されました。

・ルートの順番を確認し、/campgrounds/newのようなルートを先に定義しています。

・show.ejsでのリンク生成時に、campground._idを正しく指定しています。
編集する

0

2Answer

・なぜreq.params.idに不正な値(例えば画像URL)が入ってしまうのか、原因が分かりません。

詳細ページをレンダリングする際に編集ページへのリンクを生成しているはずですが、その URL を組み立てるときに渡す id パラメータが期待する値になっていないことが考えられます。

・このエラーを防ぐためのルーティングやバリデーションのベストプラクティスがあれば教えてください。

上記の理由であれば、防ぐ方法は気をつけるくらいしかありません。

・MongoDBのObjectIdとして正しくIDを受け取る方法についてアドバイスをお願いします。

詳細ページのコードを貼っていただければ何か分かるかもしれません。

1Like

アドバイスありがとうございます!!!

詳細ページで編集ページへのリンクを生成している部分のコードを以下に貼り付けます。この部分が原因かもしれないとご指摘いただいたので、確認をお願いできますでしょうか。

show.ejs
<% layout('layouts/boilerplate') -%>

<div class="row">
    <div class="offset-3 col-6">
        <div class="card mb-4">
            <img src="<%= campground.image %>" class="card-img-top" alt="">
            <div class="card-body">
                <h5 class="card-title">
                    <%= campground.title %>
                </h5>
                <p class="card-text">
                    <%= campground.description %>
                </p>
            </div>
            <ul class="list-group list-group-flush">
                <li class="list-group-item text-muted">
                    <%= campground.location %>
                </li>
                <li class="list-group-item">¥<%= campground.price %>/泊</li>

            </ul>
            <div class="card-body">
                <a class="btn btn-info" href="/campgrounds/<%= campground._id %>/edit">編集する</a>
                <form class="d-inline" action="/campgrounds/<%= campground._id %>?_method=delete" method="post">
                    <button class="btn btn-danger">削除する</button>
                </form>
            </div>
        </div>
        <h2>レビュー</h2>
        <form class="mb-3 validated-form" action="/campgrounds/<%= campground._id %>/reviews" method="post"
            novalidate>
            <div class="mb-3">
                <label for="rating" class="form-label">評価</label>
                <input type="range" class="form-range" id="rating" min="1" max="5" name="review[rating]">
            </div>
            <div class="mb-3">
                <label for="body" class="form-label">コメント</label>
                <textarea name="review[body]" id="body" class="form-control" cols="30" rows="3" required></textarea>
                <div class="valid-feedback">
                    OK!
                </div>
            </div>
            <button class="btn btn-success">投稿する</button>
        </form>
        <% for(let review of campground.reviews) { %>
            <div class="mb-3">
                <p>評価:<%= review.rating %>
                </p>
                <p>コメント:<%= review.body %>
                </p>
            </div>
            <% } %>

    </div>
</div>

「Edit」ボタンのリンク生成部分では、campground._idを使ってMongoDBのObjectIdを渡しているつもりです。ただし、詳細ページから編集ページに遷移する際に、req.params.idが正しいObjectIdではなく、不正な文字列(例: 画像URL)になってしまうことがあります。

この部分に何か問題があるか、または他の可能性についてアドバイスいただけると助かります。

0Like

Your answer might help someone💌