UPDATED POST
I am currently developing a Survey application that uses MVC4, Razor, EF5. There will be various surveys an will be utilizing one view. The Models for the application comes from an existing database. Apart from that, I created a separate Entities for the following:
SurveyDisplay - Model for elements that will appear on the survey page because it consists of different languages.
SurveyInfo - Model for information where data comes from a web service.
SurveyQuestion - Model for the questionnaires of the survey.
SurveyChoices - Model for the choices of each question in the survey.
SurveyAnswers - Model to retrieve choices of answers
UPDATE IMAGE(Added SurveyAnswers)
Kindly refer to the image below for the following fields:
I am able to get the particular values to display in my page which is a Razor, but upon POST. I am getting ModelState.IsValid == false. All models are null except for SurveyAnswers.
Here's how my code goes so far:
SurveyRepository:
For this part, I imported stored procedures to get data from the database.
public List<SurveyQuestion> GetQuestions(int surveyid)
{
using (var ctx = new ICSDBContext())
{
return ctx.GetSurveyQuestions(surveyid).ToList<SurveyQuestion>();
}
}
public List<SurveyChoice> GetChoices(int surveyid)
{
using (var ctx = new ICSDBContext())
{
return ctx.GetSurveyChoices(surveyid).ToList<SurveyChoice>();
}
}
public List<SurveyDisplay> GetSurveyDisplay(int surveyid)
{
using (var ctx = new ICSDBContext())
{
return ctx.GetSurveyDisplay(surveyid).ToList<SurveyDisplay>();
}
}
SurveyController:
using ICS.Repositories;
using ICS.ViewModels;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
public class SurveyController : Controller
{
SurveyRepository surveyRepository = new SurveyRepository();
SurveyViewModel surveyViewModel = new SurveyViewModel();
[HttpGet]
public ActionResult Index(int surveyid, string rowid)
{
var surveyDisplay = surveyRepository.GetSurveyDisplay(surveyid);
var surveyQuestions = surveyRepository.GetQuestions(surveyid);
var surveyChoices = surveyRepository.GetChoices(surveyid);
string headerText = "";
string messageBody = "";
string buttonText = "";
foreach (var item in surveyDisplay)
{
headerText = item.HeaderText;
messageBody = item.MessageBody;
buttonText = item.ButtonText;
}
surveyViewModel.HeaderText = Server.HtmlEncode(headerText);
surveyViewModel.MessageBody = Server.HtmlEncode(messageBody);
surveyViewModel.Buttontext = Server.HtmlEncode(buttonText);
surveyViewModel.SurveyQuestions = surveyQuestions;
surveyViewModel.SurveyChoices = surveyChoices;
return View("Survey", surveyViewModel);
}
//Not the actual code yet. I'm trying to check in this action whether there is POSTed data or none.
[HttpPost]
}
SurveyViewModel
public class SurveyViewModel
{
public List<SurveyInfo> SurveyInfo { get; set; }
public string HeaderText { get; set; }
public string MessageBody { get; set; }
public string Buttontext { get; set; }
public List<SurveyQuestion> SurveyQuestions { get; set; }
public List<SurveyChoice> SurveyChoices { get; set; }
public List<SurveyAnser> SurveyAnsers { get; set; }
}
Razor View
<h2>@Html.DisplayFor(model => model.HeaderText)</h2>
<div id="info">
<p>@Html.DisplayFor(model => model.MessageBody)</p>
<div class="margTop20">
<ul>
@for (var info = 0; info < Model.SurveyInfo.Count(); info++)
{
<li>
<span>Case ID: </span>
<b>@Html.DisplayFor(model => model.SurveyInfo[info].SRNumber)</b>
</li>
<li>
<span>Description: </span>
<b>Others</b>
</li>
<li>
<span>Problem Category: </span>
<b>@Html.DisplayFor(model => model.SurveyInfo[info].ProblemSubCategory)</b>
</li>
<li>
<span>Product: </span>
<b>@Html.DisplayFor(model => model.SurveyInfo[info].Product)</b>
</li>
<li>
<span>Method of Service: </span>
<b>@Html.DisplayFor(model => model.SurveyInfo[info].SupportType)</b>
</li>
}
</ul>
</div>
</div>
@for (var question = 0; question < Model.SurveyQuestions.Count(); question++)
{
<div id="@("question" + ConvertNumberToWords.Translate(question))" class="@(Convert.ToBoolean(Model.SurveyQuestions[question].Subquestion) == true ? "subquestion" : "questions")">
<p>
<b>
@Html.DisplayFor(model => model.SurveyQuestions[question].TheQuestion)
</b>
</p>
@Html.HiddenFor(model => model.SurveyAnswers[question].QuestionID)
@if (Convert.ToBoolean(Model.SurveyQuestions[question].Mandatory) == true)
{
<p><span id="@("errorQuestion" + ConvertNumberToWords.Translate(question))" class="errorMsg">*Please choose your answer</span></p>
}
@for (var choice = 0; choice < Model.SurveyChoices.Count(); choice++)
{
if (Model.SurveyQuestions[question].QuestionID == Model.SurveyChoices[choice].QuestionID)
{
if (Model.SurveyChoices[choice].isStyleOptBox)
{
var choicesGroup = (from c in Model.SurveyChoices where c.QuestionID == Model.SurveyQuestions[question].QuestionID select new { c.ChoicesID, c.ChoicesName });
@Html.Raw("<ul>")
@Html.Raw("<li>")
@Html.RadioButtonForSelectList(model => model.SurveyAnswers[question].ChoiceID, new SelectList(choicesGroup, "ChoicesID", "ChoicesName"))
@Html.Raw("</li>")
@Html.Raw("</ul>")
break;
}
else if (Model.SurveyChoices[choice].isStyleChkBox)
{
var choicesGroup = (from c in Model.SurveyChoices where c.QuestionID == Model.SurveyQuestions[question].QuestionID select new { c.ChoicesID, c.ChoicesName });
@Html.Raw("<ul>")
@Html.Raw("<li>")
@Html.CheckBoxListFor(model => model.SurveyAnswers[question].ChoiceID, model => choicesGroup, model => model.ChoicesID, model => model.ChoicesName, model => false, Position.Vertical)
@Html.Raw("</li>")
@Html.Raw("</ul>")
break;
}
else if (Model.SurveyChoices[choice].isStyleCboBox)
{
}
else
{
<div class="margTop20">
<p>
@*<textarea cols="" rows="5" class="form-control"></textarea>*@
@Html.TextAreaFor(model => model.SurveyAnswers[question].Comment, new { rows = "5", cols = "0", @class = "form-control" })
</p>
</div>
}
}
}
</div>
}
</div>
<input id="hidQuestionCount" type="hidden" value="@Model.SurveyQuestions.Count()" />
<div>
@*<a class="btn btn-primary" href="#myModal" id="btnSubmit">@Model.Buttontext</a> @Url.Action("Submit", "SaveSurvey", Model)*@
<input id="btnSubmit" class="btn btn-primary" type="submit" value="@Model.Buttontext" />
</div>
If you will notice, I am using a custom Html Helper to render radio button groups which is RadioButtonSelectListFor which is very handy in this scenario. I am able to bind and get the value of the selected control as you can see in the image below:
Secondly, I am also using the Html Helper package Hmtl Helper CheckBoxListFor to display group of checkboxes to make multiple selections and submit it. But the problem is, I am getting 1 value among all checkboxes which causes me real pain and headache. When there is 2 or more checkboxes checked, only the first item is being returned, you may refer to the image below:
For the comments value, I have no problem with it as I can get the values. As seen on the image:
I also have one problem, I need to bind QuestionID in SurveyAnswers because it is used for reporting purpose.
To sum up, below are my things to achieve:
OBJECTIVES:
- Bind QuestionID to model SurveyAnswers
- Return all checkboxes value and add it to list SurveyAnswers
- If possible, make ModelState.IsValid to be true. If not, I won't be validating model to get the list of SurveyAnwsers
I really want to get this thing to work. I have been doing a lot of research just to get it going, but no progress yet. Kindly help me guys! Any inputs/ suggestions will be highly appreciated.
Thank you very much!