Asp.Net MVC验证相关字段

Asp.Net MVC验证相关字段,asp.net,asp.net-mvc,validation,Asp.net,Asp.net Mvc,Validation,我目前正在尝试进行MVC验证,遇到了一些问题,根据另一个字段的值需要一个字段。下面是一个例子(我还没有弄清楚)-如果PaymentMethod==“check”,那么ChequeName应该是必需的,否则它可以通过 [Required(ErrorMessage = "Payment Method must be selected")] public override string PaymentMethod { get; set; } [Required(ErrorMessage = "Che

我目前正在尝试进行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以尝试使其正常工作,但我无法传递变量来进行验证(下面的扩展)

实施:

[JEPaymentDetailRequired(PaymentSelected = PaymentMethod, PaymentType = "Cheque", ErrorMessage = "Cheque name must be completed when payment type of cheque")]
有人有过这种验证的经验吗?将其写入控制器会更好吗


谢谢您的帮助。

我将在模型中编写验证逻辑,而不是在控制器中。控制器应仅处理视图和模型之间的交互。由于模型需要验证,我认为它被广泛认为是验证逻辑的场所

对于依赖于另一个属性或字段的值的验证,我(不幸地)不知道如何完全避免在模型中为此编写一些代码,如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
,但这只能处理这一类逻辑。稍微复杂一点的东西还需要另一个非常具体的属性,等等,这很快就会变得疯狂。

你的问题可以相对简单地通过使用例如


如果除了服务器上的模型验证之外,还需要客户端验证,我认为最好的方法是自定义验证属性(如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;
    }
}
[Required]
public bool IsEmailGiftCertificate { get; set; }

[RequiredIf("IsEmailGiftCertificate", true, ErrorMessage = "Please provide Your Email.")]
public string YourEmail { get; set; }
使用属性装饰属性:

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;
    }
}
[Required]
public bool IsEmailGiftCertificate { get; set; }

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

只需使用Codeplex上提供的万无一失的验证库:

它支持以下“requiredif”验证属性/装饰:

[RequiredIf]
[RequiredIfNot]
[RequiredIfTrue]
[RequiredIfFalse]
[RequiredIfEmpty]
[RequiredIfNotEmpty]
[RequiredIfRegExMatch]
[RequiredIfNotRegExMatch]
开始很容易:

  • 从提供的链接下载软件包
  • 添加对包含的.dll文件的引用
  • 导入包含的javascript文件
  • 确保视图从其HTML中引用包含的javascript文件,以进行不引人注目的javascript和jquery验证

  • 仔细想想。。。如何设置PaymentSelected=PaymentMethod?你应该得到一个错误,因为PaymentMethod不是一个常量表达式。嗨,Min,你是对的。我原以为我可以这样做,但没用。我只是想展示我所做的尝试,但也评论说它不允许我传递变量。感谢djuth,我已经获取了一个ModelStateDictionary并在模型中对此进行了验证,然后将该dictionary传递回控制器以合并到ModelState中。似乎做到了这一点,并允许我做一些编程工作-不太好,只是做一个声明每个属性,但至少我可以在一个地方得到一切。如果每个属性tho有多个错误,我不确定这将如何进行。我知道这个答案已经有2年了,但我正在尝试让它起作用,基本上它会启动依赖属性的验证,无论第一个属性的值是什么。任何帮助都将不胜感激。
    [RequiredIf]
    [RequiredIfNot]
    [RequiredIfTrue]
    [RequiredIfFalse]
    [RequiredIfEmpty]
    [RequiredIfNotEmpty]
    [RequiredIfRegExMatch]
    [RequiredIfNotRegExMatch]