I have a problem sending a model to a POST function, I don't know if I'm doing something wrong when setting the list that I have in the model, but all the attributes that I send appear to be zero or null and I don't understand why.
Model EvaluationQuestionsDetailsView
public int AprendizEvaluacionID { get; set; }
public int EvaluacionID { get; set; }
public string Nombre { get; set; }
public string Fecha { get; set; }
public string Horas { get; set; }
public List<EvaluacionPregunta> EvaluacionPreguntas { get; set; }
The list that is in the previous model is contained by the link table between Evaluation and Questions, from here I take the questions to show them in the views that I require, now, this in the GET function and the data visualization works perfectly for me but the thing is when I try to send from the view to the controller the same model but modified to do what I intend to do.
An important detail is that the Questions entity has an attribute called "Answers" where it has the answers separated by "semicolons" and in the view I make the respective code so that each answer appears in a radio button each, that is to say that if I have 4 answers in this attribute, it will be 4 radio buttons that will come up.
GET view
@model ASPXEvaluacion.Models.EvaluacionPreguntasDetailsView
@{
ViewBag.Title = "Realizar Evaluación";
}
<h2>Realizar Evaluación</h2>
<div>
<h4>Evaluación</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Nombre)
</dt>
<dd>
@Html.DisplayFor(model => model.Nombre)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Fecha)
</dt>
<dd>
@Html.DisplayFor(model => model.Fecha)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Horas)
</dt>
<dd>
@Html.DisplayFor(model => model.Horas)
</dd>
</dl>
</div>
@using ASPXEvaluacion.Utils;
<h3>Preguntas a realizar</h3>
@if (Model.EvaluacionPreguntas.Count == 0)
{
<h4> No hay preguntas registradas para esta evaluación, comuniquese con su instructor </h4>
}
else
{
using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.AprendizEvaluacionID)
@Html.HiddenFor(model => model.EvaluacionID)
@Html.HiddenFor(model => model.Nombre)
@Html.HiddenFor(model => model.Fecha)
@Html.HiddenFor(model => model.Horas)
<table class="table">
@{
for (int i = 0; i < Model.EvaluacionPreguntas.Count; i++)
{
<tr>
<td>@(i + 1)<text>. </text>@Html.DisplayFor(modelItem => Model.EvaluacionPreguntas[i].Preguntas.Question)</td>
</tr>
var preguntas = Model.EvaluacionPreguntas[i].Preguntas;
List<string> respuestas = preguntas.Respuestas.Split(';').ToList();
respuestas.Shuffle();
foreach (string item in respuestas)
{
<tr>
<td>
@Html.RadioButtonFor(itemPregunta => Model.EvaluacionPreguntas[i].Preguntas.Respuestas, item, new { id = "" })
@item
@Html.HiddenFor(itemPregunta => item)
</td>
</tr>
}
}
}
</table>
<div class="form-group mb-5">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Enviar" name="RealizarEvaluacion" class="btn btn-default" />
</div>
</div>
}
}
This code works perfectly for me (the Shuffle function is a list randomizer so that the answers are not always located in the same position, also the first answer before the first semicolon is the correct answer) and it shows me the data as such but at the time of submitting, the POST function does not set the data sent to the view but instead sets it to zero or null.
Controller GET and POST functions
public ActionResult RealizarEvaluacion(int? idEvaluacion, int? idAprendizEvaluacion)
{
if (idEvaluacion == null || idAprendizEvaluacion == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Evaluacion evaluacion = db.Evaluacions.Find(idEvaluacion);
if (evaluacion == null)
{
return HttpNotFound();
}
var view = new EvaluacionPreguntasDetailsView
{
AprendizEvaluacionID = (int) idAprendizEvaluacion,
EvaluacionID = evaluacion.EvaluacionID,
Nombre = evaluacion.Nombre,
Fecha = string.Format("{0:yyyy-MM-dd}", evaluacion.Fecha),
Horas = string.Format("{0:t} - {1:t}", evaluacion.HoraInicio, evaluacion.HoraFinal),
EvaluacionPreguntas = evaluacion.EvaluacionPreguntas.ToList(),
};
return View(view);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult RealizarEvaluacion(EvaluacionPreguntasDetailsView evaluacionPreguntas)
{
code...
}
It's just in the POST function that I don't get the model I need, I don't know if I'm doing something wrong when creating the radio buttons or the binding is not done properly or what, I haven't developed much in MVC with EF in C# but I would like to solve this nothing else, that the complete model can be sent.
PS: The objective that I visualize (I don't know if there will be a simpler way) is that in the view model, the "Responses" attribute is set by the selected radio button and when sending it to the POST function, this model is compared with the original answers where the first answer before the first semicolon is true and thus score the result, otherwise it would not be scored and thus would not be added to the final grade of the exam; I hope you can help me with this, I only need this to continue with the process and complete this project.
I ended up finding the solution to my problem searching and searching the Internet, although I deduce that it was rather something too obvious because of some posts that gave the idea and I did not notice it at first sight.
It turns out that I was using the list of QuestionEvaluation as my set of the answers selected by each radio button, this made the model "damage" and in this way it did not send the data that it should (I honestly don't know why this didn't work but I imagine it didn't you can modify a model within another model in a list or well, what do I know); Then, analyzing the code of other people, I discovered that the model had to contain another property that would serve as a base to contain the selection of the radios, so my model looked like this:
I had to create an array of strings to capture the selection of one of them for each group of radios, so in the part of the controller in the view variable it looked like this:
And in the foreach of the view it looks like this:
This is how I was able to solve it and well, in case someone has a doubt and has not found it yet, well, here I leave my own solution