我正在使用MVC5。我正在为用户编写一个向内部应用程序提交索赔的表格,并且在创建索赔时,我需要根据他们当前的余额来验证用户的索赔额。它拒绝该金额是否大于余额,例如10美元对5美元,并要求他们将余额归零。
我觉得最好将余额作为viewmodel上的(不可编辑)属性CurrentBalance
,并带有一个自定义验证属性来比较这两个值。我将其呈现为表单上的只读字段。当用户选择他们要提交给哪个程序(例如HRA)时,Ajax请求将根据他们选择的程序来填写当前余额。
问题在于,当将视图模型实例作为ValidationContext
的一部分传递给我的属性时,CurrentBalance
总是显示为零。这是调试时的片段:https://i.imgur.com/syDEuJ2.png
因此,无论余额如何,验证都会毫无例外地失败。
我尝试将CurrentBalance
设置为视图上的普通非只读字段,并在提交前自行设置值。在渲染视图之前,我还尝试在控制器中设置值。无论哪种情况,它仍为零,如上图所示。
我的自定义属性如下:
public class ClaimAmountAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var claim = (ClaimCreateViewModel)validationContext.ObjectInstance;
var amount = (decimal)value;
if (claim.CurrentBalance - amount < 0)
{
return new ValidationResult(GetErrorMessage());
}
return ValidationResult.Success;
}
public string GetErrorMessage() => "Amount must be less than balance; please zero out balance instead.";
}
这是我观点的相关部分,尽管如此,无论是否存在readonly属性,似乎都没有什么不同。
@model ClaimCreateViewModel
<div class="form-group">
@Html.LabelFor(model => model.CurrentBalance, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.CurrentBalance, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Amount, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Amount, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Amount, "", new { @class = "text-danger" })
</div>
</div>
最后,这是viewmodel的一个片段:
public class ClaimCreateViewModel
{
[Key]
public int TransactionID { get; set; }
// ...
[Required]
[ClaimAmount] //my custom attribute
public decimal Amount { get; set; }
[Display(Name = "Balance")]
public decimal CurrentBalance { get; set; }
// ...
}
似乎我所做的任何事情都没有在CurrentBalance
中产生ValidationContext
的值。请帮帮我。
答案 0 :(得分:1)
好吧,这很尴尬。事实证明,我的POST操作中的 [Bind]
属性丢失了CurrentBalance
。验证在操作之前进行,但这无关紧要; [Bind]
正在此之前采取行动,以防止发布过多信息。我已经更新了该操作,它现在可以工作:
public ActionResult Create([Bind(Include = "TransactionID,Amount,CurrentBalance")] ClaimCreateViewModel claim)
{
// ...
}