简体   繁体   中英

Any better way to handle user input validation?

I have a 3 layered system of presentation, logic, and data access. In my logic layer, I have a Validate() method which makes sure that the data that's about to get forwarded to the data access layer is valid for the database (no nulls where nulls are not allowed, and so on).

On top of that, in the .aspx presentation layer, we have some user-friendly error checking and validation, directly checking the controls on the web form. My problem is the ValidateInput() method in the code behind which checks the controls, it's several hundreds of lines long and really annoying to maintain. The code for checking the data is far far longer than the code that does the actual work.

What I've got looks like this:

        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.
        }

We have a nice styled notification box hidden in the master page that gets turned from Visible false to true when we call it, creating the "illusion" of an overlaying box. It looks really nice and works really well so we want to use it. The idea is that we gather up all the errors for the whole form, put them in a list, and then send that list to the notification box, which then gives you all the errors in one nice list.

But the Validate() is just a torturous amount of "if" statements and it's hard to keep track of. Is this just the nature of input validation, or is there some other, better way of handling this?

I think you can able to avoid using these kind of If statements using a Generic function. My suggestion is to define a function like this

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

enum ValidationType
{
    NoNullValues,
    Integer,
    // etc
}

Please modify the function. Also checks the syntax, I am using notepad to write the code. This approach also helps you to achieve re-useabilty if you are use all validation methods in a separate class.

Thanks

Couple of the different ways that I had handled it (in different projects) :

  1. Use custom control library - controls were simply extending existing ASP.NET/3rd party controls to add validation logic which was controlled by properties such as IsMandatory, MandatoryMessage etc. Properties were typically set at the design-time (and were not backed by view-state). The validation logic would accumulate error messages in the message collection exposed by base page. Another variant had used user controls combining ASP.NET controls along with validators but frankly speaking, ASP.NET validators sucks.

  2. Essentially a base page class had a validation logic that would traverse the control collection within the page and then perform validation based on control type. The page would offer a registry to register control to validate, type of validations and error message to display. There was also method to un-register/skip control validation that was used primarily to skip control traversal within control such as repeater/grid-view.

For client-side(browser side) validation, I had used jquery validation (or own JS library). In both cases above, the validation logic would also emit necessary start-up scripts to set-up the client-side validation - however, #2 could generate a single start-up script (with less size) while #1 entails generating a start-up script per control instance. From flexibility perspective, #1 is better and fits nicely in control based development approach. #2 centralizes your validation logic at one central place (ie a base page) which can be very handy.

a) Create an validation type enum to enumerate all types of validation you want to perform. (In your code you are doing string null checking for both controls which are both textboxes, its unnecessary repetition of code logic) b) Create a class of constants / or resource file that holds all the error messages. c) Write a function that takes a control, Validation type enum, arguments for validation and error message id. It will check the type of control and perform validation as indicated by enum. If error, error message is added to your "errorMessages" collection.

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);
        }
        ...
    }
}

Now you can call the above function on every control you want to validate. One more improvement will be to Implement a base class for all your controls that holds the corresponding error message collection in a property (Dictionary<ValidationType,String>) . Then you can modify the validation function to accept an array of ValidationType enum to perform several validation in one call. Each control will give you its error message for every validation type in its property we created in the base class.

Hope this helps.

Thanks Ven

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM