You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC多选项问卷开发:视图实现与数据存储方案咨询

Fixing Your ASP.NET MVC Questionnaire View & Saving Responses

Hey there! Let's break down how to fix your questionnaire view and handle saving responses correctly in ASP.NET MVC. First, let's diagnose the core issue with your current code: when using foreach with RadioButtonFor, the generated HTML creates radio buttons that don't group properly per question, and MVC's model binding won't be able to map each answer back to its corresponding QuestionID reliably. Here's the step-by-end solution:


1. Create a ViewModel for Responses

First, define a ViewModel to separate what's displayed/collected in the view from your database entities. This makes model binding cleaner and more maintainable:

public class QuestionResponseViewModel
{
    public int QuestionID { get; set; }
    public string QuestionText { get; set; }
    [Required(ErrorMessage = "Please select an answer for this question.")]
    public string SelectedAnswer { get; set; }
}

// Main view model to hold all questions
public class QuestionnaireViewModel
{
    public List<QuestionResponseViewModel> Questions { get; set; }
}

2. Fix the View (Two Solid Options)

Option 1: Use Editor Templates (Clean & Scalable)

Editor Templates are the best practice for rendering repeated items and ensuring proper model binding.

Step 2.1: Create the Editor Template

Create a folder Views/Shared/EditorTemplates (if it doesn't exist), then add a partial view named QuestionResponseViewModel.cshtml:

@model QuestionResponseViewModel

<tr>
    <td>@Model.QuestionText</td>
    <td class="text-center">
        @Html.RadioButtonFor(m => m.SelectedAnswer, "Strongly Agree", new { id = $"SA_{Model.QuestionID}" })
    </td>
    <td class="text-center">
        @Html.RadioButtonFor(m => m.SelectedAnswer, "Somewhat Agree", new { id = $"WA_{Model.QuestionID}" })
    </td>
    <td class="text-center">
        @Html.RadioButtonFor(m => m.SelectedAnswer, "Strongly Disagree", new { id = $"SD_{Model.QuestionID}" })
    </td>
</tr>

Step 2.2: Update the Main View

Now your main view can use EditorFor to render all questions with proper grouping:

@model QuestionnaireViewModel

@using (Html.BeginForm("SubmitResponses", "Questionnaire", FormMethod.Post))
{
    <table class="table">
        <tr>
            <th>Question</th>
            <th class="text-center">Strongly Agree</th>
            <th class="text-center">Somewhat Agree</th>
            <th class="text-center">Strongly Disagree</th>
        </tr>
        @Html.EditorFor(m => m.Questions)
    </table>

    <button type="submit" class="btn btn-primary">Submit Responses</button>
    @Html.ValidationSummary(true)
}

Option 2: Use a for Loop (Straightforward)

If you prefer avoiding Editor Templates, use a for loop (requires Questions to be an IList):

@model QuestionnaireViewModel

@using (Html.BeginForm("SubmitResponses", "Questionnaire", FormMethod.Post))
{
    <table class="table">
        <tr>
            <th>Question</th>
            <th class="text-center">Strongly Agree</th>
            <th class="text-center">Somewhat Agree</th>
            <th class="text-center">Strongly Disagree</th>
        </tr>
        @for (int i = 0; i < Model.Questions.Count; i++)
        {
            <tr>
                <td>@Model.Questions[i].QuestionText</td>
                <td class="text-center">
                    @Html.RadioButtonFor(m => m.Questions[i].SelectedAnswer, "Strongly Agree")
                </td>
                <td class="text-center">
                    @Html.RadioButtonFor(m => m.Questions[i].SelectedAnswer, "Somewhat Agree")
                </td>
                <td class="text-center">
                    @Html.RadioButtonFor(m => m.Questions[i].SelectedAnswer, "Strongly Disagree")
                </td>
                @Html.HiddenFor(m => m.Questions[i].QuestionID)
            </tr>
        }
    </table>

    <button type="submit" class="btn btn-primary">Submit Responses</button>
    @Html.ValidationSummary(true)
}

3. Controller Logic to Load & Save Responses

Step 3.1: Load Questions into the View

In your controller, fetch questions from tblQuestions and map them to your ViewModel:

public class QuestionnaireController : Controller
{
    private readonly YourDbContext _dbContext; // Inject your DbContext

    public QuestionnaireController(YourDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public IActionResult Index()
    {
        var questions = _dbContext.tblQuestions
            .Select(q => new QuestionResponseViewModel
            {
                QuestionID = q.QuestionID,
                QuestionText = q.Question
            })
            .ToList();

        var viewModel = new QuestionnaireViewModel
        {
            Questions = questions
        };

        return View(viewModel);
    }
}

Step 3.2: Handle Submission & Save to Database

Add a POST action to validate responses and save them to tblTestProper:

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult SubmitResponses(QuestionnaireViewModel viewModel)
{
    if (!ModelState.IsValid)
    {
        return View("Index", viewModel);
    }

    // Get current user's ID (adjust based on your auth system)
    int currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);

    foreach (var response in viewModel.Questions)
    {
        var userResponse = new tblTestProper
        {
            QuestionID = response.QuestionID,
            UserID = currentUserId,
            Answer = response.SelectedAnswer
        };

        _dbContext.tblTestProper.Add(userResponse);
    }

    _dbContext.SaveChanges();

    return RedirectToAction("ThankYou"); // Redirect to a confirmation page
}

public IActionResult ThankYou()
{
    return View();
}

Key Takeaways

  • Model Binding: foreach fails here because it doesn't track item indexes, making it impossible for MVC to map answers to their questions. Editor Templates or for loops fix this by preserving index information.
  • Validation: The [Required] attribute ensures users can't submit incomplete responses.
  • Database: Adjust the DbContext code to match your actual entity classes. If you're not using Entity Framework, use ADO.NET to insert records directly into tblTestProper.

内容的提问来源于stack exchange,提问作者mj.e

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:18:43