
在 asp.net 表单中,使用 `readonly` 的 `` 可以既保持用户不可编辑、又确保其值随表单一同提交,无需额外隐藏字段或 `display:none`/`visibility:hidden` 折衷方案。
在处理如“运费自动计算”这类场景时,一个常见误区是:为避免 disabled 字段不提交而改用 display:none 或 visibility:hidden 配合冗余隐藏字段。但这样做不仅增加 DOM 复杂度,还易引发绑定失败(如 type="hidden" 与 decimal 模型属性类型不匹配)、样式错位或 JavaScript 维护困难等问题。
✅ 正确做法是:直接使用带 name 属性的 readonly 输入框。
readonly 元素不会被用户修改,但会参与表单序列化和服务器端模型绑定——只要它拥有合法的 name(对应模型属性名),ASP.NET MVC / Razor Pages 就能正确将值绑定到 decimal DeliveryCharge 等强类型属性上。
以下是精简、语义清晰且可直接落地的实现方案:
对应的 JavaScript 计算逻辑(示例):
function calculateDeliveryCharge() {
const input = document.getElementById('deliveryChargeInput');
// 示例:根据其他字段动态计算(如订单重量、地区等)
const baseRate = 5.99;
const surcharge = Math.random() * 3.0;
const result = parseFloat((baseRate + surcharge).toFixed(2));
input.value = result;
}⚠️ 关键注意事项:
- 必须保留 asp-for="DeliveryCharge":它会自动生成正确的 name="DeliveryCharge" 和 id,确保模型绑定;
- 不要移除 readonly:它保障 UX(不可编辑)与功能(可提交)的统一;
- 避免重复 asp-for:原代码中两个 asp-for="DeliveryCharge" 会导致生成同名字段,引发服务端绑定冲突或覆盖;
- 禁用 disabled:disabled 字段永远不提交,即使视觉上类似 readonly,也不适用本场景;
- 无需隐藏字段: 在此场景下纯属冗余,且 type="hidden" 的值默认为字符串,若直接赋值 value="@Model.DeliveryCharge" 虽可工作,但绕过了 readonly 输入的双向一致性,增加维护成本。
? 进阶建议:
如需更严格的防篡改(例如防止用户通过 DevTools 修改 readonly 值),应在服务端重新校验并计算 DeliveryCharge,而非完全信任客户端输入——readonly 是 UX 层防护,非安全机制。
综上,拥抱 readonly + asp-for 的简洁组合,即可优雅解决“只读但可提交”的核心需求,兼顾可访问性、可维护性与服务端类型安全。










