我目前正在尝试通过MVC验证,并且遇到了一些需要字段的问题,具体取决于另一个字段的值。下面是一个例子(我还没想到) - 如果PaymentMethod ==“Check”,那么应该需要ChequeName,否则可以让它通过。
[Required(ErrorMessage = "Payment Method must be selected")]
public override string PaymentMethod
{ get; set; }
[Required(ErrorMessage = "ChequeName is required")]
public override string ChequeName
{ get; set; }
我正在使用[Required]的System.ComponentModel.DataAnnotations,并且还扩展了ValidationAttribute以尝试使其工作,但我无法通过变量来进行验证(下面的扩展名)< / p>
public class JEPaymentDetailRequired : ValidationAttribute
{
public string PaymentSelected { get; set; }
public string PaymentType { get; set; }
public override bool IsValid(object value)
{
if (PaymentSelected != PaymentType)
return true;
var stringDetail = (string) value;
if (stringDetail.Length == 0)
return false;
return true;
}
}
实现:
[JEPaymentDetailRequired(PaymentSelected = PaymentMethod, PaymentType = "Cheque", ErrorMessage = "Cheque name must be completed when payment type of cheque")]
有没有人有过这种验证的经验?将它写入控制器会更好吗?
感谢您的帮助。
答案 0 :(得分:4)
如果除了服务器上的模型验证之外还想要客户端验证,我认为最好的方法是自定义验证属性(如Jaroslaw建议的那样)。我在这里包含了我使用的源码。
自定义属性:
public class RequiredIfAttribute : DependentPropertyAttribute
{
private readonly RequiredAttribute innerAttribute = new RequiredAttribute();
public object TargetValue { get; set; }
public RequiredIfAttribute(string dependentProperty, object targetValue) : base(dependentProperty)
{
TargetValue = targetValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// get a reference to the property this validation depends upon
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(DependentProperty);
if (field != null)
{
// get the value of the dependent property
var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);
// compare the value against the target value
if ((dependentvalue == null && TargetValue == null) ||
(dependentvalue != null && dependentvalue.Equals(TargetValue)))
{
// match => means we should try validating this field
if (!innerAttribute.IsValid(value))
// validation failed - return an error
return new ValidationResult(ErrorMessage, new[] { validationContext.MemberName });
}
}
return ValidationResult.Success;
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "requiredif"
};
var depProp = BuildDependentPropertyId(DependentProperty, metadata, context as ViewContext);
// find the value on the control we depend on;
// if it's a bool, format it javascript style
// (the default is True or False!)
var targetValue = (TargetValue ?? "").ToString();
if (TargetValue != null)
if (TargetValue is bool)
targetValue = targetValue.ToLower();
rule.ValidationParameters.Add("dependentproperty", depProp);
rule.ValidationParameters.Add("targetvalue", targetValue);
yield return rule;
}
}
Jquery验证扩展:
$.validator.unobtrusive.adapters.add('requiredif', ['dependentproperty', 'targetvalue'], function (options) {
options.rules['requiredif'] = {
dependentproperty: options.params['dependentproperty'],
targetvalue: options.params['targetvalue']
};
options.messages['requiredif'] = options.message;
});
$.validator.addMethod('requiredif',
function (value, element, parameters) {
var id = '#' + parameters['dependentproperty'];
// get the target value (as a string,
// as that's what actual value will be)
var targetvalue = parameters['targetvalue'];
targetvalue = (targetvalue == null ? '' : targetvalue).toString();
// get the actual value of the target control
var actualvalue = getControlValue(id);
// if the condition is true, reuse the existing
// required field validator functionality
if (targetvalue === actualvalue) {
return $.validator.methods.required.call(this, value, element, parameters);
}
return true;
}
);
使用以下属性装饰属性:
[Required]
public bool IsEmailGiftCertificate { get; set; }
[RequiredIf("IsEmailGiftCertificate", true, ErrorMessage = "Please provide Your Email.")]
public string YourEmail { get; set; }
答案 1 :(得分:4)
只需使用Codeplex上提供的Foolproof验证库: https://foolproof.codeplex.com/
它支持以下“requiredif”验证属性/装饰:
[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]
开始很容易:
答案 2 :(得分:3)
我会在模型中编写验证逻辑,而不是控制器。控制器应该只处理视图和模型之间的交互。由于它是需要验证的模型,我认为它被广泛认为是验证逻辑的地方。
对于依赖于另一个属性或字段的值的验证,我(遗憾的是)没有看到如何完全避免在模型中为其编写一些代码,如Wrox ASP.NET MVC书中所示,排序喜欢:
public bool IsValid
{
get
{
SetRuleViolations();
return (RuleViolations.Count == 0);
}
}
public void SetRuleViolations()
{
if (this.PaymentMethod == "Cheque" && String.IsNullOrEmpty(this.ChequeName))
{
RuleViolations.Add("Cheque name is required", "ChequeName");
}
}
以声明方式进行所有验证会很棒。我确信你可以制作一个RequiredDependentAttribute
,但这只能处理这种逻辑。甚至稍微复杂一点的东西还需要另一个非常特殊的属性,等等会很快变得疯狂。
答案 3 :(得分:2)
使用conditional validation attribute例如
可以相对简单地解决您的问题[RequiredIf("PaymentMethod == 'Cheque'")]
public string ChequeName { get; set; }