目前我正在提交一份付款表单,在此付款表单上可以切换是否显示credit card validation。显示CVV字段取决于某些配置,这取决于应用程序中几个层中的某些业务逻辑(在我的实例中,某些支付网关没有/需要CVV)。
表单显示以下字段:
public class IndexViewModel
{
public IEnumerable<CardType> CardTypes { get; set; }
public bool IsCvvEnabled { get; set; }
public PayProcess { get; set; }
}
public class ProcessViewModel : IValidatableObject
{
public string CardHolder { get; set; }
public string CardNumber { get; set; }
public string CardType { get; set; }
public string ExpiryDate { get; set; }
public string Cvv { get; set; }
public IEnumerable<ValidationResult> Validate(
ValidationContext validationContext)
{
// validation of properties CardHolder, Number, Type, etc...
// how do I read this value?
if (IsCvvEnabled)
{
int tempCvv;
if (string.IsNullOrEmpty(Cvv))
{
yield return new ValidationResult(Index.CVVRequired,
new[] { "CVV" });
}
else if (!int.TryParse(Cvv, out tempCvv))
{
yield return new ValidationResult(Index.CVVInvalid,
new[] { "CVV" });
}
}
}
}
该视图如下所示:
<section id="aligned">
<h3>@ViewRes.Index.Header</h3>
@Html.ValidationMessageFor(m => m.PayProcess.CreditCardType)
@Html.LabelFor(x => x.PayProcess.CreditCardType,
"Card Type")
@Html.DropDownListFor(m => m.PayProcess.CreditCardType,
Model.CreditCardTypes)
<!-- the other fields ... -->
@if (Model.PayProcess.IsCvvEnabled)
{
@Html.ValidationMessageFor(m => m.PayProcess.Cvv)
@Html.LabelFor(x => x.PayProcess.Cvv,
"Card Verification")
@Html.TextBoxFor(m => m.PayProcess.Cvv)
}
</section>
public ActionResult Index()
{
var indexViewModel = CreateIndexViewModel(new ProcessViewModel());
return View(model);
}
private PayIndexViewModel CreateIndexViewModel(ProcessViewModel processViewModel)
{
if (!ModelState.IsValid)
{
return View("Index", CreateIndexViewModel(processViewModel));
}
// handle success scenario
}
private IndexViewModel CreateIndexViewModel(ProcessViewModel processViewModel)
{
var isCvvEnabled = _someDependency.Gateway.SupportsCvv;
var cardTypes = _someDependency.Gateway.GetSupportedCardTypes
.Select(x => new SelectListItem {
Text = x.Name,
Value = x.ID });
return new IndexViewModel
{
CardTypes = cardTypes,
IsCvvEnabled = isCvvEnabled,
PayProcess = processViewModel
};
}
ProcessViewModel
仅包含用户提交的表单输入值,但不包含IsCvvEnabled
,因为用户未提交该值。
如果验证需要此上下文信息,如何正确执行此验证?
答案 0 :(得分:1)
如果用户没有在表单中提交值,那么您必须在帖子操作上手动设置它,或者您可以在验证属性之前设置自定义模型绑定器以设置属性。然而,对于像这样微不足道的事情,我认为这太过分了。
就我个人而言,我实现你想要的方法的首选方法是将你的验证方法重构为一个接收ModelState
的方法,然后你自己在你的帖子行动中调用它:
viewModel.IsCvvEnabled = _someDependency.Gateway.SupportsCvv;
viewModel.Validate(this.ModelState);
if(!ModelState.IsValid)
{
return View(viewModel);
}
您必须将IsCvvEnabled属性放入ProcessViewModel。