• mvc 实体类 自定义验证特性


    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 = @"^1d{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.WebAPIApp_DataXXX.UserCenter.Model.xml

  • 相关阅读:
    使用 OpCache 提升 PHP 性能
    在线视频开发博客教程
    修正ECMALL在PHP5.3以上版本中无法开启支付方式的BUG
    第二个小项目的讲解后感言
    mybatis进行分页,使用limit
    mybatis传递多个参数值(转)
    一个关于前端页面的小标签<tbody>
    json-lib的一些过滤操作
    关键字volidate和transient(转)
    Java中实现序列化的两种方式 Serializable 接口和 Externalizable接口
  • 原文地址:https://www.cnblogs.com/njcxwz/p/7170499.html
Copyright © 2020-2023  润新知