ValidationAttribute验证特性一般用来验证数据的格式,范围,是否必填等,我们通过它的子类特性Range Required 等特性
可以轻松实现对数据的验证。
但是对于一些特殊需要的特性,系统自带的特性局限性很大,我们就可以自定义扩展需要的特性了。
api的开发中,存在着很多时间范围的查询,一般要求传入开始时间和结束时间 ,并且结束时间必须大于开始时间,只有这样
结束时间才有意义,那么我们就通过时间比较特性来说说如何自定义ValidationAttribute,其他情况由此发散开去。
gogogo!
先上核心代码 ,代码注释很全,不单独详讲
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] //指定在那些元素可以使用该特性
public class DateTimeCompareAttribute : ValidationAttribute
{
/// <summary>
/// 开始时间(比较时间)
/// </summary>
public string minTime { get; set; }
/// <summary>
/// 特性初始化 StartTime字段为当前待比较的开始时间
/// </summary>
/// <param name="StartTime"></param>
public DateTimeCompareAttribute(string StartTime)
{
minTime = StartTime;
}
/// <summary>
/// 格式错误返回消息 非时间格式会触发 本例不需要重写
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public override string FormatErrorMessage(string name)
{
return base.FormatErrorMessage(name);
}
/// <summary>
/// 此方法先于 IsValid(object value)调用
///
/// </summary>
/// <param name="value"></param>
/// <param name="validationContext"></param>
/// <returns></returns>
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var compareDate = (DateTime)value;//当前待验证的结束时间
//validationContext.ObjectInstance 待验证对象
//validationContext.ObjectType 待验证对象类型
var tempData = Convert.ChangeType(validationContext.ObjectInstance, validationContext.ObjectType);//创建待验证对象
System.Reflection.PropertyInfo propertyInfo = validationContext.ObjectType.GetProperty(minTime); //获取指定名称的属性
if (!DateTime.TryParse(propertyInfo.GetValue(tempData, null).ToString(), out DateTime minTimeDate)) //获取属性值
{
//如果开始时间也为时间格式 此代码不会进入
return new ValidationResult($"{minTime}不是时间格式");
}
else
{ //比较2个时间 如果结束时间小于等于开始时间 返回错误消息
//可以根据业务自定义添加参数 比较是否需要等于
if (compareDate <= minTimeDate)
{
return new ValidationResult($"{minTime}不能大于等于当前时间");
}
}
return base.IsValid(value, validationContext);
}
/// <summary>
/// 当前值是否有效
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override bool IsValid(object value)
{
if (!DateTime.TryParse(value.ToString(), out DateTime minTimeDate))
{
return false;
}
else
{
return true;
}
}
}
调用过程 实体对象部分:
/// <summary>
/// 起始时间
/// </summary>
[Required(ErrorMessage = "请输入起始时间")]
public DateTime StartTime { get; set; }
/// <summary>
/// 结束时间
/// </summary>
[Required(ErrorMessage = "请输入结束时间")]
[DateTimeCompare("StartTime")]
public DateTime EndTime { get; set; }
控制器参数验证:
if (!ModelState.IsValid)
{
var errMsg= ModelState
.Where(v => v.Value.Errors.Any())
.Select(c => c.Value.Errors
.Where(x => !string.IsNullOrWhiteSpace(x.ErrorMessage)).FirstOrDefault().ErrorMessage).FirstOrDefault();
}
控制器中,调用对象的验证 获取验证消息 进行具体的操作处理
后面2个代码段其实和调用系统验证是一样的,我单独提出来,让不是特别了解的同学好百度相关内容!么么哒!