[英]MVC3 Custom validation attribute that compare valid minimum and maximum values
I have 2 parameters in decimal for my model as following: 我的模型有两个十进制参数,如下所示:
public class Range
{
public decimal MinimumValue { get; set; }
public decimal MaximumValue { get; set; }
}
Would it be possible to make custom validation for both parameters where: 是否可以对以下两个参数进行自定义验证:
There are a lot of articles about creating custom validation attributes, but here is a sample of how it may look in your case: 关于创建自定义验证属性的文章很多,但是这里是一个样例示例:
public class GreaterThanAttribute : ValidationAttribute
{
public string PropertyNameToCompare { get; set; }
public GreaterThanAttribute(string propertyNameToCompare)
{
PropertyNameToCompare = propertyNameToCompare;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var propertyToCompare = validationContext.ObjectType.GetProperty(PropertyNameToCompare);
if (propertyToCompare == null)
{
return new ValidationResult(
string.Format("Invalid property name '{0}'", PropertyNameToCompare));
}
var valueToCompare = propertyToCompare.GetValue(validationContext.ObjectInstance, null);
bool valid;
if (value is decimal && valueToCompare is decimal)
{
valid = ((decimal) value) > ((decimal) valueToCompare);
}
//TODO: Other types
else
{
return new ValidationResult("Compared properties should be numeric and of the same type.");
}
if (valid)
{
return ValidationResult.Success;
}
return new ValidationResult(
string.Format("{0} must be greater than {1}",
validationContext.DisplayName, PropertyNameToCompare));
}
}
I don't like very much the place where I start to check for property types, but I don't know if it's possible to make it nicer. 我不太喜欢开始检查属性类型的地方,但是我不知道是否有可能使它变得更好。
Of course you will need to implement GreaterThanAttribute
too. 当然,您也需要实现
GreaterThanAttribute
。
I did a custom attribute to validade a field if checkbox is checked. 如果选中了复选框,我做了一个自定义属性来验证字段。 If checkbox isn't checked the field is required, if not, the field isn't required.
如果未选中复选框,则该字段为必填项;如果未选中,则该字段为必填项。 I can use this code to adapt and check if a field is greather than other.
我可以使用此代码来适应和检查某个字段是否比其他字段更好。 You can also use data annotations extensions.
您还可以使用数据注释扩展。 More information about data annotations extensions here
有关数据注释扩展的更多信息,请点击此处
public class RequiredIf : ConditionalValidationAttribute
{
protected override string ValidationName
{
get { return "requiredif"; }
}
public RequiredIf(string dependentProperty, object targetValue)
: base(new RequiredAttribute(), dependentProperty, targetValue)
{
}
protected override IDictionary<string, object> GetExtraValidationParameters()
{
return new Dictionary<string, object>
{
{ "rule", "required" }
};
}
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public abstract class ConditionalValidationAttribute : ValidationAttribute, IClientValidatable
{
protected readonly ValidationAttribute InnerAttribute;
public string DependentProperty { get; set; }
public object TargetValue { get; set; }
protected abstract string ValidationName { get; }
protected virtual IDictionary<string, object> GetExtraValidationParameters()
{
return new Dictionary<string, object>();
}
protected ConditionalValidationAttribute(ValidationAttribute innerAttribute, string dependentProperty, object targetValue)
{
this.InnerAttribute = innerAttribute;
this.DependentProperty = dependentProperty;
this.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(this.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 && this.TargetValue == null) || (dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
{
// match => means we should try validating this field
if (!InnerAttribute.IsValid(value))
{
// validation failed - return an error
return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
}
}
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = ValidationName,
};
string depProp = BuildDependentPropertyId(metadata, context as ViewContext);
// find the value on the control we depend on; if it's a bool, format it javascript style
string targetValue = (this.TargetValue ?? "").ToString();
if (this.TargetValue.GetType() == typeof(bool))
{
targetValue = targetValue.ToLower();
}
rule.ValidationParameters.Add("dependentproperty", depProp);
rule.ValidationParameters.Add("targetvalue", targetValue);
// Add the extra params, if any
foreach (var param in GetExtraValidationParameters())
{
rule.ValidationParameters.Add(param);
}
yield return rule;
}
private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
{
string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
// This will have the name of the current field appended to the beginning, because the TemplateInfo's context has had this fieldname appended to it.
var thisField = metadata.PropertyName + "_";
if (depProp.StartsWith(thisField))
{
depProp = depProp.Substring(thisField.Length);
}
return depProp;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.