Asp.Net MVC验证 - 依赖字段

Sam*_*m J 7 asp.net validation asp.net-mvc

我目前正在尝试通过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; }
Run Code Online (Sandbox Code Playgroud)

我正在为[Required]使用System.ComponentModel.DataAnnotations,并且还扩展了ValidationAttribute以尝试使其工作,但我无法通过变量来进行验证(下面的扩展名)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

执行:

[JEPaymentDetailRequired(PaymentSelected = PaymentMethod, PaymentType = "Cheque", ErrorMessage = "Cheque name must be completed when payment type of cheque")]
Run Code Online (Sandbox Code Playgroud)

有没有人有这种验证的经验?将它写入控制器会更好吗?

谢谢你的帮助.

Pea*_*rog 5

如果除了服务器上的模型验证之外,还需要客户端验证,我认为最好的方法是自定义验证属性(如 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
);
Run Code Online (Sandbox Code Playgroud)

用属性装饰一个属性:

[Required]
public bool IsEmailGiftCertificate { get; set; }

[RequiredIf("IsEmailGiftCertificate", true, ErrorMessage = "Please provide Your Email.")]
public string YourEmail { get; set; }
Run Code Online (Sandbox Code Playgroud)


dju*_*uth 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");
  }
}
Run Code Online (Sandbox Code Playgroud)

以声明方式进行所有验证会很棒。我确信你可以制作一个RequiredDependentAttribute,但这只能处理这一种类型的逻辑。稍微复杂一点的东西将需要另一个非常具体的属性,等等,这很快就会变得疯狂。