Reputation: 75
I am currently stuck at some point of my implementation where I use a ViewModel class to display data, but I need to post values from other object which are equal to given values in the ViewModel. Here are both model classes
ViewModel.cs
public class ViewModel
{
public IList<Answer> Answers { get; set; }
public Question Questions { get; set; }
}
UserScore.cs
public partial class UserScore
{
public int ScoreID { get; set; }
public int U_Id { get; set; }
public int A_Id { get; set; }
public bool CorrectAnswer { get; set; }
public int Q_Id { get; set; }
public virtual Answer Answer { get; set; }
public virtual Member Member { get; set; }
public virtual Question Question { get; set; }
}
So far so good. I am using an object of Question and List of Answers to display the data I need in my Controller
Controller.cs
public ActionResult TakeTest(int id=0)
{
ViewModel vm = new ViewModel();
Test t = db.Tests.Find(id);
if (t == null)
{
return HttpNotFound();
}
vm.Questions = (from q in db.Questions
join tt in db.Tests on q.BelongToTest equals tt.TestId
where q.BelongToTest == id
select q).FirstOrDefault();
vm.Answers = new List<Answer>(from a in db.Answers
join q in db.Questions on a.BelongToQuestion equals q.QuestionId
join tt in db.Tests on q.BelongToTest equals tt.TestId
where q.BelongToTest == id &&
a.BelongToQuestion == vm.Questions.QuestionId
select a).ToList();
foreach (var i in vm.Answers)
{
i.CorrectOrNot = false;
}
return View(vm);
}
View.cshtml
@model MvcTestApplication.Models.ViewModel
@using MvcTestApplication.Models
@{
ViewBag.Title = "TakeTest";
}
<h2>TakeTest</h2>
@using (Html.BeginForm()) {
<table>
<tr>
<th>Question Name</th>
</tr>
<tr>
<td>@Html.DisplayFor(model => model.Questions.Question_Text)</td>
</tr>
</table>
<table id="dataTable">
<tr>
<th>Correct?</th>
<th>Answer text</th>
<th>Open Answer</th>
</tr>
@for(int i = 0; i < Model.Answers.Count; i++)
{
<tr>
<td>@Html.CheckBoxFor(m => m.Answers[i].CorrectOrNot)</td>
<td>@Html.DisplayFor(m => m.Answers[i].AnswerText)</td>
<td>@Html.EditorFor(m => m.Answers[i].OpenAnswerText)</td>
</tr>
}
</table>
if(ViewBag.Message != null)
{
<script>
$(document).ready(function(){
alert('@ViewBag.Message');
});
</script>
}
<input type="submit" value="Next Question" />
}
Now in my post method I need to get the value of vm.Question.QuestionId
and AnswerId
of the Answer list, set them to be equal to UserScore.Q_Id
and UserScore.A_Id
. How can I do that ? I tried many ways but with no success.
Controller.cs
[HttpPost]
[Authorize]
public ActionResult TakeTest(ViewModel vm)
{
if (ModelState.IsValid)
{
UserScore us = new UserScore();
us.U_Id = (from m in db.Members
where m.UserID == WebSecurity.CurrentUserId
select m.MemberId).FirstOrDefault();
us.A_Id = 49;
//us.A_Id = vm.Questions.QuestionID returns NULL
us.Q_Id = 150;
db.UserScores.Add(us);
db.SaveChanges();
}
return View(vm);
}
In general I need to know how to bind this vm.something
to us.something
because Question appears to be null all the time.
Upvotes: 1
Views: 1269
Reputation: 55
You should use an hiddenfor helpers in your view and try something like that.
@Html.hiddenfor(m=>vm.Questions.QuestionId)
Give it a try : Html.HiddenFor value property not getting set
Upvotes: 1
Reputation: 5771
These values are null, because they are not present in your view. You will need to keep them in your View in the form of a hidden control. The ViewModel that you receive in the post can only construct the ViewModel using values present in the View. Since there is no ID maintained in the View, the constructed ViewModel has a null ID.
You can use
@Html.HiddenFor(model => model.Questions.ID)
and for your answer ID
@Html.HiddenFor(m => m.Answers[i].ID)
Upvotes: 2
Reputation: 455
vm.Questions.QuestionID returns NULL because u haven't used that on the view anywhere. A easy hack would be to use a hidden field to capture the value or you should be initializing your viewmodel again and follow the logic in the post method.
Upvotes: 2