Practical .NET

Integrating Ajax Code into the ASP.NET Validation Infrastructure

Here's how to integrate the ASP.NET CustomValidator control with client-side code to create a page that uses Ajax and server-side code to validate data at the browser.

In a comment to a tip in our ".NET Tips and Tricks" blog, a reader noted that what he needed was an example of how to ensure that no invalid data is entered into a FormView when data had to be validated against several other controls (and had to be checked against server-side data). The solution is to use ASP.NET's CustomValidator control to extend the ASP.NET validation infrastructure with your own code.

However, you also want to notify users as quickly as possible when the data they've entered is unacceptable. Rather than post the whole page back to the server, it makes sense--wherever possible--to validate your data using JavaScript running in the browser. ASP.NET's CustomValidator will do that also. And, with a little Ajax, you can use JavaScript even if you need server-side resources.

For instance, let's say that if the user enters a customer name, I have to check to see if that customer is valid for a combination of two other pieces of data on the form: location and warehouse. Furthermore, that check involves accessing a server-side database. By letting the CustomValidator take care of calling my validation code and displaying the error message, all I have to write is my validation code and pass the data to it…almost.

Setting Up the Server-side Resources
My first step is to add a method to my page that can be called by client-side JavaScript code. That method will accept three values: the customer id, the location id and the warehouse id. I'll put my validation code in that method and return True if the combination is OK, False if it's not. That method's skeleton, with the WebMethod attribute that lets me call it from the browser, looks like this:

  <System.Web.Services.WebMethod()>
  Public Shared Function ValidateCustLocWareH(
                    CustId As String,
                    LocationId As String,
                    WarehouseId As String) As Boolean
    Dim res As Boolean

        'code to validate inputs and set the res variable
    
    Return res

  End Function

Now I need to add the client-side code to check my user's entry. For that, I'll add a CustomValidator to my FormView and set its ControlToValidate property to the TextBox where the user enters the customer id. I'll also set the validator's ClientValidationFunction to the name of a JavaScript function (ValidateCustomerID) that I'll create to handle calling my validation method. Those settings will ensure that my validation code is called at all the right moments, that the user won't be able to send their data to the server while there are errors, and that my error message will be displayed correctly.

Integrating Ajax Code
I can now switch to my .aspx file and write the function I specified in the CustomValidator. My function must accept two parameters, which I'll call source and args:

 <script type="text/javascript">
function ValidateCustomerID(source, args) {

  }
</script>

Of the two parameters, I'm only interested in the arg parameter because it has two useful properties:

  • Value: The current value from the control I'm validating
  • IsValid: When set to false, it causes ASP.NET's validation infrastructure to display the CustomValidator's error message and prevent the page from posting back

In the function's code, I want to call my server-side method (called ValidateCustLocWareH). I can get the customer id it needs from the args parameter's Value property. However, to get the location and warehouse values, which are in textboxes in the FormView, I'll have to use some jQuery to retrieve the values.

In order to use jQuery I'll need to put the jquery-1.4.1.min.js library in my Scripts folder (already done in the latest versions of Visual Studio) and add a script tag to download the library. In order to control the id attribute for the location and warehouse textboxes, I'll have to set their ClientIdMode property to static.

The JavaScript code at the top of my function to retrieve those values looks like this:

 var locid = $("#LocationIdTB").val();
var wrhsid = $("#WarehouseIdTB").val();
All I should have to do now is call my method, passing the three values and use the return value from the method to set the IsValid property on the args parameter. Unfortunately, this is where I have to write some extra code.

The problem is that the default mechanisms for calling my method are all asynchronous; by the time the result gets back from the page manager, my client-side validation function will have finished processing and it will be too late to set the IsValid property. I need to call the method synchronously and wait for the result.

To call the method asynchronously, I have to write two more lines of jQuery code. First, I need to assemble the parameters I'll pass to my method into the JSON format (parameter names and values enclosed in single quotes and separated by a colon; each parameter/value pair separated by a comma):

 var argList = "{'CustId':'"  + args.Value + 
"','LocationId':'" + locid +
"','WareHouseId':'" + wrhsid + "'}";

Then I call jQuery's ajax function, specifying my page and method name in the url property. To have my call executed asynchronously, I must set the async property to false (it defaults to true). If my call succeeds, the function I put in the success property will be called and the result from my server-side method will be passed to it. I can use that result's d property to set the IsValid property that notifies ASP.NET's validation infrastructure that there's bad data on the page:

 
$.ajax({
          type: "POST",
          url: "CCD.aspx/ValidateCustLocWareH",
          data: argList,
          async: false,
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          success: function (res) {  args.IsValid = res.d; },
          fail: function (msg) { alert(msg); }
         });

Putting it all together, this code lets me validate any combination of data items on the page as the user enters their data. When the data passes all my validation checks, the user can -- finally -- click the Update button on the FormView to save their results (and, I assume, go onto the next record).

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at http://blog.learningtree.com/tag/ui/.

comments powered by Disqus

Featured

Subscribe on YouTube