需要 MVC 3 方面的帮助,以更好的方式在集合属性上创建自定义验证器
我一直致力于创建自定义验证器来满足我们项目的业务规则。
现在下面给出的是模型:
public class CreateTestModel { 公共创建测试模型() {
[Required]
public string Name { get; set; }
public string Description { get; set; }
public string BucketValidator { get; set; }
public RadioButtonListViewModel<GoalTypes> Goals { get; set; }
[EntityValidator(Property1:"IncludedEntities",Property2:"ExcludedEntities",MandatoryCount:1,isBucket=false, ErrorMessage = "One Entity is Compulsory")]
public IEnumerable<TestEntityModel> IncludedEntities { get; set; }
public IEnumerable<TestEntityModel> ExcludedEntities { get; set; }
public int MandatoryEntityCount { get; set; }
public IEnumerable<TestFilterModel> IncludedFilters { get; set; }
public IEnumerable<TestFilterModel> ExcludedFilters { get; set; }
[EntityValidator(Property1:"Buckets",Property2:"",MandatoryCount:2,isBucket=true,ErrorMessage = "Bucket is compulsory")]
[DisplayName("BucketErrors")]
public IEnumerable<BucketModel> Buckets { get; set; }
public bool AutoDecision { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int AdminId { get; set; }
[DefaultValue(true)]
public bool IsEnabled { get; set; }
}
根据上面给定的模型,我创建了实体验证器,用于满足我的业务规则。但是,由于验证是在集合属性上进行的,因此当集合中存在多个值时,验证器无法输入错误集合,否则它会检查生成的错误。
EntityValidator 类如下所示:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class EntityValidator : ValidationAttribute,IClientValidatable
{
public int numberOfMandatoryEntities{get; private set;}
public int totalCountofIncludeEntities { get; private set; }
public bool isBucket { get; set; }
public string Property1{get; private set;}
public string Property2{ get; private set; }
private const string DefaultErrorMessageFormatString = "Atleast one entity is required";
public EntityValidator(string Property1, string Property2, int MandatoryCount)
{
this.Property1 = Property1;
if (!String.IsNullOrEmpty(Property2))
this.Property2 = Property2;
numberOfMandatoryEntities = MandatoryCount;
}
public EntityValidator(string Property1,string Property2,int MandatoryCount,bool isBucket)
{
this.Property1 = Property1;
if(!String.IsNullOrEmpty(Property2))
this.Property2 = Property2;
this.isBucket = isBucket;
numberOfMandatoryEntities = MandatoryCount;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
object property2Value = null;
object property1Value = null;
int property1Count=0;
int trafficCount = 0;
if(!String.IsNullOrEmpty(Property2))
property2Value = validationContext.ObjectInstance.GetType().GetProperty(Property2).GetValue(validationContext.ObjectInstance, null);
property1Value = validationContext.ObjectInstance.GetType().GetProperty(Property1).GetValue(validationContext.ObjectInstance, null);
if (property1Value != null)
{
property1Count = ((IEnumerable<Object>)property1Value).Count();
if (isBucket)
{
IEnumerable<BucketModel> bucket = ((IEnumerable<BucketModel>)property1Value);
var result = bucket.Select(x => x.TrafficPercentage);
foreach (var i in result)
{
trafficCount = trafficCount + i;
}
}
}
if(isBucket)
{
if(trafficCount<100)
{
var x = new ValidationResult(string.Format("Percentage total cannot be less than 100 %", validationContext.DisplayName));
return x;
}
}
if (property2Value != null)
{
property1Count = property1Count +((IEnumerable<Object>)property2Value).Count();
}
if (property1Count < numberOfMandatoryEntities)
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
#region IClientValidatable Members
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var x = new ModelClientValidationRule();
x.ValidationType = "entityvalidator";
x.ErrorMessage = string.Format(ErrorMessageString, metadata.GetDisplayName());
x.ValidationParameters.Add("mandatoryentity", numberOfMandatoryEntities);
x.ValidationParameters.Add("checkforbucket", isBucket);
return new[]
{
x
};
}
现在的问题是:
1)当集合中有多个值时,IsValid 返回错误,但没有发现绑定到 ModelState 中的任何属性!添加伪属性是一种选择,但有什么比这更好的方法呢?
2) 通过为每个规则添加伪属性并在 clientvalidationrules 中指定函数,并将适配器添加到验证中,可以轻松获取此验证器客户端。 但这种方法似乎不太合适,只是一种解决方法,有没有更好的方法呢?
请帮忙...!提前致谢....
I am stuck with creating the custom validators to satisfy our project's buisness rules.
Now below given is the model :
public class CreateTestModel
{
public CreateTestModel()
{
[Required]
public string Name { get; set; }
public string Description { get; set; }
public string BucketValidator { get; set; }
public RadioButtonListViewModel<GoalTypes> Goals { get; set; }
[EntityValidator(Property1:"IncludedEntities",Property2:"ExcludedEntities",MandatoryCount:1,isBucket=false, ErrorMessage = "One Entity is Compulsory")]
public IEnumerable<TestEntityModel> IncludedEntities { get; set; }
public IEnumerable<TestEntityModel> ExcludedEntities { get; set; }
public int MandatoryEntityCount { get; set; }
public IEnumerable<TestFilterModel> IncludedFilters { get; set; }
public IEnumerable<TestFilterModel> ExcludedFilters { get; set; }
[EntityValidator(Property1:"Buckets",Property2:"",MandatoryCount:2,isBucket=true,ErrorMessage = "Bucket is compulsory")]
[DisplayName("BucketErrors")]
public IEnumerable<BucketModel> Buckets { get; set; }
public bool AutoDecision { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int AdminId { get; set; }
[DefaultValue(true)]
public bool IsEnabled { get; set; }
}
upon the above given model i created the Entity validator which is used to satisfy my business rules .But since the validation is to be taken place on the collection properties the Validator fails to put in the error when there are more than one value in the collection, else it checks in the errors generated.
EntityValidator class is as given below :
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class EntityValidator : ValidationAttribute,IClientValidatable
{
public int numberOfMandatoryEntities{get; private set;}
public int totalCountofIncludeEntities { get; private set; }
public bool isBucket { get; set; }
public string Property1{get; private set;}
public string Property2{ get; private set; }
private const string DefaultErrorMessageFormatString = "Atleast one entity is required";
public EntityValidator(string Property1, string Property2, int MandatoryCount)
{
this.Property1 = Property1;
if (!String.IsNullOrEmpty(Property2))
this.Property2 = Property2;
numberOfMandatoryEntities = MandatoryCount;
}
public EntityValidator(string Property1,string Property2,int MandatoryCount,bool isBucket)
{
this.Property1 = Property1;
if(!String.IsNullOrEmpty(Property2))
this.Property2 = Property2;
this.isBucket = isBucket;
numberOfMandatoryEntities = MandatoryCount;
}
public override string FormatErrorMessage(string name)
{
return string.Format(ErrorMessageString, name);
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
object property2Value = null;
object property1Value = null;
int property1Count=0;
int trafficCount = 0;
if(!String.IsNullOrEmpty(Property2))
property2Value = validationContext.ObjectInstance.GetType().GetProperty(Property2).GetValue(validationContext.ObjectInstance, null);
property1Value = validationContext.ObjectInstance.GetType().GetProperty(Property1).GetValue(validationContext.ObjectInstance, null);
if (property1Value != null)
{
property1Count = ((IEnumerable<Object>)property1Value).Count();
if (isBucket)
{
IEnumerable<BucketModel> bucket = ((IEnumerable<BucketModel>)property1Value);
var result = bucket.Select(x => x.TrafficPercentage);
foreach (var i in result)
{
trafficCount = trafficCount + i;
}
}
}
if(isBucket)
{
if(trafficCount<100)
{
var x = new ValidationResult(string.Format("Percentage total cannot be less than 100 %", validationContext.DisplayName));
return x;
}
}
if (property2Value != null)
{
property1Count = property1Count +((IEnumerable<Object>)property2Value).Count();
}
if (property1Count < numberOfMandatoryEntities)
{
return new ValidationResult(ErrorMessage);
}
return ValidationResult.Success;
}
#region IClientValidatable Members
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var x = new ModelClientValidationRule();
x.ValidationType = "entityvalidator";
x.ErrorMessage = string.Format(ErrorMessageString, metadata.GetDisplayName());
x.ValidationParameters.Add("mandatoryentity", numberOfMandatoryEntities);
x.ValidationParameters.Add("checkforbucket", isBucket);
return new[]
{
x
};
}
Now the Problems are :
1) When there are more than one values in the collection the IsValid returns the error but it is not spotted bound to any property in ModelState ! Adding a pseudo property is an option but what is the better way than that ?
2) Taking this validator client side is easy by adding pseudo properties for each rule and specifying the function in the clientvalidationrules, and adding the adaptor to validated.
But this approach doesnt seem very appropriate and just seems a workaround, is there any better way to do so ??
Please help ... ! Thanks in advance....
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当验证规则像您的情况一样变得复杂时,我建议您保留数据注释并转到 FluentValidation.NET ,其中与 ASP.NET MVC 集成(我一直使用它,不仅当验证规则变得复杂)。就客户端验证规则而言,它支持大多数常见规则,但当它变得复杂时,您最好编写自定义适配器。
When validation rules get complicated as in your case I would recommend you leaving data annotations and head over to FluentValidation.NET which has a great integration with ASP.NET MVC (I use it all the time, not only when validation rules get complicated). As far as client validation rules are concerned, it supports most of the common rules but when it gets complicated you are better of writing custom adapters.