无法获取单选按钮选中值,在线投票系统数据接收问题求助
问题分析与修复方案
嘿,我仔细看了你的代码,发现几个关键问题导致你拿不到单选按钮的选中值,而且投票数据也没法正确写入数据库。咱们一步步来修复:
1. Get Vote方法的查询逻辑错误
你在Get方法里查询Question的条件写错了,这会导致你永远拿不到对应ID的问题:
// 错误代码 var Question = await poolDbContext.Questions.Include(A => A.Answers).AsNoTracking().SingleOrDefaultAsync(r => r.Id == r.Id);
r.Id == r.Id永远为true,会返回数据库里第一个Question(甚至抛出异常),完全没用到传入的id参数。改成下面这样:
// 修复后 var Question = await poolDbContext.Questions.Include(A => A.Answers).AsNoTracking().SingleOrDefaultAsync(r => r.Id == id);
2. 视图的提交按钮位置错误
你的Vote.cshtml把提交按钮放在了foreach循环内部,这会导致每个选项下面都有一个提交按钮,还可能干扰单选按钮的分组逻辑。把按钮移到循环外面:
@model PoolManager.Models.Question <div> @Html.HiddenFor(x => x.Id) <h3>@Model.Text</h3> @foreach (var a in Model.Answers) { <p> @Html.RadioButtonFor(b => b.SelectedAnswer, a.Id) @a.Text </p> } <input type="submit" /> <!-- 移到循环外部,一个按钮就够 --> </div>
另外你循环里的@Model.SelectedAnswer是调试用的,上线前可以删掉。
3. Post方法未实际保存投票数据
你的VotePost方法只是调用了SaveChanges(),但根本没创建Vote对象、关联选中的答案,等于啥都没存。修改成下面这样:
[HttpPost, ActionName("Vote")] [ValidateAntiForgeryToken] public ActionResult VotePost(Question question) { try { if (ModelState.IsValid) { using (var poolDbContext = new PoolContext()) { // 先验证选中的答案是否属于当前问题,防止恶意提交 var selectedAnswer = poolDbContext.Answers.FirstOrDefault(a => a.Id == int.Parse(question.SelectedAnswer) && a.QuestionId == question.Id); if (selectedAnswer == null) { ModelState.AddModelError("", "无效的投票选项"); return View(question); } // 创建投票记录 var vote = new Vote { IpAdress = HttpContext.Connection.RemoteIpAddress.ToString(), VoteDate = DateTime.Now, AnswerId = selectedAnswer.Id // 关联选中的答案 }; poolDbContext.Votes.Add(vote); poolDbContext.SaveChanges(); // 现在才真正保存数据 return RedirectToAction("Index"); } } return View(question); } catch (DbUpdateException) { ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); } return View(question); }
4. Vote模型的关系逻辑错误
当前你的Vote模型里有List<Question> Questions,这不符合业务逻辑——一个投票应该对应一个答案,而不是多个问题。修改Vote模型:
public class Vote { public int Id { get; set; } public string IpAdress { get; set; } public DateTime VoteDate { get; set; } // 移除多余的List<Question>,添加Answer关联 public int AnswerId { get; set; } public virtual Answer Answer { get; set; } public Vote() { // 无需初始化Questions } }
记得在你的DbContext里配置好Vote和Answer的外键关系(比如在OnModelCreating方法里)。
5. Question模型的SelectedAnswer类型优化
当前SelectedAnswer是string类型,但你绑定的是a.Id(int),虽然模型绑定能自动转换,但改成int类型更直观,避免转换错误:
public class Question { // ... 其他属性 public int SelectedAnswer { get; set; } // 从string改为int }
对应的视图代码不用改,因为a.Id本来就是int,类型匹配后模型绑定会更顺畅。
测试建议
做完这些修改后,你可以:
- 先测试Get Vote方法,确认能正确加载对应问题的所有选项
- 选择一个选项提交,检查Post方法中
question.SelectedAnswer是否拿到了正确的答案ID - 查看数据库,确认Vote表中新增了投票记录,且AnswerId关联正确
内容的提问来源于stack exchange,提问作者Dorin Munreanu
相关产品推荐
相关产品推荐

