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

ASP.NET Core Razor Pages中Post Action无法获取ViewModel的解决方法

问题修复方案

核心问题分析

Post方法接收的CreateBallotViewModel属性为空,主要由三个原因导致:

  1. 模型中choice和tracking是字段而非属性,ASP.NET Core模型绑定只支持带getter/setter的属性;
  2. 视图中表单控件的name属性不匹配模型字段,且缺少关键的ElectionId隐藏字段;
  3. 控制器中DbContext初始化方式错误,且未验证模型状态。

1. 修正模型定义

将choice和tracking改为自动属性(添加get/set访问器),模型绑定才能正确识别并赋值:

using System;
using System.Collections.Generic;

namespace electronicvotingfyp.Models
{
    public class CreateBallotViewModel
    {
        public List<ElectionOption> options { get; set; }
        public Election elect { get; set; }
        // 改为属性,添加get/set访问器
        public string choice { get; set; }
        public string tracking { get; set; }
        //vote encrypted
        //signed vote
        //keys
    }
}

2. 修复Razor视图

调整表单控件的name、id属性,添加隐藏字段传递ElectionId:

@model CreateBallotViewModel
<div class="row">
    <div class="col-md-5 offset-md-1">
        <h4 class="mb-3">@Model.elect.Question</h4>
        <div class="my-3">
            @using (Html.BeginForm(actionName: "CreateBallot", controllerName: "Account", FormMethod.Post))
            {
                <!-- 添加隐藏字段传递ElectionId,否则Post时elect为null -->
                @Html.HiddenFor(m => m.elect.ElectionId)

                @foreach (var opt in Model.options)
                {
                    <div class="form-check">
                        <!-- 使用RadioButtonFor生成正确的name和id -->
                        @Html.RadioButtonFor(m => m.choice, opt.OptionName, new { @class = "form-check-input", id = $"choice_{opt.OptionName}" })
                        <!-- label的for属性对应单选按钮的id -->
                        <label class="form-check-label" for="choice_@opt.OptionName">@opt.OptionName</label>
                    </div>
                }
                <div class="form-check">
                    <!-- 修正name为"choice",使用asp-for自动匹配模型属性 -->
                    <input asp-for="choice" type="radio" class="form-check-input" value="" id="choice_neutral">
                    <label class="form-check-label" for="choice_neutral">Neutral</label>
                </div>
                <div class="col-md-3">
                    <label asp-for="tracking" class="form-label">Tracking Number</label>
                    <!-- 使用asp-for自动生成正确的name和id -->
                    <input type="text" class="form-control" asp-for="tracking" placeholder="" required>
                    <div class="invalid-feedback">
                        Security code required
                    </div>
                </div>
                <hr class="my-4">
                <button class="btn btn-primary" type="submit">Cast Ballot</button>
            }
        </div>
    </div>
</div>

关键调整点:

  • 移除所有name="credit"的错误设置,用asp-for或RadioButtonFor自动生成与模型匹配的name属性;
  • 确保label的for属性与对应单选按钮的id一致,提升交互体验;
  • 添加@Html.HiddenFor(m => m.elect.ElectionId)传递选举ID,避免Post时cbm.elect为null。

3. 优化控制器代码

使用依赖注入获取DbContext,添加模型状态验证:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using electronicvotingfyp.Models;
using System.Security.Cryptography;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Crypto;
using System.Text;

public class AccountController : Controller
{
    private readonly electronicvotingfypIdentityDbContext _dbContext;

    // 依赖注入DbContext,替代手动创建
    public AccountController(electronicvotingfypIdentityDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [Authorize]
    [HttpGet]
    public IActionResult CreateBallot(int ElectionId)
    {
        var election = _dbContext.Elections.Single(u => u.ElectionId == ElectionId);
        var electionOptions = _dbContext.Options.Where(p => p.Election == election).ToList();

        var cbm = new CreateBallotViewModel() { options = electionOptions, elect = election };
        return View(cbm);
    }

    [Authorize]
    [HttpPost]
    public IActionResult CreateBallot(CreateBallotViewModel cbm)
    {
        // 先验证模型状态,排查绑定错误
        if (!ModelState.IsValid)
        {
            // 重新加载选项和选举信息,返回视图显示错误
            cbm.elect = _dbContext.Elections.Single(u => u.ElectionId == cbm.elect.ElectionId);
            cbm.options = _dbContext.Options.Where(p => p.Election == cbm.elect).ToList();
            return View(cbm);
        }

        try
        {
            var keys = _dbContext.ElectionKeys.Single(u => u.RelatedElection.ElectionId == cbm.elect.ElectionId);
            PemReader pr = new PemReader(new StringReader(keys.publicKey));
            AsymmetricCipherKeyPair keyPair = (AsymmetricCipherKeyPair)pr.ReadObject();

            ElectionKeySystemContrroller ks = new ElectionKeySystemContrroller(keyPair);
            byte[] inputChoice = Encoding.UTF8.GetBytes(cbm.choice);
            byte[] encryptedChoice = ks.Encrypt(inputChoice, 0, inputChoice.Length);

            // 后续逻辑:保存加密后的投票等
            return View(cbm);
        }
        catch (Exception ex)
        {
            ModelState.AddModelError(string.Empty, "处理投票时发生错误:" + ex.Message);
            // 重新加载数据返回视图
            cbm.elect = _dbContext.Elections.Single(u => u.ElectionId == cbm.elect.ElectionId);
            cbm.options = _dbContext.Options.Where(p => p.Election == cbm.elect).ToList();
            return View(cbm);
        }
    }
}

关键优化:

  • 通过依赖注入获取electronicvotingfypIdentityDbContext,避免手动创建时的配置缺失;
  • 添加ModelState.IsValid验证,快速排查绑定错误;
  • 异常处理中重新加载模型数据,确保返回视图时页面内容完整。

内容的提问来源于stack exchange,提问作者Agossou Sara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:45:08