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属性是必需的。有可能做这样的事吗?如果是的话,你能在服务器端和客户端实现它吗?
以下是我的想法:服务器端:
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">