Monday, July 27, 2009

Read from DB while clientside validation using asp:CustomValidator (Bypass)

Ok, by saying bypass, I mean I didnt read data from SQL server table while the client side validation. I read it earlier, stored data in a hidden listbox, and used customvalidator to perform the client side validation . Here's how:

1. Declare a hidden list box that can be readable by javascript:

<asp:ListBox ID="uxHiddenListBoxForPermissionName" runat="server" Style="display:none">
</asp:ListBox>

Style="display:none" keeps the item hidden as well as readable by javascript. For my work I needed to add another hidden item, just to make sure that it is an update or add operation:

<asp:TextBox ID="uxTextBoxLog" runat="server" Style="display:none">
</asp:TextBox>

2. Populate data into the listbox from the code behind file:

Put this method in the code behind file (.cs):
private void GenerateHiddenListBox()
{
uxHiddenListBoxForPermissionName.Items.Clear();
ListItem item;
DataRowCollection rowCollection = Manager.GetManager().RoleManager.GetPermissions().Rows;
foreach (DataRow row in rowCollection)
{
item = new ListItem();
item.Value = row["Id"].ToString();
item.Text = row["Name"].ToString();
uxHiddenListBoxForPermissionName.Items.Add(item);
}
}

Manager.GetManager().RoleManager.GetPermissions() is the method that is used to read the table from DB. Replace it with yours. You should run this method each time there has been any change in the table (ex: new row added/ existing row modified/ deleted)

3. Add the customValidator to the field that you want to validate, along with other validators (if any):

<tr valign="top">
<td style="width: 20%">
<asp:Label ID="Label7" runat="server" Text="<%$Resources:Texts,Name %>"></asp:Label>
</td>
<td style="width: 40%">
<asp:TextBox ID="uxName" runat="server" MaxLength="50" Width="97%"></asp:TextBox>
</td>
<td style="width: 40%">

<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="*"
ValidationGroup="PermissionValidation" ControlToValidate="uxName" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>


<asp:CustomValidator runat="server" ID="uxCustomValidator" ClientValidationFunction="checkNames"
ControlToValidate="uxName" ValidationGroup="PermissionValidation" ErrorMessage="
<%$Resources:Texts,PermissionNameAlreadyExists %>" SetFocusOnError="True" Display="Dynamic">
</asp:CustomValidator>

</td>
</tr>

here I am validaing the uxName field. I'm using the asp:RequiredFieldValidator to check the field is nonempty, and using the asp:CustomValidator to check whether the entry already exists or not.

4. Write the client side function to perform the validation (this function is referred from asp:customvalidator):

<script type="text/javascript" >

function checkNames(source, args){
var permissionNameList= document.getElementById(uxPermissionListClientId);
var nameField= document.getElementById(uxNameClientId);
//alert(permissionNameList.length);
// alert(nameField.value);
var logText= document.getElementById(uxTextBoxLogClientId).value;
//alert(logText);
if(logText=='New'){ //I've set the value of textbox to 'New' while performing add operation
for(var i=0;i
<permissionNameList.length;i++){
//alert(permissionNameList.options[i].text);

if(permissionNameList.options[i].text==nameField.value){
// alert('validation is false, brother');
args.IsValid=false;
}
}
}
else{ //else I've set the value of the hidden text field to the current item to exclude it from comparing.
for(var i=0;i
<permissionNameList.length;i++){
//alert(permissionNameList.options[i].text);

if(permissionNameList.options[i].text==nameField.value&&nameField.value!=logText){
// alert('validation is false, brother');
args.IsValid=false;
}
}
}
}
</script>

uxPermissionListClientId is the client id for list box where data is stored reading from table, uxNameClientId is the client id of the textbox for which the validation is being performed, and uxTextBoxLogClientId is the client id of uxTextBoxLog, the hidden text box where I keep track whether an adding or updating event is going on. setting args.IsValid=false means there is an error, validation will not pass, and postback will not occure.