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

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

新規登録して質問してみよう
ただいま回答率
85.37%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

Q&A

解決済

1回答

16060閲覧

ASP.NET MVC ラジオボタンのView/Controllerのやり取り

masterofpuppets

総合スコア12

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

ASP.NET

ASP.NETは動的なWebサイトやWebアプリケーション、そしてWebサービスを構築出来るようにする為、Microsoftによって開発されたウェブアプリケーション開発フレームワークです。

ASP.NET MVC Framework

ASP.NET MVC Frameworkは、MVCパターンをベースとした、マイクロソフトのウェブアプリケーション開発用のフレームワークです。

0グッド

0クリップ

投稿2018/10/12 00:56

編集2018/10/12 02:31

お世話になっております。
前回、ASP.NET MVCでのラジオボタンについてで質問させていただいた件で、
引き続き質問させていただきます。

開発環境:C#, ASP.NET MVC5, SQLServer2014
実現したいこと:社員各個人に複数のアンケートを取るが、各設問の回答を5段階(5:非常に満足、4:満足、3:普通~)で回答してもらう。
UIとして、ラジオボタンで選択させたい。
(複数と書きましたのは、例えばあるアンケートでは設問が10、別のアンケートでは設問が5…と、アンケート内容によって可変となる為)

SQLServer上に用意したテーブルですが、
「QAHead」テーブル
・QA_Id int …アンケートID
・Employee_Id int …社員番号
・Remarks nvarchar(max) …その他備考(フリーワード)

「QADetail」テーブル
・QA_Id int …アンケートID
・Employee_Id int …社員番号
・QA_No smallint …アンケートNo
・QA_Ans smallint …回答
となっております。QAHeadとQADetailは1:nの関係です。

対応するModelとしまして、

public class QAModels { [DisplayName("ID")] public int QA_Id { get; set; } [DisplayName("社員番号")] public int Employee_Id { get; set; } [DisplayName("備考")] public string Remarks { get; set; } public IList<QADetailModels> Details { get; set; } } public class QADetailModels { [DisplayName("ID")] public int QA_Id { get; set; } [DisplayName("社員番号")] public int Employee_Id { get; set; } [DisplayName("アンケートNo")] public short QA_No { get; set; } // このアンケート内容は別のテーブルから引いてくるものとする [DisplayName("アンケート内容")] public string QA_Description { get; set; } [DisplayName("回答")] public short QA_Ans { get; set; } }

としました。
View上で表示するために、

@model TESTAPP.Models.QAModels @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> <table class="table table-bordered"> <tr><th>No</th><th>設問内容</th><th>回答</th></tr> foreach (var item in Model.Details) { <tr> <td>@item.QA_No</td> <td>@item.QA_Description</td> <td><div class="editor-field"> @for (int x = 1; x <= 5; x++) { <label> @Html.RadioButtonFor( m => item.QA_Ans, x, new { @Name = $"{item.Skill_No}", @id = $"{item.QA_No}_{x}"} ) @x </label> }</div> </td> </tr> } </table> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <button name="button" value="Upd" class="btn btn-primary">更新</button> </div> </div> </div> }

…これですと、View上への表示は可能ですが、ユーザーが(ラジオボタンをクリックして)選択した値をControllerに返す際、

[HttpPost] [ValidateAntiForgeryToken] public ActionResult CreateEval([Bind(Include = "QA_Id, Employee_Id, Remarks, Details")] QAModels qam) { }

上記の記述ではDetailsがnullとなってしまい、データベースへの更新が出来ない状況です。

単に表示だけでなく、その後のユーザーの回答内容をデータベースに反映させるには、どのようにすればよいか、
アドバイス等何卒よろしくお願いいたします。

【追記】
上記Viewの部分、以下のように変更してみました。

foreach (int i = 0; i < Model.Details.Count; i++) { <tr> <td>@Html.DisplayFor(m => m.Details[i].QA_No)</td> <td>@Html.DisplayFor(m => m.Details[i].QA_Description)</td> <td><div class="editor-field"> @for (int x = 1; x <= 5; x++) { <label> @Html.RadioButtonFor( m => m.Details[i].QA_Ans, x, new { @Name = $"{Model.Details[i].QA_Ans}", @id = $"{Model.Details[i].QA_No}_{x}"} ) @x </label> }</div> </td> </tr> }

データ表示に関しては表示はされますが、POSTした場合、相変わらずnullのままです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/12 01:10

質問欄に前のスレッドの URL を書いて、その話の続きであることを明記してください。
masterofpuppets

2018/10/12 01:15

大変失礼いたしました。URLを追記させていただきました。
guest

回答1

0

ベストアンサー

先のスレッドで紹介した以下の記事は読んでもらえたでしょうか?

コレクションのデータアノテーション検証
http://surferonwww.info/BlogEngine/post/2014/09/01/validation-of-collection-data-during-model-binding-using-data-annotation.aspx

そこに書いてあるように、コレクションのモデルバインディングがうまく行われるようにするには、レンダリングされる html 要素の name 属性が連番のインデックスを含むようにします。

質問者さんのコードの「回答」で言うと、name="Details[i].QA_Ans" という形で、i は 0 から始まる連番にします。

あと、モデルに定義されているすべての項目の値が POST されるようにします。なので <td>@item.QA_No</td> というような形ではなく、EditorFor を使うか、@item.QA_No とか DisplayFor を使うのであれば HiddenFor を追加してください。

と、言葉で書くだけでは分からないと思いますので、あとでサンプルコードを書いてアップします。お待ちください。

【追記】

以下、サンプルです。

Controller / Action Method / Model

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.ComponentModel.DataAnnotations; namespace Mvc5App.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); } [HttpGet] public ActionResult QuestionsAndAnswers() { // サンプル用の QAModels を作成 QAModels model = new QAModels { QA_Id = 1, Employee_Id = 12345, Remarks = "備考", Details = new List<QADetailModels> { // 質問数は任意。ここではとりあえず 5 題としています。 new QADetailModels { QA_Id = 1, Employee_Id = 12345, QA_No = 1, QA_Description = "質問文その 1" }, new QADetailModels { QA_Id = 1, Employee_Id = 12345, QA_No = 2, QA_Description = "質問文その 2" }, new QADetailModels { QA_Id = 1, Employee_Id = 12345, QA_No = 3, QA_Description = "質問文その 3" }, new QADetailModels { QA_Id = 1, Employee_Id = 12345, QA_No = 4, QA_Description = "質問文その 4" }, new QADetailModels { QA_Id = 1, Employee_Id = 12345, QA_No = 5, QA_Description = "質問文その 5" } } }; return View(model); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult QuestionsAndAnswers(QAModels model) { return View(model); } } // Model // Controller に含めたのは単に分けるのが面倒だったからです // 質問者さんのコードの DisplayName は古いので以下のように変えました // それ以外は質問者さんのコードの通りです。 public class QAModels { [Display(Name="ID")] public int QA_Id { get; set; } [Display(Name="社員番号")] public int Employee_Id { get; set; } [Display(Name="備考")] public string Remarks { get; set; } public IList<QADetailModels> Details { get; set; } } public class QADetailModels { [Display(Name="ID")] public int QA_Id { get; set; } [Display(Name="社員番号")] public int Employee_Id { get; set; } [Display(Name="アンケートNo")] public short QA_No { get; set; } // このアンケート内容は別のテーブルから引いてくるものとする [Display(Name="アンケート内容")] public string QA_Description { get; set; } [Display(Name="回答")] public short QA_Ans { get; set; } } }

View

上のアクションメソッド QuestionsAndAnswers をベースに Visual Studio 2015 のスキャフォールディング機能を使って自動生成させたものです。Template は Create を、Model class は QAModels を設定。それに <table> ... </table> のコードを追加した以外は手を加えていません。

@model Mvc5App.Controllers.QAModels @{ ViewBag.Title = "QuesttionsAndAnswers"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>QuesttionsAndAnswers</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>QAModels</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(model => model.QA_Id, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.QA_Id, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.QA_Id, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Employee_Id, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Employee_Id, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Employee_Id, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Remarks, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Remarks, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Remarks, "", new { @class = "text-danger" }) </div> </div> <table class="table"> <tr> <th> @Html.DisplayNameFor(model => model.Details[0].QA_No) </th> <th> @Html.DisplayNameFor(model => model.Details[0].QA_Description) </th> <th> @Html.DisplayNameFor(model => model.Details[0].QA_Ans) </th> </tr> @for (int i = 0; i < Model.Details.Count; i++) { <tr> @Html.HiddenFor(model => model.Details[i].QA_Id) @Html.HiddenFor(model => model.Details[i].Employee_Id) <td> @Html.EditorFor(model => model.Details[i].QA_No, new { htmlAttributes = new { @class = "form-control" } }) </td> <td> @Html.EditorFor(model => model.Details[i].QA_Description, new { htmlAttributes = new { @class = "form-control" } }) </td> <td> @*@Html.EditorFor(model => model.Details[i].QA_Ans, new { htmlAttributes = new { @class = "form-control" } })*@ @Html.RadioButton("Details[" + i + "].QA_Ans", 5, false)<label>非常に満足&nbsp;&nbsp;</label> @Html.RadioButton("Details[" + i + "].QA_Ans", 4, false)<label>満足&nbsp;&nbsp;</label> @Html.RadioButton("Details[" + i + "].QA_Ans", 3, false)<label>普通&nbsp;&nbsp;</label> @Html.RadioButton("Details[" + i + "].QA_Ans", 2, false)<label>不満&nbsp;&nbsp;</label> @Html.RadioButton("Details[" + i + "].QA_Ans", 1, false)<label>非常に不満&nbsp;&nbsp;</label> </td> </tr> } </table> <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> } <div> @Html.ActionLink("Back to List", "Index") </div> @section Scripts { @Scripts.Render("~/bundles/jqueryval") }

以下のように RadioButton を設定して[Create]ボタンをクリックするとデータがサーバーに送信されて、

イメージ説明

以下の通り public ActionResult QuestionsAndAnswers(QAModels model) の model にモデルバインディングされます。

イメージ説明

以上ですが、分からないところがあったら聞いてください。

投稿2018/10/12 03:07

編集2018/10/12 03:37
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

masterofpuppets

2018/10/12 03:46

SurferOnWww様 サンプル及び解説、誠にありがとうございます。 早速この後試してみます。 先ずは御礼申し上げます。
masterofpuppets

2018/10/12 04:30

SurferOnWww様 Viewの記述ですが、 <label>@Html.RadioButtonFor(m => m.Details[i].QA_Ans, 1)1&nbsp;&nbsp;</label> に変更すると、元々データベース上にあったデータも表示されました。 また、POSTした際も値が返っておりました。
退会済みユーザー

退会済みユーザー

2018/10/12 05:23

それで良いと思います。 というか、特に、モデルにある QA_Ans の値で初期画面のラジオボタンの選択を設定したい場合は RadioButtonFor を使うのが正解と思います。
masterofpuppets

2018/10/12 09:29

SurferOnWww様 この度はご丁寧なご回答・解説、誠にありがとうございました。 Viewへのデータ表示→POSTで返す部分含めて、一連の処理が理解出来ました。 また、当初の質問で私のせいで混乱を招くようなことになってしまい、改めてお詫び申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問