C#自定义属性必需如果

时间:2014-11-12 22:48:46

标签: c# required validationattribute

我刚刚进入自定义属性,我非常喜欢它们。我想知道是否可以创建一个应用于属性的属性,并表示同一对象中另一个属性的名称。如果要检查引用的属性是否有值,如果是,则需要装饰属性。 像这样:

[RequiredIfNotNull("ApprovedDate")]
[DisplayName("Approved By")]
[StringLength(50, ErrorMessage = "{0} must not exceed {1} characters")]
public string ApprovedBy { get; set; }

[DisplayName("Approved Date")]
[DisplayFormat(DataFormatString = "{0:d}")]
[PropertyMetadata(ColumnName = "ApprovedDate")]
public DateTime? ApprovedDate { get; set; }

因此,批准的属性使用RequiredIfNotNull属性进行修饰,该属性引用要检查null的属性。在这种情况下,批准日期。 如果ApprovedDate有值,我希望需要ApprovedBy属性。 可以这样做吗? 如果是这样,你可以实现服务器端和客户端吗?

1 个答案:

答案 0 :(得分:0)

这是我提出的: 服务器端:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Web.Mvc;   
namespace Atlas.Core.Attributes
{
    /// <summary>
    /// Add the following decoration: [ConditionalRequired("Model", "Field")]
    /// Model = client model being used to bind object
    /// Field = the field that if not null makes this field required.
    /// </summary>
    public class ConditionalRequiredAttribute : ValidationAttribute, IClientValidatable
    {
        private const string DefaultErrorMessageFormatString = "The {0} field is required.";
        private readonly string _dependentPropertyPrefix;
        private readonly string _dependentPropertyName;

        public ConditionalRequiredAttribute(string dependentPropertyPrefix, string dependentPropertyName)
        {
            _dependentPropertyPrefix = dependentPropertyPrefix;
            _dependentPropertyName = dependentPropertyName;
            ErrorMessage = DefaultErrorMessageFormatString;
        }

        protected override ValidationResult IsValid(object item, ValidationContext validationContext)
        {
            PropertyInfo property = validationContext.ObjectInstance.GetType().GetProperty(_dependentPropertyName);
            object dependentPropertyValue = property.GetValue(validationContext.ObjectInstance, null);

            if (dependentPropertyValue != null && item == null)
                return new ValidationResult(string.Format(ErrorMessageString, validationContext.DisplayName));

            return ValidationResult.Success;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = string.Format("{0} is required", metadata.GetDisplayName()),
                ValidationType = "conditionalrequired",
            };

            rule.ValidationParameters.Add("requiredpropertyprefix", _dependentPropertyPrefix);
            rule.ValidationParameters.Add("requiredproperty", _dependentPropertyName);
            yield return rule;
        }
    }
}

客户方:

$.validator.unobtrusive.adapters.add('conditionalrequired', ['requiredpropertyprefix', 'requiredproperty'], function (options) {
        options.rules['conditionalrequired'] = {
            requiredpropertyprefix: options.params['requiredpropertyprefix'],
            requiredproperty: options.params['requiredproperty']
        };
        options.messages['conditionalrequired'] = options.message;
});

$.validator.addMethod('conditionalrequired', function (value, element, params) {
        var requiredpropertyprefix = params['requiredpropertyprefix'];
        var requiredproperty = params['requiredproperty'];
        var field = $('#' + requiredproperty).length == 0 ? '#' + requiredpropertyprefix + '_' + requiredproperty : '#' + requiredproperty;
        return !($(field).val().length > 0 && value.length == 0);
    }
);

我将其设置为接受模型或前缀值,然后接受实际字段的名称。 这样做的原因是,在许多情况下,我将添加一个对象作为模型的一部分,这将导致该元素的表单id呈现为ModelName_FieldName。 但是我也想到你可能会也可能不会使用带有嵌入对象的模型。在这种情况下,id只是FieldName,因此客户端代码检查FieldName是否存在该元素,如果不存在则返回ModelName_FieldName,否则它只返回FieldName。我还没有这样做,但我应该检查以确保生成的fieldname不是null。

然后装饰你的财产,你会做这样的事情:

[DataMember]
[DisplayName("Approved By")]
[ConditionalRequired("HOA", "ApprovedDate")]
[StringLength(50, ErrorMessage = "{0} must not exceed {1} characters")]
public string ApprovedBy { get; set; }

我的模型看起来像这样:

    public class HOAModel
    {
        public HOA HOA { get; set; }
   }

我的视图实现如下:

Html.Kendo().DatePickerFor(m => m.HOA.ApprovedDate)

所以我的客户端元素具有以下ID:

<input name="HOA.ApprovedDate" class="k-input" id="HOA_ApprovedDate" role="textbox">