mvc 实体类验证的时候 如果有多个验证特性需要在属性上层叠很多个验证特性,显得属性特别臃肿并且也不够直观,极大地影响我使用它的兴趣,所以我想自定义一个验证特性,然后将所有需要验证的情形全部放在一个特性里,看上去更直观一点。

   [DataContract]public partial class Sys_Menu : BaseModel{[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)][DataMember]public int? MenuID { get; set; }[Validate(DisplayName = "菜单URL", MaxLength = 100)][DataMember]public string URL { get; set; }[Validate(DisplayName = "菜单名", Required = true, MaxLength = 20)][DataMember]public string Name { get; set; }[StringLength(100)]public string Description { get; set; }[DataMember]public int? ParentID { get; set; }public bool? IsActive { get; set; }

自定义的验证特性是不是看上去更清爽一点

实现

 public class ValidateAttribute : ValidationAttribute, IClientValidatable{private const string EmailPattern = @"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$";private const string FixedPhonePattern = @"^(\d{3,4}-)?\d{6,8}$";private const string MobilePhonePattern = @"^1\d{10}$";/// <summary>/// 是否必填项/// </summary>public bool Required { get; set; }/// <summary>/// 数据格式/// </summary>public FieldDataType DataType { get; set; }/// <summary>/// 展示名称/// </summary>public string DisplayName { get; set; }/// <summary>/// 正则表达式/// </summary>public string RegexPattern { get; set; }public int MaxLength { get; set; }public int MinLength { get; set; }/// <summary>/// 验证/// </summary>/// <param name="value"></param>/// <param name="regx"></param>/// <returns></returns>private bool IsMatch(string value, string regx){if (string.IsNullOrEmpty(value)){return false;}bool isMatch = Regex.IsMatch(value, regx);return isMatch;}protected override ValidationResult IsValid(object value, ValidationContext validationContext){if (string.IsNullOrEmpty(DisplayName)){DisplayName = validationContext.MemberName;}//前后有空格if (value is string && !value.Equals(value.ToString().Trim().ToString())){IPropertyAccessor propertyAccessor = Caches.PropertyAccessorCache.Get(validationContext.ObjectType.GetProperty(validationContext.MemberName));if (propertyAccessor != null){propertyAccessor.SetValue(validationContext.ObjectInstance, value.ToString().Trim().ToString());value = value.ToString().Trim().ToString();}}ValidateResult result = Valid(value);if (!result.IsValid){return new ValidationResult(result.ErrorMessage);}else{return ValidationResult.Success;}}/// <summary>/// 验证 如果不是必填项 只要不为空的才验证 待扩展/// </summary>/// <param name="value"></param>/// <returns></returns>public ValidateResult Valid(object value){if (this.Required){if (value == null){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "不能为空" };}if (value is string){if (string.Empty.Equals(value.ToString())){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "不能为空" };}}else if (value is ICollection){if (((ICollection)value).Count == 0){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "条目不能为空" };}}}if (value != null){switch (DataType){case FieldDataType.Email:if (!string.IsNullOrEmpty(value.ToString()) && !IsMatch(value.ToString(), EmailPattern)){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "不满足邮箱格式" };}break;case FieldDataType.FixedPhone:if (!string.IsNullOrEmpty(value.ToString()) && !IsMatch(value.ToString(), FixedPhonePattern)){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "不满足固话格式" };}break;case FieldDataType.MobilePhone:if (!string.IsNullOrEmpty(value.ToString()) && !IsMatch(value.ToString(), MobilePhonePattern)){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "不满足手机格式" };}break;case FieldDataType.Phone:if (!string.IsNullOrEmpty(value.ToString()) && (!IsMatch(value.ToString(), MobilePhonePattern) || !IsMatch(value.ToString(), FixedPhonePattern))){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "不满足电话格式" };}break;}if (!string.IsNullOrEmpty(RegexPattern)){if (!string.IsNullOrEmpty(value.ToString()) && !IsMatch(value.ToString(), RegexPattern)){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "格式不正确" };}}if (MaxLength != 0){if (value is string){if (!string.IsNullOrEmpty(value.ToString()) && value.ToString().Length > MaxLength){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "超出数据最大长度" };}}else if (value is ICollection){if (((ICollection)value).Count > MaxLength){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "超出最大条目" };}}}if (MinLength != 0){if (value is string){if (!string.IsNullOrEmpty(value.ToString()) && value.ToString().Length < MinLength){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "超出数据最小长度" };}}else if (value is ICollection){if (((ICollection)value).Count < MinLength){return new ValidateResult { IsValid = false, ErrorMessage = DisplayName + "超出最小条目" };}}}}return new ValidateResult { IsValid = true, ErrorMessage = DisplayName + "验证通过" };}public override string ToString(){StringBuilder sb = new StringBuilder();if (this.Required){sb.Append("Required");}if (DataType != FieldDataType.None){sb.Append(" DataType:" + DataType.ToString());}if (!string.IsNullOrEmpty(RegexPattern)){sb.Append(" RegexPattern:" + RegexPattern.ToString());}if (MaxLength != 0){sb.Append(" MaxLength:" + MaxLength.ToString());}if (MinLength != 0){sb.Append(" MinLength:" + MinLength.ToString());}return sb.ToString();}public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context){throw new NotImplementedException();}}

可以根据自己的想法去验证

最后说说为什么要重写一个ToString(),这个是给HelpPage 接口说明文档使用的 我们将这个特性扩展进去,接口文档里开发人员就可以看到验证的说明

  public class ModelDescriptionGenerator{// Modify this to support more data annotation attributes.private readonly IDictionary<Type, Func<object, string>> AnnotationTextGenerator = new Dictionary<Type, Func<object, string>>{{ typeof(RequiredAttribute), a => "Required" },{ typeof(RangeAttribute), a =>{RangeAttribute range = (RangeAttribute)a;return String.Format(CultureInfo.CurrentCulture, "Range: inclusive between {0} and {1}", range.Minimum, range.Maximum);}},{ typeof(MaxLengthAttribute), a =>{MaxLengthAttribute maxLength = (MaxLengthAttribute)a;return String.Format(CultureInfo.CurrentCulture, "Max length: {0}", maxLength.Length);}},{ typeof(MinLengthAttribute), a =>{MinLengthAttribute minLength = (MinLengthAttribute)a;return String.Format(CultureInfo.CurrentCulture, "Min length: {0}", minLength.Length);}},{ typeof(StringLengthAttribute), a =>{StringLengthAttribute strLength = (StringLengthAttribute)a;return String.Format(CultureInfo.CurrentCulture, "String length: inclusive between {0} and {1}", strLength.MinimumLength, strLength.MaximumLength);}},{ typeof(DataTypeAttribute), a =>{DataTypeAttribute dataType = (DataTypeAttribute)a;return String.Format(CultureInfo.CurrentCulture, "Data type: {0}", dataType.CustomDataType ?? dataType.DataType.ToString());}},{ typeof(RegularExpressionAttribute), a =>{RegularExpressionAttribute regularExpression = (RegularExpressionAttribute)a;return String.Format(CultureInfo.CurrentCulture, "Matching regular expression pattern: {0}", regularExpression.Pattern);}},{ typeof(ValidateAttribute), a =>{ValidateAttribute validateExpression = (ValidateAttribute)a;return String.Format(CultureInfo.CurrentCulture, "Customer Validate: {0}", validateExpression.ToString());}},};

顺带说一下,假如我的实体层是独立的 也需要做一些配置

首先要自定义一个MultiXmlDocumentationProvider

 public class MultiXmlDocumentationProvider : IDocumentationProvider, IModelDocumentationProvider{/*********** Properties*********//// <summary>The internal documentation providers for specific files.</summary>private readonly XmlDocumentationProvider[] Providers;/*********** Public methods*********//// <summary>Construct an instance.</summary>/// <param name="paths">The physical paths to the XML documents.</param>public MultiXmlDocumentationProvider(params string[] paths){this.Providers = paths.Select(p => new XmlDocumentationProvider(p)).ToArray();}/// <summary>Gets the documentation for a subject.</summary>/// <param name="subject">The subject to document.</param>public string GetDocumentation(MemberInfo subject){return this.GetFirstMatch(p => p.GetDocumentation(subject));}/// <summary>Gets the documentation for a subject.</summary>/// <param name="subject">The subject to document.</param>public string GetDocumentation(Type subject){return this.GetFirstMatch(p => p.GetDocumentation(subject));}/// <summary>Gets the documentation for a subject.</summary>/// <param name="subject">The subject to document.</param>public string GetDocumentation(HttpControllerDescriptor subject){return this.GetFirstMatch(p => p.GetDocumentation(subject));}/// <summary>Gets the documentation for a subject.</summary>/// <param name="subject">The subject to document.</param>public string GetDocumentation(HttpActionDescriptor subject){return this.GetFirstMatch(p => p.GetDocumentation(subject));}/// <summary>Gets the documentation for a subject.</summary>/// <param name="subject">The subject to document.</param>public string GetDocumentation(HttpParameterDescriptor subject){return this.GetFirstMatch(p => p.GetDocumentation(subject));}/// <summary>Gets the documentation for a subject.</summary>/// <param name="subject">The subject to document.</param>public string GetResponseDocumentation(HttpActionDescriptor subject){return this.GetFirstMatch(p => p.GetDocumentation(subject));}/*********** Private methods*********//// <summary>Get the first valid result from the collection of XML documentation providers.</summary>/// <param name="expr">The method to invoke.</param>private string GetFirstMatch(Func<XmlDocumentationProvider, string> expr){return this.Providers.Select(expr).FirstOrDefault(p => !String.IsNullOrWhiteSpace(p));}}

  public static class HelpPageConfig{[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",MessageId = "Panasia.UserCenter.WebAPI.Areas.HelpPage.TextSample.#ctor(System.String)",Justification = "End users may choose to merge this string with existing localized resources.")][SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly",MessageId = "bsonspec",Justification = "Part of a URI.")]public static void Register(HttpConfiguration config){// Uncomment the following to use the documentation from XML documentation file.//config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));config.SetDocumentationProvider(new MultiXmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/UserCenter.Model.xml"), HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));

右键项目属性设置XML文件生成路径

..\XXX.UserCenter.WebAPI\App_Data\XXX.UserCenter.Model.xml

转载于:https://www.cnblogs.com/njcxwz/p/7170499.html

mvc 实体类 自定义验证特性相关推荐

  1. ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)

    ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需要将相应的ValidationAttri ...

  2. Asp.net MVC验证那些事(4)-- 自定义验证特性

    在项目的实际使用中,MVC默认提供的Validation Attribute往往不够用,难以应付现实中复杂多变的验证需求.比如, 在注册用户的过程中,往往需要用户勾选"免责声明", ...

  3. mvc model类添加验证功能

    ASP.NET MVC3新增了许多新特性,IValidatableObject接口就是新增的诸多特性之一.ASPNET MBC3该书中是这样描述的:IValidatableObject 接口允许执行 ...

  4. MyBatisPlus3.x代码生成器生成实体类自定义需要填充的字段

    场景 MyBatisPlus3.x中使用代码生成器(全注释): https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/89518466 M ...

  5. MultipleRegularExpressionAttribute MVC中扩展自定义验证规则

    好久都没有写博客,最近工作中没有什么可写的,公司的项目是以业务为重,技术含量实在不咋的.这次sprint中有一个要求就是password必须一些规则,比如给你一些正则表达式必须满足几个,直接看效果吧 ...

  6. 专题---自定义实体类

    目录 一.概述 二.项目初始化 2.1 创建空解决方案 2.2 DBX操作 2.2.1 创建DBX 2.2.2 调试DBX 2.2.3 创建实体类 2.2.4 调试实体类 2.3 ARX操作 2.3. ...

  7. ASP.NET MVC 4 (十) 模型验证

    模型验证是在模型绑定时检查从HTTP请求接收的数据是否合规以保证数据的有效性,在收到无效数据时给出提示帮助用户纠正错误的数据. 显式模型验证 验证数据最直接的方式就是在action方法中对接收的数据验 ...

  8. ASP.NET Core MVC 中的模型验证

    数据模型的验证被视为是数据合法性的第一步,要求满足类型.长度.校验等规则,有了MVC的模型校验能够省却很多前后端代码,为代码的简洁性也做出了不少贡献. 原文地址:https://docs.micros ...

  9. eclipse mysql生成实体类_Eclipse实现数据库反向生成实体类(pojo)-------(插件安装和实现步骤的说明)...

    一.插件安装 1.下载插件: http://jaist.dl.sourceforge.net/sourceforge/jboss/HibernateTools-3.2.4.Beta1-R2008103 ...

  10. 【ASP.NET MVC4】第八课:MVC数据验证、验证特性、自定义验证

    知识点:MVC数据验证概述.验证特性的使用.自定义验证.扩充基于 Entity Framework 的数据模型. 1.MVC 数据验证概述 1.1  为什么要进行数据验证 ASP.NET MVC 中的 ...

最新文章

  1. Portainer 安装与配置
  2. 动态规划(一)简单例子
  3. stm32的dma缓冲区长度,,存放数据数组会不会冲掉
  4. 总结PHP中DateTime的常用方法
  5. javascript中的replace方法
  6. ListCtrl::DeleteColumn的一点小经验
  7. C语言之函数指针和函数的首地址
  8. 用python + openpyxl处理excel(07+)文档 + 一些中文处理的技巧
  9. Linux内核机器ID,linux-如何强制内核重新读取/重新初始化PCI设备ID?
  10. Linux笔记19.postfix邮件服务器配置安装
  11. 个人展示-LICHUNHUI
  12. 使用openssl 来生成rsa pkcs1 2048格式的公私钥
  13. Tensorflow2.0之FGSM
  14. openCV视频教程
  15. 利用aether api实现从指定maven仓库下载jar包
  16. 华为云IOT的应用侧开发Java Demo使用详细教程(IntelliJ IDEA 开发)
  17. MCE | 靶向相分离 小分子药物研发
  18. 四种 AI 技术方案,教你拥有自己的 Avatar 形象
  19. 3GPP: TS 38.300 NR; Overall description - 1.物理层
  20. 佳明表盘 c语言开发的吗,Garmin MonkeyC的写法和经验

热门文章

  1. Eclipse的MAT的支配树
  2. navicat 执行sql文件
  3. 7步轻松设置授权管理器License Manager
  4. (10) IFC中的构件与空间结构(IfcRelContainedInSpatialStructure) (Industry Foundation Class)
  5. peer channel create解析
  6. session自动登录抽屉网(自动携带cookie)
  7. Codeforces Round #531 F. Elongated Matrix (状压dp)
  8. decorview、window、dialog关系详解
  9. 【BAT】BAT 阶段技能汇总:全功能小程序
  10. 计算机学院三行情书,【计算机·头条】“当你老了”三行情书颁奖晚会