我刚刚进入自定义属性,我非常喜欢它们。我想知道是否可以创建一个应用于属性的属性,并表示同一对象中另一个属性的名称。如果要检查引用的属性是否有值,如果是,则需要装饰属性。 像这样:
[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属性。 可以这样做吗? 如果是这样,你可以实现服务器端和客户端吗?
答案 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">