【问题标题】:Any better way to handle user input validation?有更好的方法来处理用户输入验证吗?
【发布时间】:2012-03-19 16:15:36
【问题描述】:

我有一个表示、逻辑和数据访问的 3 层系统。在我的逻辑层中,我有一个 Validate() 方法,它确保将要转发到数据访问层的数据对数据库有效(不允许空值的情况下没有空值,等等)。

最重要的是,在 .aspx 表示层中,我们有一些用户友好的错误检查和验证,直接检查 Web 表单上的控件。我的问题是检查控件的代码中的 ValidateInput() 方法,它有数百行长,维护起来真的很烦人。检查数据的代码远比实际工作的代码长。

我得到的是这样的:

        private List<string> ValidateInput()
        {
           List<string> errormessages = new List<string>();

           if (LastNameETextBox.Text.Trim() == String.Empty)
           { 
              errormessages.Add("Last name required."); 
           }

           if (FirstNameETextBox.Text.Trim() == String.Empty)
           { 
              errormessages.Add("First name required."); 
           }

           //etc. etc.
        }

我们有一个漂亮的通知框隐藏在母版页中,当我们调用它时,它会从 Visible false 变为 true,从而创建叠加框的“错觉”。它看起来真的很好,而且效果很好,所以我们想使用它。我们的想法是我们收集整个表单的所有错误,将它们放在一个列表中,然后将该列表发送到通知框,然后在一个漂亮的列表中为您提供所有错误。

但是 Validate() 只是大量的“if”语句,很难跟踪。这只是输入验证的本质,还是有其他更好的处理方式?

【问题讨论】:

    标签: c# asp.net validation input error-handling


    【解决方案1】:

    我认为您可以通过通用函数避免使用此类 If 语句。 我的建议是定义这样的函数

    private List<string> ValidateInput(string ErrorMessage, TextBox txtInput, ValidatationType validationType)
    {
        List<string> errormessages = new List<string>();
    
    
        if (validatationType  == ValidationType.NoNullValues)
        { 
    
            if (txtInput.Text.Equals(String.Empty))
                {
                    errormessages.Add(ErrorMessage); 
                }
    
        }
    
        if (validatationType  == ValidationType.Integer)
        { 
    
            int number;
            if (Int32.TryParse(value, out number))
            {
                errormessages.Add(ErrorMessage); 
            }
    
        }
    
        // etc. etc.
    }
    

    枚举验证类型

    enum ValidationType
    {
        NoNullValues,
        Integer,
        // etc
    }
    

    请修改功能。还要检查语法,我正在使用记事本编写代码。 如果您在单独的类中使用所有验证方法,这种方法还可以帮助您实现可重用性。

    谢谢

    【讨论】:

    • 啊,我明白你在做什么了。谢谢!这绝对是对我现在所拥有的改进。
    【解决方案2】:

    我处理它的几种不同方式(在不同的项目中):

    1. 使用自定义控件库 - 控件只是扩展现有 ASP.NET/3rd 方控件以添加由 IsMandatory、MandatoryMessage 等属性控制的验证逻辑。属性通常在设计时设置(并且不受视图状态的支持)。验证逻辑将在基页公开的消息集合中累积错误消息。另一个变体使用结合了 ASP.NET 控件和验证器的用户控件,但坦率地说,ASP.NET 验证器很烂。

    2. 本质上,一个基页面类具有一个验证逻辑,该逻辑将遍历页面内的控件集合,然后根据控件类型执行验证。该页面将提供一个注册表来注册要验证的控件、验证类型和要显示的错误消息。还有一种取消注册/跳过控件验证的方法,该方法主要用于跳过控件内的控件遍历,例如中继器/网格视图。

    对于客户端(浏览器端)验证,我使用了jquery validation(或自己的 JS 库)。在上述两种情况下,验证逻辑也会发出必要的启动脚本来设置客户端验证 - 但是,#2 可以生成单个启动脚本(大小更小),而 #1 需要生成启动-up 每个控件实例的脚本。从灵活性的角度来看,#1 更好,并且非常适合基于控制的开发方法。 #2 将您的验证逻辑集中在一个中心位置(即基本页面),这非常方便。

    【讨论】:

      【解决方案3】:

      a) 创建一个验证类型枚举来枚举您想要执行的所有验证类型。 (在您的代码中,您正在对两个都是文本框的控件进行字符串空检查,这是不必要的代码逻辑重复) b) 创建一个包含所有错误消息的常量类/或资源文件。 c) 编写一个函数,该函数接受一个控件、验证类型枚举、验证参数和错误消息 ID。它将检查控件的类型并按照枚举的指示执行验证。如果出现错误,错误消息将添加到您的“errorMessages”集合中。

      enum ValidationType{
          NullCheck,
          IsNumber,
          RangeCheck,
          ....
      }
      
      class ErrorMessages{
          const string FNEMPTY = "First Name is empty";
          ....
      }
      
      class BusinessObject{
          function ValidateControl(Control cntrl, ValidationType type, object[] args, string message)
          {
              if(cntrl is TextBox)
              {
                   if(cntrl as TextBox).Text.Trim() == String.Empty
                        errorMessages.Add(message);
              }
              ...
          }
      }
      

      现在您可以在要验证的每个控件上调用上述函数。另一个改进是为所有控件实现一个基类,该基类在属性(Dictionary&lt;ValidationType,String&gt;) 中保存相应的错误消息集合。然后,您可以修改验证函数以接受 ValidationType 枚举数组,以便在一次调用中执行多个验证。对于我们在基类中创建的属性中的每种验证类型,每个控件都会为您提供错误消息。

      希望这会有所帮助。

      谢谢 文

      【讨论】:

      • 请记住以可重用的方式创建您的函数,即不特定于一种类型的控件。这将帮助您防止重写所有类型控件的逻辑,您也可以在其他项目中使用它:)
      猜你喜欢
      • 2022-01-23
      • 1970-01-01
      • 2014-06-04
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 2016-07-21
      • 2013-01-01
      相关资源
      最近更新 更多