vLr
vLr

Reputation: 75

How to bind Model from get to post method MVC 4

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

Answers (3)

Seb Monte
Seb Monte

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

Praveen Paulose
Praveen Paulose

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

HappyLee
HappyLee

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

Related Questions