• 基于easyui的webform扩展(续)


    回顾

      《前端基于easyui的mvc扩展》《前端基于easyui的mvc扩展(续)》《基于easyui的webform扩展》这几篇讲解了如何在mvc以及web form内来实现前端使用easyui以及在后端使用基于ValidationAttribute进行验证(mvc本身就有支持),但是这都是以Framework4.0为基础的,那么当我们遇到3.5或者是更早以前的版本的时候,现在这套应用就需要重新重构了。

      首先来梳理一下整个流程,大致的流程如下:

    1. 通过调用需要展示的控件方法
    2. 解析属性上的验证元数据
    3. 生成符合easyui验证规则的html
    4. 提交表单到后端
    5. 对表单转化后的对象进行验证
    6. 如果通过验证则可以对对象进行操作,不通过则直接返回

      mvc和web form在前端的方式基本上都是用一样的,那么也就是说要让我们编写的代码能支持更多的版本的情况下,假如我们自己实现一套验证特性的话,那么只要让前端生成的规则保持一致,后端的话,只有web form是自己去验证这一步的。

    实现

      那么参考前几篇的结果以及ValidationAttribute,我们很快便能整理出一套跟ValidationAttribute相似的验证特性了,部分代码如下:

    //验证基类
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
    public abstract class CustomValidationBaseAttribute : Attribute
    {
        private object m_Model = null;
        protected object Model { get { return m_Model; } }
    
        private string m_ErrorMessage = null;
        public string ErrorMessage
        {
            get { return m_ErrorMessage; }
            set { m_ErrorMessage = value; }
        }
    
        public bool IsValid(object model, object value)
        {
            if (model == null)
                return false;
    
            m_Model = model;
            return IsValid(value);
        }
    
        public virtual string FormatErrorMessage(string displayName)
        {
            return string.Format(ErrorMessage, displayName);
        }
    
        protected abstract bool IsValid(object value);
    }
    
    //必填特性
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    public class CustomRequiredAttribute : CustomValidationBaseAttribute
    {
        protected override bool IsValid(object value)
        {
            return value != null && !string.IsNullOrEmpty(value.ToString());
        }
    }
    

      有了特性,那么接下来只要根据不同的环境,来生成相同的easyui验证规则就可以了。

      首先分析一下各种控件的规则,主要有以下3种情况:

    1. linkbutton这种不需要进行数据绑定,只要显示文本或某些属性的
    2. validatebox、numberbox、combobox等是需要解析表达式,在model存在的情况下,要显示出值的
    3. Label只要显示属性上配置的DisplayName的,虽然不是easyui的控件,但是2里面的控件共用表达式树的解析

      其实以上2-3的区别仅仅是在控件上添加一个属于easyui的样式表而已,于是使用如下2中类来区分以上3种情况,代码如下:

    internal class BuilderBase
    {
        public BuilderBase(string tag, string attributeJson) : this(tag, null, attributeJson) { }
    
        public BuilderBase(string tag, string control, string attributeJson)
        {
            //省略,文章最后提供详细源码
        }
    
        //扩展Builder,比如Linkbutton要添加文本或其他编辑控件要增加name及验证规则
        protected virtual void ExpandFor(TagBuilder builder) { }
    }
    
    internal class ParseExpressionBuilder : BuilderBase
    {
        public ParseExpressionBuilder(string tag, Expression<Func<TModel, object>> expression, string attributeJson) : this(tag, null, expression, default(TModel), attributeJson) { }
    
        public ParseExpressionBuilder(string tag, string control, Expression<Func<TModel, object>> expression, TModel model, string attributeJson) : base(tag, control, attributeJson)
        {
            //略
        }
    
        protected override void ExpandFor(TagBuilder builder)
        {
            //略
        }
    
        //此方法用来处理不同控件的绑定值操作
        protected virtual void AppendValue(ref TagBuilder builder, object value)
        {
            if (value != null)
                builder.AddAttribute("value", value.ToString());
        }
    }
    

       这里将具体的生成规则都放在了一些列的Builder内,但是为了保证在mvc和web form内能生成相同easyui的easyui规则,由于我们自定义的规则是参考ValidationAttribute的,因此我们只要根据接口来实现我们自定义的那一部分就可以了,其实只要适当的修改第一篇文章内的生成规则便可以完工了,部分代码如下:

    //这里挑选了必填验证的代码,跟之前的相比仅仅是验证特性的对象不同而已
    var attribute = validationAttrs.FirstOrDefault(attr => attr is CustomRequiredAttribute);
    if (attribute != null)
    {
        tag.AddAttribute("required", "true");
        tag.AddAttribute("missingMessage", attribute.ErrorMessage);
    }
    

      而上篇提到的EasyUIHelper仅仅是提供给外部生成的公用方法而已,它的代码大致如下:

    public class EasyUIHelper
    {
        public static string Label(Expression<Func<TModel, object>> expression, string attributeJson)
        {
            return new LabelBuilder(expression, attributeJson);
        }
    
        public static string ValidateText(Expression<Func<TModel, object>> expression, TModel model, string attributeJson)
        {
            return new ValidateboxBuilder(expression, model, "text", attributeJson);
        }
        //针对3.5的其他重构和其他方法省略,具体请看源码
    }
    

       完成了前端的生成规则以后,接下来就是对于后端验证进行重构了,代码与之前的差别不大,仅仅是把原本基于ValidationAttribute改为基于CustomValidationBaseAttribute来完成,为了节省篇幅代码就不写了,具体的可以查看源码。

    结尾

      由于本篇是基于前几篇的一个总结和对之前版本的兼容,因此内容相对比较少,如果对这几篇的内容有什么问题请指出,谢谢大家,另外源码在此(从代码库中抽出来的一部分)。

  • 相关阅读:
    linux上的常用的进程与内存优化命令
    ubuntu 上运行的django 出现No space left on device错误
    openstack 使用pbr配置,setup.cfg的格式与含义
    openstack中安装包与组件
    对drf序列化器的理解
    对商品数据表的理解
    首页广告数据表的理解
    对省市区地址的理解
    对邮箱验证的理解
    用户中心个人信息实现的理解
  • 原文地址:https://www.cnblogs.com/ahl5esoft/p/3274073.html
Copyright © 2020-2023  润新知