zoukankan      html  css  js  c++  java
  • 基于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来完成,为了节省篇幅代码就不写了,具体的可以查看源码。

    结尾

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

  • 相关阅读:
    Spring Boot 使用 Dom4j XStream 操作 Xml
    Spring Boot 使用 JAX-WS 调用 WebService 服务
    Spring Boot 使用 CXF 调用 WebService 服务
    Spring Boot 开发 WebService 服务
    Spring Boot 中使用 HttpClient 进行 POST GET PUT DELETE
    Spring Boot Ftp Client 客户端示例支持断点续传
    Spring Boot 发送邮件
    Spring Boot 定时任务 Quartz 使用教程
    Spring Boot 缓存应用 Memcached 入门教程
    ThreadLocal,Java中特殊的线程绑定机制
  • 原文地址:https://www.cnblogs.com/ahl5esoft/p/3274073.html
Copyright © 2011-2022 走看看