'How to get multiple answers from radio buttons when clicking submit ASP.NET CORE MVC

This is a quiz with around 40 questions and each question with multiple answers. Everything looks fine until I try to catch the answers from the view to the controller because everything returns 0 or null, Please help!

This is what I have The Database looks like this: enter image description here

Model Evaluacion:

namespace ENCB_Placement_Test_Official.Models
{
    public class Evaluacion
    {
        public int ExamenId { get; set; }
        public int RegistroId { get; set; }
        public int ReactivoId { get; set; }
        public string RespuestaAlumno { get; set; }
        public string Pregunta { get; set; }
        public string Respuesta1 { get; set; }
        public string Respuesta2 { get; set; }
        public string Respuesta3 { get; set; }
        public string Respuesta4 { get; set; }
    }
}

Services folder with a class called RepositorioExaluaciones

namespace ENCB_Placement_Test_Official.Servicios
{
    public interface IRepositorioEvaluaciones
    {
        Task EnviarRespuesta(Evaluacion evaluacion);
        Task<IEnumerable<Evaluacion>> ObtenerEvaluaciones();
    }
    public class RepositorioEvaluaciones: IRepositorioEvaluaciones
    {
        private readonly string connectionString;
        public RepositorioEvaluaciones(IConfiguration configuration)
        {
            connectionString = configuration.GetConnectionString("DefaultConnection");
        }

        public async Task<IEnumerable<Evaluacion>> ObtenerEvaluaciones()
        {
            using var connection = new SqlConnection(connectionString);
            return await connection.QueryAsync<Evaluacion>(@"SELECT Examenes.Id AS ExamenId,
                                                                                RegistroId,
                                                                                ReactivoId,
                                                                                RespuestaAlumno,
                                                                                Pregunta,
                                                                                Respuesta1,
                                                                                Respuesta2,
                                                                                Respuesta3,
                                                                                Respuesta4
                                                            FROM Examenes 
                                                            INNER JOIN Reactivos
                                                            ON Examenes.ReactivoId = Reactivos.Id
                                                            WHERE Examenes.RegistroId = 1");
        }
        public async Task EnviarRespuesta(Evaluacion evaluacion)
        {
            using var connection = new SqlConnection(connectionString);
            connection.Execute(@"UPDATE Examenes
                                SET RespuestaAlumno = @RespuestaAlumno
                                WHERE RegistroId = @RegistroId", evaluacion);
        }
    }
}

Controller Evaluaciones

namespace ENCB_Placement_Test_Official.Controllers
{
    public class EvaluacionesController:Controller
    {
        private readonly IRepositorioEvaluaciones repositorioEvaluaciones;

        public EvaluacionesController(IRepositorioEvaluaciones repositorioEvaluaciones)
        {
            this.repositorioEvaluaciones = repositorioEvaluaciones;
        }
        public async Task<IActionResult> Evaluar()
        {
            if (!ModelState.IsValid)
            {
                return View();
            }
            var obtenerExamen = await repositorioEvaluaciones.ObtenerEvaluaciones();
            return View(obtenerExamen);
        }

        [HttpPost]
        public async Task<IActionResult> Evaluar(Evaluacion evaluacion)
        {
            if (!ModelState.IsValid)
            {
                return View(evaluacion);
            }  
            await repositorioEvaluaciones.EnviarRespuesta(evaluacion);
            return View();
        }
    }
}

View Evaluar, this is where I think I have the problem because when I debug the app and click the submit button I just get nulls and zeros

@model IEnumerable<Evaluacion>
@{
    ViewData["Title"] = "Start Assesment";
    var contador = 1;
}
<h1>Start Assesment</h1>

<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<form asp-action="Evaluar" method="post">
    @foreach (var reactivo in Model)
    {
        <div class="mb-3">
            <label class="form-label">@contador . @reactivo.Pregunta</label>
            <div class="form-check">
                <input class="form-check-input" type="radio" id="@reactivo.ExamenId" name="@reactivo.ExamenId" value="Respuesta1" checked />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta1</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="radio" id="@reactivo.ExamenId" name="@reactivo.ExamenId" value="Respuesta2" />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta2</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="radio" id="@reactivo.ExamenId" name="@reactivo.ExamenId" value="Respuesta3" />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta3</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="radio" id="@reactivo.ExamenId" name="@reactivo.ExamenId" value="Respuesta4" />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta4</label>
            </div>
        </div>
        contador++;
    }
    <button type="submit" class="btn btn-primary">Send Response</button>
</form>

It is supposed to return an answer like "Respuesta1" and it should be stored in the Model.RespuestaAlumno and I just don't have any idea on how can I do it. please help.



Solution 1:[1]

In your Model Design, You need a property to receive the value of the selected answer(maybe you already have that property in your model,I don't understand spanish), So I create that property:

public class Evaluacion
    {
        public int ExamenId { get; set; }
        public int RegistroId { get; set; }
        public int ReactivoId { get; set; }
        public string RespuestaAlumno { get; set; }
        public string Pregunta { get; set; }
        public string Respuesta1 { get; set; }
        public string Respuesta2 { get; set; }
        public string Respuesta3 { get; set; }
        public string Respuesta4 { get; set; }
        public string Answer { get; set; }
    }

Then in your View, name uses property names for binding and it asked to start at index 0. I write a simple demo here, you can refer to it:

@model IEnumerable<Evaluacion>
@{
    ViewData["Title"] = "Start Assesment";
    var contador = 1;
}
<h1>Start Assesment</h1>

<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<form asp-action="Evaluar" method="post">
    @foreach (var reactivo in Model)
    {
        int i = contador - 1;
        <div class="mb-3">
            <label class="form-label">@contador . @reactivo.Pregunta</label>
            <div class="form-check ">
                <input class="form-check-input" type="radio"  name="[@i].Answer" value="@reactivo.Respuesta1" checked />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta1</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="radio"  name="[@i].Answer" value="@reactivo.Respuesta2" />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta2</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="radio"  name="[@i].Answer" value="@reactivo.Respuesta3" />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta3</label>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="radio"  name="[@i].Answer" value="@reactivo.Respuesta4" />
                <label class="form-check-label" for="@reactivo.ExamenId">@reactivo.Respuesta4</label>
            </div>
        </div>
        contador++;
    }
    <button type="submit" class="btn btn-primary">Send Response</button>
</form>

Finally, The type of the model passed into the controller from the page is IEnumerable, You can't just use Evaluacion to receive, You need to change like this:

        [HttpPost]
        public async Task<IActionResult> Evaluar(List<Evaluacion> evaluacion)
        {
            //.......
            return View(evaluacion);
        }

Demo:

enter image description here

You can see the project can receive the answer successfully.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Xinran Shen