ASP.NET MVC ModelState验证失效及取款交易逻辑异常问题
ASP.NET MVC ATM练习项目两个问题修复方案
1. 取款环节ModelState验证不生效、非法输入无错误提示
按以下顺序排查修复:
- 检查POST提交对应的
Create动作方法执行顺序:必须将ModelState.IsValid判断放在所有业务逻辑之前,验证失败时直接返回对应视图并传入当前模型实例,绝对不能用RedirectToAction跳转——重定向会清空当前请求上下文中的ModelState错误信息,前端自然拿不到提示。 - 检查
Create.cshtml表单代码:必须在表单内添加@Html.ValidationSummary(true)渲染模型级通用错误,取款金额输入框旁必须添加@Html.ValidationMessageFor(m => m.Amount, "", new { @class = "text-danger" })渲染字段级错误,缺少这两个HTML辅助方法,即便后端写入了错误信息,前端也没有占位标签展示。 - 检查Withdraw模型类的验证特性:取款金额字段必须加对应验证标记:必填标记
[Required]、数值范围标记[Range(1, int.MaxValue)],特性内可以自定义ErrorMessage内容。 - 检查视图脚本引用:必须在视图的Scripts区块引入
_ValidationScriptsPartial分部视图(包含jQuery验证、非侵入式验证的js引用),否则客户端验证不生效,非数字类非法输入提交后容易出现模型绑定异常但错误无法展示的问题。
2. 交易次数校验逻辑错误,TransactionBal递减为负数
你当前写的判断条件emp.TransactionBal <= 10逻辑完全反向:
- 这个条件的含义是“只要剩余交易次数小于等于10就允许交易”,而你的需求是初始给10次交易机会,每取一次扣1次,次数到0就禁止交易。这个错误条件会在次数为0、-1、-2的时候依然放行交易请求,自然会出现次数减为负数的问题。
- 修复逻辑:
- 所有交易操作执行前,优先判断剩余次数:
if (emp.TransactionBal <= 0)时,直接向ModelState写入“交易次数已用完”的错误,返回视图,不执行任何扣款、扣次数的操作。 - 只有金额验证通过、余额充足、剩余交易次数大于0三个条件全部满足时,才执行余额扣减、交易次数减1的操作。
- 加一层兜底逻辑:次数递减后如果值小于0,强制赋值为0,避免极端情况出现负数。
- 所有交易操作执行前,优先判断剩余次数:
参考代码片段
WithdrawController的POST动作方法
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create(Withdraw model) { // 取当前登录用户(替换成你自己的用户存储读取逻辑,比如Session、内存缓存都可以) var currentUser = (Employee)Session["LoginUser"]; // 优先判断交易次数 if (currentUser.TransactionBal <= 0) { ModelState.AddModelError(string.Empty, "您的可交易次数已耗尽,无法继续取款"); } // 模型验证不通过直接返回 if (!ModelState.IsValid) { return View(model); } // 校验余额是否充足 if (currentUser.Balance < model.Amount) { ModelState.AddModelError(nameof(model.Amount), "账户余额不足,无法完成取款"); return View(model); } // 所有校验通过,执行核心交易逻辑 currentUser.Balance -= model.Amount; currentUser.TransactionBal -= 1; // 兜底防止次数为负 if (currentUser.TransactionBal < 0) { currentUser.TransactionBal = 0; } // 更新存储的用户数据 Session["LoginUser"] = currentUser; // 交易成功后再跳转 return RedirectToAction("Success"); }
Withdraw模型类
using System.ComponentModel.DataAnnotations; public class Withdraw { [Required(ErrorMessage = "请输入取款金额")] [Range(1, 20000, ErrorMessage = "单次取款金额必须为1-20000范围内的正整数")] public int WithdrawAmount { get; set; } }
Create.cshtml表单核心片段
@model WebApplication1.Models.Withdraw <h2>取款操作</h2> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <!-- 通用错误提示 --> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(m => m.WithdrawAmount, "取款金额") @Html.TextBoxFor(m => m.WithdrawAmount, new { @class = "form-control" }) <!-- 字段级错误提示 --> @Html.ValidationMessageFor(m => m.WithdrawAmount, "", new { @class = "text-danger" }) </div> <button type="submit" class="btn btn-primary mt-2">确认取款</button> } @section Scripts{ <!-- 引入验证脚本 --> @Html.Partial("_ValidationScriptsPartial") }
内容的提问来源于stack exchange,提问作者Victor Adewale
相关产品推荐
相关产品推荐

