質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.79%

新規登録(Create)ページからデータ登録後、登録内容が反映された状態で直接、編集(Edit)ページに遷移したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 570

score 43

前提・実現したいこと

タイトルにも書かせていただいているのですが、
①新規登録ページで、フォームの内容を登録
②登録後に、(普通なら一覧ページ(Index.vbhtml)に遷移するところを)編集ページ(Edit.vbhtml)へ遷移し、
かつ、登録した内容も反映(既に各フォームに入力されている)状態にしたい。

※下記のモデルファイルで定義している、複合主キーである「id」と「itemId」の2つを手がかりに、新規登録後、
DBから、登録直後のレコードを取得したいのですが、その部分でエラーが発生してしまいます。

発生している問題・エラーメッセージ

コントローラファイルの
「Dim test As Test = db.Tests.Where(Function(data) data.id = id).Where(Function(data) data.itemId = itemId)」
の箇所で以下のエラーが発生

'System.Data.Entity.Infrastructure.DbQuery`1[MvcApp.Test]' のオブジェクトを型 'MvcApp.Test' にキャストできません。'

その後、同じ箇所を
「Dim test As Test = CType(db.Tests.Where(Function(data) data.CampaignId = id).Where(Function(data) data.CampeignName = CampaignName), DbQuery)」
と修正してみるも、

'DbQuery' の値を 'Test' に変換できません。


というエラーが発生したため、いったん元の状態に戻しました。

該当のソースコード

Test.vb(モデルファイル)

Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel

Public Class Test

    <Key()>
    <DisplayName("テストID")>
    Public Property Id As String

    <DisplayName("テスト名")>
    Public Property Name As String

    <Key()>
    <DisplayName("商品ID")>
    Public Property itemId As String

    <DisplayName("商品名")>
    Public Property itemName As String

End Class

MyMVCContext.vb(コンテキストファイル)

Imports System.Data.Entity

Public Class MyMvcContext : Inherits DbContext
    Public Property Tests As DbSet(Of Test) ' Testsテーブル
End Class

Create.vb.html(新規登録画面のファイル)

@ModelType MvcApp.Test
@Code
    ViewData("Title") = "Create"
End Code

<h2>Create</h2>

@Using (Html.BeginForm()) 
    @Html.AntiForgeryToken()

    @<div class="form-horizontal">
    <h4>Test</h4>
    <hr />
    @Html.ValidationSummary(True, "", New With {.class = "text-danger"})
    <div class="form-group">
        @Html.LabelFor(Function(model) model.id, htmlAttributes:=New With {.class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(Function(model) model.id, New With {.htmlAttributes = New With {.class = "form-control"}})
            @Html.ValidationMessageFor(Function(model) model.id, "", New With {.class = "text-danger"})
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(Function(model) model.Name, htmlAttributes:=New With {.class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(Function(model) model.Name, New With {.htmlAttributes = New With {.class = "form-control"}})
            @Html.ValidationMessageFor(Function(model) model.Name, "", New With {.class = "text-danger"})
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(Function(model) model.itemId, htmlAttributes:=New With {.class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(Function(model) model.itemId, New With {.htmlAttributes = New With {.class = "form-control"}})
            @Html.ValidationMessageFor(Function(model) model.itemId, "", New With {.class = "text-danger"})
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(Function(model) model.itemName, htmlAttributes:=New With {.class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(Function(model) model.itemName, New With {.htmlAttributes = New With {.class = "form-control"}})
            @Html.ValidationMessageFor(Function(model) model.itemName, "", New With {.class = "text-danger"})
        </div>
    </div>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>
End Using

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@Section Scripts 
    @Scripts.Render("~/bundles/jqueryval")
End Section

※TestsController.vb(コントローラのファイル)

Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Linq
Imports System.Net
Imports System.Web
Imports System.Web.Mvc
Imports MvcApp

Namespace Controllers
    Public Class TestsController
        Inherits System.Web.Mvc.Controller

        Private db As New MyMvcContext

        ' GET: Tests
        Function Index() As ActionResult
            Return View(db.Tests.ToList())
        End Function

        ' GET: Tests/Create
        Function Create() As ActionResult
            Return View()
        End Function

        ' POST: Tests/Create
        '過多ポスティング攻撃を防止するには、バインド先とする特定のプロパティを有効にしてください。
        '詳細については、https://go.microsoft.com/fwlink/?LinkId=317598 を参照してください。
        <HttpPost()>
        <ValidateAntiForgeryToken()>
        Function Create(<Bind(Include:="id,Name,itemId,itemName")> ByVal test As Test) As ActionResult
            If ModelState.IsValid Then
                db.Tests.Add(test)
                db.SaveChanges()

                TempData("id") = test.id
                TempData("itemId") = test.itemId
                Return RedirectToAction("Edit")
            End If
            Return View(test)
        End Function

        ' GET: Tests/Edit/5
        Function Edit(ByVal id As String, ByVal itemId As String) As ActionResult
            id = TempData("id")
            itemId = TempData("itemId")
            If IsNothing(id) Then
                Return New HttpStatusCodeResult(HttpStatusCode.BadRequest)
            End If
            Dim test As Test = db.Tests.Where(Function(data) data.id = id).Where(Function(data) data.itemId = itemId)

            If IsNothing(Test) Then
                Return HttpNotFound()
            End If
            Return View(Test)
        End Function

        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If (disposing) Then
                db.Dispose()
            End If
            MyBase.Dispose(disposing)
        End Sub
    End Class
End Namespace

Edit.vbhtml(編集画面用のファイル)

@ModelType MvcApp.Test
@Code
    ViewData("Title") = "Edit"
End Code

<h2>Edit</h2>

@Using (Html.BeginForm())
    @Html.AntiForgeryToken()

    @<div class="form-horizontal">
        <h4>Test</h4>
        <hr />
        @Html.ValidationSummary(True, "", New With { .class = "text-danger" })
        @Html.HiddenFor(Function(model) model.Id)

        <div class="form-group">
            @Html.LabelFor(Function(model) model.Name, htmlAttributes:= New With { .class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(Function(model) model.Name, New With { .htmlAttributes = New With { .class = "form-control" } })
                @Html.ValidationMessageFor(Function(model) model.Name, "", New With { .class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(Function(model) model.itemId, htmlAttributes:= New With { .class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(Function(model) model.itemId, New With { .htmlAttributes = New With { .class = "form-control" } })
                @Html.ValidationMessageFor(Function(model) model.itemId, "", New With { .class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(Function(model) model.itemName, htmlAttributes:= New With { .class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(Function(model) model.itemName, New With { .htmlAttributes = New With { .class = "form-control" } })
                @Html.ValidationMessageFor(Function(model) model.itemName, "", New With { .class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
End Using

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@Section Scripts 
    @Scripts.Render("~/bundles/jqueryval")
End Section

試したこと

コントローラのCreateアクションや、Editアクションにブレイクポイントを貼りつつ、処理の流れを確認しましたが、
エラー箇所の少し前、
id = TempData("id")
itemId = TempData("itemId")
の箇所については、Create.vbhtmlで入力した値が、取得できていることを確認できました。

補足情報(FW/ツールのバージョンなど)

※一部、質問に関係がないと思われるファイルや、コードは削除しております。
※また、フォームの入力制限に関しても、現段階の目的からは外れるため、まだ何も実装していない状態です。

統合開発環境
Visual Studio2019
(言語:VB.NET、プロジェクトテンプレート:ASP.NET Webアプリケーション MVC)

使用PC
Windows10

※平日は仕事のため、返信が19:30以降になります。
※休日の返信は不定期です。
申し訳ございませんが、どうぞよろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

問題が出ている式の最後に FirstOrDefault() を追加したらどうなりますか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/06/10 21:12 編集

    >SurferOnWww様

    返信が遅くなり申し訳ございません。
    いただいた回答の中でのコメント上でのやりとりだったからか、通知が来ておらず、先程、確認いたしました。
    以下、こちらで調査した結果のご報告と、コメントの返信をさせていただきます。

    >例外の理由は何か理解していますか?
    最初のエラーの理由は、型が異なることによるエラー
    2つめのエラーの理由は、LINQ to Entitiesで使用できないメソッドが使われていることによるエラー
    を指しているものと思っております。

    >FirstOrDefault がダメで Single で解決したというのは考えにくいです。
    →結論を申し上げますと、FirstOrDefaultでも同様に動作しました。

    最初にいただいた回答に対して、エラーが起こった旨を報告しましたが、その理由を順を追って説明させていただきます。

    1.今回、質問させていただいているコードとは別に、元のコードがあります。そのコードは、質問内容に書かせていただいている「省略前の」コードではなく、また別のコードです。(仮にAとします)
    そして、そのコードAは、自宅で確認することができないコードのため、自宅では(基本的にやろうとしていることは同じ)似たようなコードを書いて勉強しております。(自宅で書いているコードをBとします)

    2.もともとはAで書いていたコードで起こったエラーでしたが、自宅で、似たようなコードBを作成し、エラー解決を試みておりました。

    3.「'MvcApp.Test' にキャストできません」というエラーはAにもBにも同様に発生しておりました。
    ※このタイミングでteratailに質問投稿いたしました。

    4.SurferOnWww様の返信を確認した際は、「Aのコードは触ることができるがBのコードは触ることができない」状況にあり、
    Aのコードの方に、「FirstOrDefault」を試したところ、
    「ストア式に変換できません」のエラーが発生しました。
    ※このタイミングでteratailに「エラー解決できない旨」の返信をいたしました。

    5.その後、自宅にてBのエラー解決を引き続き、行っている際、「.Single」で期待通りの結果が得られたため、teratailにて「解決」の報告をさせていただきました。
    ※その際、(FirstOrDefaultは試していなかったため)自身では、「.Single」だからこそ上手く動作した、と思っておりました。

    6.本日、Aのコードを触るタイミングで、(多少コードを触った後でしたが)「.Single」で当初のエラーは解決できたことを確認。
    ※別のエラーが発生したため、「編集画面に遷移し、(新規登録時の)値が表示されるところまで」を確認しました。ただ、また別の問題でエラーが発生したため、その先まで進むことができておりません。
    ※「その先」とは、編集画面に遷移後、さらに入力値を編集し、登録するまでの処理ですが、こちらに関してはAとBで大分コードが異なるため、質問内容の範疇を超えるため、割愛させていただきます。

    7.先程、自宅にてSurferOnWww様の返信を確認し、Bのコードで「FirstOrDefault」を試してみると、「Single」同様に、エラー解決することを確認。
    ※こちらに関しては、Aで起こったようなエラーは発生せず、遷移後の編集画面で編集し、更新ボタンをクリックしても、内容が更新されるところまでを確認。


    長くなりましたが、
    もともと質問したいと提示させてもらっているBのコードについては、(SurferOnWww様の回答通り)
    「FirstOrDefault」(もちろんSingleも)で、解決となりました。

    今回の質問の基となっているAのコードについては、「FirstOrDefault」によりエラー箇所について解決できたが、それだけで、完全に想定通りの動作とはなっていない、というのが現状です。
    (今回の質問内容の範疇を超えているので、また別問題となりますが)

    AとBのコードの違いについては、色々とあるのですが、事細かく両者を見比べることができない環境にあります。
    また、幸い「質問内容」に対する解決法は、「いただいた回答」に間違いはございませんので、その先のエラーについては、いったん自力で解決を試みたいと思います。

    長々と失礼いたしました。

    キャンセル

  • 2020/06/10 21:59 編集

    自宅と会社ではコード違うコード。最初の問題は会社のコードで起こった。自宅から質問しているので自宅のコードをベースにやり取りした。会社のコードとは違うので会社で回答者のレスを試した結果は自宅とは違う。そうとは知らない回答者にとっては訳の分からない話になってしまったというわけですか? それは真摯に解決策を考えてレスしている回答者に対して非常に失礼な話と認識できませんか? そういうイイカゲンなことをする人には怒りを覚えます。

    キャンセル

  • 2020/06/10 22:49

    >SurferOnWww様

    おっしゃる通りです。
    エラーの内容が全く同じだったため、お恥ずかしい限りですが、自身では今回の質問内容に影響する部分に関してのみ同様の動作をするコードを書いているという自覚でした。
    大変申し訳ございませんでした。

    環境の違う状態で試し、不完全な情報で返信をしましたことを深く反省をしております。
    二度とこのようなことはないようにいたします。
    申し訳ございませんでした。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る