C#需要自定义属性If

本文关键字:If 自定义属性 | 更新日期: 2023-09-27 18:30:07

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

[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; }

因此,approved-by属性使用RequiredIfNotNull属性进行装饰,该属性引用该属性来检查null。在这种情况下,为批准日期。如果ApprovedDate有值,我希望ApprovedBy属性是必需的。有可能做这样的事吗?如果是的话,你能在服务器端和客户端实现它吗?

C#需要自定义属性If

以下是我的想法:服务器端:

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。我还没有这么做,但我可能应该检查一下,以确保得到的字段名不是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">