Wednesday, December 23, 2009

Data type validation using validation control

While developing ASP.NET application you would have come across scenarios where you would like to validate whether the value entered is of a particular data type. The options available with an ASP.NET developer is to write javascript functions to check whether the entered value complies with a data type or make the page postback and check the data type in server side. These two options are time consuming. Is there any simple way of doing this? The answer is to the question is “YES”. One can make use of compare validator to accomplish the task very easily. Lets see how.

To compare whether the entered value is of a particular data type one should make sure that the “Operator” property of compare validator should be “DataTypeCheck” and the “Type” property should be the data type you want to check. These two things are the only requirement to validate the data type. Compare validator supports validation for Currency, Date, Double, Integer and String data type. Below is a sample code which tries to check all these data types.

Enter string: <asp:TextBox ID="txtString" runat="server"></asp:TextBox>
<asp:CompareValidator ID="cmpVldString" runat="server" ErrorMessage="Not a valid string." ControlToValidate="txtString"
Type="String" Operator="DataTypeCheck"> </asp:CompareValidator>
<br />
Enter integer: <asp:TextBox ID="txtInt" runat="server"> </asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" runat="server" ErrorMessage="Not a valid Integer." ControlToValidate="txtInt"
Type="Integer" Operator="DataTypeCheck"> </asp:CompareValidator>
<br />
Enter double: <asp:TextBox ID="txtDouble" runat="server"> </asp:TextBox>
<asp:CompareValidator ID="CompareValidator2" runat="server" ErrorMessage="Not a valid double." ControlToValidate="txtDouble"
Type="Double" Operator="DataTypeCheck"> </asp:CompareValidator>
<br />
Enter date: <asp:TextBox ID="txtDate" runat="server"> </asp:TextBox>
<asp:CompareValidator ID="cmpVldDate" runat="server" ErrorMessage="Not a valid date." ControlToValidate="txtDate"
Type="Date" Operator="DataTypeCheck" > </asp:CompareValidator>
<br />
Enter currency: <asp:TextBox ID="txtCurrency" runat="server"> </asp:TextBox>
<asp:CompareValidator ID="cmpVldCurrency" runat="server" ErrorMessage="Not a valid currencys." ControlToValidate="txtCurrency" Type="Currency" Operator="DataTypeCheck" > </asp:CompareValidator><br />
<asp:Button ID="Button1" runat="server" Text="Button" />

In the above code sample you can see that I am checking the datatype for string, Integer, date, double and finally currency. Isn’t it so easy to check the data type?

Now since we are validating date you would like to check against a particular format say “DD/MM/YYYY”. The default date format against which the compare validator checks the date is “YYYY/MM/DD”. One way specify the date format is to assign the page’ culture to the required culture which supports your date format. Say we want to check “DD/MM/YYYY” then we can set the following in the code behind.

protected void Page_Load(object sender, EventArgs e)
{
    Page.Culture = "hi-IN";

In the above code we are setting the culture for the page as Hindi-India which will accept the date in “DD/MM'/YYYY” format. Another way specifying the format in compare validator is to assign culture to the control which is specified in “ControlToValidate” property of the compare validator. For e.g. you have date picker assigned to a compare validator then assigning the culture or date format to the date picker will do the trick. As such there is no way to specify date format or culture to a compare validator.

Note: When you use compare validator to check currency data type keep in mind it doesn’t check for currency symbol compliance.

Try to know more…..

Sandeep

Monday, December 21, 2009

Retrieving controls from an ASP.NET GridView control using javascript.

In our day to day ASP.NET programming we would have used GridView for one or the other purpose. There would have been requirement to access the controls inside a GridView from javascript. Whenever I had to use the ASP.NET GridView control, nearly 95% of the time I had to access the controls inside the GridView using javascript for one or the other purpose. With this blog I wanted to show how easily you can retrieve controls rendered inside a GridView from javascript. I would like to highlight this by taking an age old design where you will have a checkbox in the header and another set of checkboxes in the column below. Checking the checkbox in the header would select all the checkboxes in the column and un-checking a single checkbox in the column would un-check the header checkbox. This strategy can be used to access any type of controls not only inside the GridView but other data rendering controls as well. Now lets see the code for the same.

<asp:GridView ID="gvChk" runat="server" AutoGenerateColumns="False"
            BackColor="White" BorderColor="#DEDFDE" BorderStyle="None" BorderWidth="1px"
            CellPadding="4" ForeColor="Black" GridLines="Vertical"
            onrowdatabound="gvChk_RowDataBound">
            <RowStyle BackColor="#F7F7DE" />
            <Columns>
                <asp:TemplateField HeaderText="Sl. No">
                    <EditItemTemplate>
                        <asp:TextBox ID="TextBox1" Text='<%#Eval("No") %>' runat="server"></asp:TextBox>
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text='<%#Eval("No") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <EditItemTemplate>
                        <asp:CheckBox ID="CheckBox1" runat="server" />
                    </EditItemTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="CheckBox1" runat="server" />
                    </ItemTemplate>
                    <HeaderTemplate>
                        <asp:CheckBox ID="chkHeader" onclick="javascript:selectAllCheckboxInGrid(<% gvChk.ClientID; %>, this);"
                            runat="server" />
                    </HeaderTemplate>
                </asp:TemplateField>
            </Columns>
            <FooterStyle BackColor="#CCCC99" />
            <PagerStyle BackColor="#F7F7DE" ForeColor="Black" HorizontalAlign="Right" />
            <SelectedRowStyle BackColor="#CE5D5A" Font-Bold="True" ForeColor="White" />
            <HeaderStyle BackColor="#6B696B" Font-Bold="True" ForeColor="White" />
            <AlternatingRowStyle BackColor="White" />
</asp:GridView>

The code is very simple with a GridView control having two columns. First column has a label control and second one has a checkbox control. The second column has a checkbox in the header as well. When checkbox in the header is clicked all the checkboxes in the column are selected using javascript. The javascript code to select all the checkboxes in the column are pasted below.

function selectAllCheckboxInGrid(gridID, chk)
{
    var grid = document.getElementById(gridID);
    //Loop starts from 1 because the zeroth row is the header.
    for (var i=1; i< grid.rows.length; i++)
    {
        //Getting the control in the second cell of the grid.
        //Second cell contains the checkbox.
        var cntls = grid.rows[i].cells[1].getElementsByTagName('input');
        //If you are have only one control in the cell then
        //one can do away with the loop.
        for (var j=0; j < cntls.length; j++)
        {
            if (cntls[j].type == "checkbox")
                cntls[j].checked = chk.checked;
        }
    }   
}

The above pasted javascript is straight forward. The javascript function takes two arguments, one is the GridView’ client id and the second is the checkbox in the GridView control’ header. The function starts by getting the grid control using the “getElementById” javascript method of the document object. After getting the GridView control, which is converted to a HTML table once rendered to the browser, we are looping through the rows collection starting from the first row. The zeroth row is the header so we don’t want the loop to start from the header. Starting from the 1st row we loop through the whole rows and get the controls in the second cell of the GridView using the “getElementsByTagName” method of the document object. Then we loop through the control array and check the type of the control and if it is a checkbox we set the checked property based on the checkbox control of the header cell passed as an argument to the javascript function. If you have only one control in the cell then you can directly use “cells[1].children[0].checked = chk.checked” so that you can avoid the loop. The above modified code is pasted below.

function selectAllCheckboxInGrid(gridID, chk)
{
    var grid = document.getElementById(gridID);
    //Loop starts from 1 because the zeroth row is the header.
    for (var i=1; i< grid.rows.length; i++)
    {
        //Getting the control in the second cell of the grid.
        //Second cell contains the checkbox.
        var cntls = grid.rows[i].cells[1].children[0].checked = chk.checked
    }   
}

Next we have to have a function which will check the header checkbox if all the checkbox in the column are checked and if out of all the checked checkboxes anyone is unchecked then we need to uncheck the header checkbox. The simple function is fired when any of the checkboxes in the column are clicked. The javascript function is pasted below.

function checkUncheckHeaderCheckBox(gridID)
{
    var grid = document.getElementById(gridID);
    var checked = true;
    //Loop starts from 1 because the zeroth row is the header.
    for (var i=1; i< grid.rows.length; i++)
    {
        //Getting the control in the second cell of the grid.
        //Second cell contains the checkbox.
        var cntls = grid.rows[i].cells[1].getElementsByTagName('input');
        //If you are have only one control in the cell then
        //one can do away with the loop.
        for (var j=0; j < cntls.length; j++)
        {
            if (cntls[j].type == "checkbox" && !cntls[j].checked)
            {
                checked = cntls[j].checked;
                break;
            }
        }
        if (!checked)
            break;
    }   
    //Get the header checkbox and assign its checked property.
    grid.rows[0].cells[1].children[0].checked = checked;   
}

The above function is pretty straight forward. The “GridView” control id is passed as argument. The function gets the “GridView” control using the “getElementById” function of the document object and loops through the rows starting from the first row leaving the zeroth row. Inside the loop the function retrieves the controls inside the second cell of each row and checks whether any one of the checkbox is unchecked. If so it assigns the “checked” variable as false and breaks the loop. Finally it sets the checked property of the checkbox in the header (zeroth row) to the value of “checked” variable. This function will take care of checking or unchecking the checkbox if all the checkbox in the column are checked or if any one checkbox in the checkbox column is unchecked respectively.

To fire the javascript function on the click of the checkboxes we need to add the javascript function to the “onclick” javascript event. To do this add the following in the “RowDataBound” event of the GridView control.

protected void gvChk_RowDataBound(object sender, GridViewRowEventArgs e)
{
    //Check if the row is of header type.
    if (e.Row.RowType == DataControlRowType.Header)
    {
        //Add the javascript function which gets called
        //when the checkbox in the header is clicked.
        (e.Row.FindControl("chkHeader") as CheckBox).Attributes.Add("onclick", "javascript:selectAllCheckboxInGrid('" + gvChk.ClientID + "', this);");
    }
    else if (e.Row.RowType != DataControlRowType.Footer)
    {
        //Add the javascript function call which gets called
        //when the checkboxes in the column are clicked.
        (e.Row.FindControl("CheckBox1") as CheckBox).Attributes.Add("onclick", "javascript:checkUncheckHeaderCheckBox('" + gvChk.ClientID + "');");
    }
}

With the above code we are ready to go.

The above technique using javascript can be used to retrieve any type of controls (textbox, dropdown, radio button, button, links, images, labels etc) from within the GridView control or any other ASP.NET data rendering controls. You need to make some small javascript changes according to your data bound controls layout. So tweak the code wherever necessary and start retrieving controls.

Try to know more…

Sandeep

Tuesday, December 15, 2009

Serialization in .NET - 4

In my previous blogs on serialization we had looked at the different ways of serializing an objects in .NET. The links to my previous blogs are

Soap Serialization

XML serialization

Binary serialization 

In this blog we will have a look at how to implement custom serialization using ISerializable interface. In my previous blogs on serialization we looked at ways of controlling serialization by way of applying various attributes to the class and its member variables. Applying attributes gives us some control over serialization but doesn’t provide full fledge control. Most of your day to day serialization requirement can be met with the attributes discussed in my previous articles. But if you are the one who wants to take full control over serialization, then ISerializable interface is there for you. Lets first see what is needed to implement ISerializable interface.

The ISerializable interface has got only one method, GetObjectData. In addition to implementing the GetObjectData the implementer should also take care to implement a special constructor to classes implementing ISerializable interface. The constructor is called by the system during the de-serialization process to reconstruct the serialized object. If by chance you forgot to implement the constructor, runtime error will be thrown when one tries to deserialize a class implementing ISerializable interface without the special constructor. The “System.Runtime.Serialization.SerializationException” exception message which is thrown at runtime is pasted below.

The constructor to deserialize an object of type 'ISerializableImplementation.[CLASSNAME]' was not found.

Note: “GetObjectData” will be executed only in the case of binary serialization. For custom serialization in XML and SOAP serialization you need to implement IXmlSerializable interface.

Now lets see and try to understand the GetObjectData and the special constructor.

GetObjectData: The ISerializable method has only one method to be implemented and the signature looks like this “GetObjectData((SerializationInfo info, StreamingContext context)”. The method takes SerializationInfo object as the first argument. SerializationInfo class can be used to store the required data to serialize and deserialize an object. Its the responsibility of the implementer to fill the SerializationInfo class with the necessary data. The implementer can decide on which member variables to store and which ones he doesn’t want to save. While doing this care should be taken to see that sufficient information is serialized for the objects to be deserialized. You can use the “AddValue” overloaded methods to add values to the SerializationInfo class. StreamingContext, the second argument in the method can be used to check the source from which the serialization request has come. Use the StreamingContext.State to check the source. Usage of StreamingContext is given at the end of the blog.

Special constructor: The signature of the special constructor is as follows “(SerializationInfo info, StreamingContext context)”. The paremeters for the constructor are also the same. So I will not spend time explaining these. The special constructor is executed when an object (whose class has implemented ISerializable interface) is deserialized. If the special constructor is not implemented the system will not throw any compile time error but it will throw a runtime exception. So make sure a class which implements ISerializable interface has an explicit implementation of the special constructor which takes SerializationInfo and StreaminContext as its constructor argument. The special constructor should be private or protected if you intent to inherit the class.

Things to note before you implement ISerializable interface

Keep the following things in mind before you implement the ISerializable Interface.

  • The class should have the Serializable attribute applied to it. If the class is not marked with the Serializable attribute an exception of type “System.Runtime.Serialization.SerializationException” will be thrown with the following error message.

Type 'ISerializableImplementation.[CLASSNAME]' in Assembly 'ISerializableImplementation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.

  • NonSerializable attribute should not be used as it will not have any effect.
  • Special constructor with the same argument as that of GetObjectData method must be implemented and should be private or protected.
  • If the ISerializable implemented class is derived from a base class which also implements ISerializable interface then the parent class’ GetObjectData and special constructor should be called before the child class’ function and special constructor.

That’ enough about the ISerializable interface implementation, now you will be eager to see the real implementation. The implementation is also pretty easy and straight forward. As usual lets take the Car class and implement ISerializable interface to it. The code sample is pasted below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace ISerializableImplementation
{
    [Serializable]
    public class Car : ISerializable
    {
        public Car()
        {}

        public Car(SerializationInfo info, StreamingContext context)
        {
            this.Color = info.GetString("CarColor");
            this.CubicCentimeter = info.GetDouble("CC");
            this.ModelName = info.GetValue("Model", typeof(string)).ToString();
        }

        public string Color
        { get; set; }
        public string ModelName
        { get; set; }
        public int Price
        { get; set; }
        public double CubicCentimeter
        { get; set; }

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("CarColor", this.Color);
            info.AddValue("Model", this.ModelName);
            info.AddValue("CC", this.CubicCentimeter);           
        }

        #endregion
    }
}

In the above code we have a special constructor and the GetObjectData method needed to implement custom serialization. GetObjectData method is called when a Car object is serialized and the special constructor is executed when the de-serialization of the Car object happens. Also if you notice, inside, GetObjectData method we are changing the property names, “Color” is changed to “CarColor”, “ModelName” is changed to “Model” and “CubicCentimeter” to CC. These are simple e.g. where we are taking control of serialization. Similar to this you can take control based on different scenarios. If you notice we have not included the “Price” in the serialization and deserialization process i.e. in GetObjectData and special constructor respectively.

Isn’t it so simple to implement custom serialization. Now lets see how to use the StreamingContext object in serialization and deserialization. “StreamingContext” has only two properties which can be of interest, they are “Context” and “State”. Context property can hold any type of object as the underlining type is an “System.Object” class. Context property can be used when you expect some sort of object to come from the caller when serialization is happening. State property tells us from which source the serialization request has been raised. Lets understand with an e.g.

void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
      info.AddValue("CarColor", this.Color);
      info.AddValue("Model", this.ModelName);
      info.AddValue("CC", this.CubicCentimeter);
      //If the request comes from other sources then retrieve the price from the HashTable in the "Context" 
      // property of StreamingContext class.
      if (context.State == StreamingContextStates.Other)
      {
          info.AddValue("Price", ((System.Collections.Hashtable)context.Context)["Ferari Mondeno"].ToString());
      }
          
}

In the above code I have pasted the modified “GetObjectData” method as the other structure of the Car class is same. What we have done in the method is we have added a checking to check whether the serialization request is coming from other sources, if it is then get the price value from the “Context” property of the StreamingContext object. If you see the code I am casting the object to Hashtable and retrieving the price by passing “Ferari Mondeno” string as key. Lets see how the serialization code for the above implementation should be called.

//Create a Hashtable object and add the necessary data.
System.Collections.Hashtable ht = new System.Collections.Hashtable();
ht.Add("Ferari Mondeno", 324324);
ht.Add("Lamborgini", 56677);
//Create StreamingContext instance by passing the Hashtable
//as one of the arguments. Also we are setting the
//StreaminContextStates as Other.
StreamingContext sc = new StreamingContext(StreamingContextStates.Other, ht);
//Pass the StreamingContext instance as one of the parameters
//of the binary formatter class.
BinaryFormatter bf = new BinaryFormatter(null, sc);
using (System.IO.FileStream fs = new System.IO.FileStream("Serialized.txt", System.IO.FileMode.Create))
{
    Car car = new Car { ModelName = "Ferari Mondeno", Color = "Ferari Red", CubicCentimeter = 23584.33, Price = 234656 };
    //bf.Serialize(Console.OpenStandardOutput(), car);
    bf.Serialize(fs, car);
}

In the above code you can see that we are first creating a Hashtable with the necessary data. Once that is done we are creating a StreamingContext instance by passing the Hashtable instance and setting the “StreamingConstextstate as “Other”. After this we are passing the StreamingContext instance as one of the arguments to the “BinaryFormatter” class’ constructor. As you would have noticed we are passing Hashtable instance into the “Context” property of the StreamingContext object. Using the Hashtable we are retrieving the price in “GetObjectData” method.

Now lets see how to deserialize object by making use of the StreamingContext instance. Based on the above changes we need to first change the constructor. Below is the constructor code.

public Car(SerializationInfo info, StreamingContext context)
{
    this.Color = info.GetString("CarColor");
    this.CubicCentimeter = info.GetDouble("CC");
    this.ModelName = info.GetValue("Model", typeof(string)).ToString();
    //Checking whether the serialization request is
    //coming from file or from other sources.
    if (context.State == StreamingContextStates.File || context.State == StreamingContextStates.Other)
    {
        this.Price = int.Parse(((System.Collections.Hashtable)context.Context)["Ferari Mondeno"].ToString());
    }
}

In the above code we have just added a if checking to check whether the request is coming from a file or from other sources, If so read the price value from the StreamingContext instance’ Context property. The “Context” property has a Hashatable having prices.

Now lets see the deserialization code for the above.

using (System.IO.FileStream fs = new System.IO.FileStream("Serialized.txt", System.IO.FileMode.Open))
{
    //Create a Hashtable object and add the necessary data.
    System.Collections.Hashtable ht = new System.Collections.Hashtable();
    ht.Add("Ferari Mondeno", 324324);
    ht.Add("Lamborgini", 56677);
    //Create StreamingContext instance by passing the Hashtable
    //as one of the arguments. Also we are setting the
    //StreaminContextStates as Other.
    StreamingContext sc = new StreamingContext(StreamingContextStates.File, ht);
    //Pass the StreamingContext instance as one of the parameters
    //of the binary formatter class.
    BinaryFormatter bf = new BinaryFormatter(null, sc);
    Car deserializedCar = (Car)bf.Deserialize(fs);
    string nl = Environment.NewLine;
    Console.WriteLine(nl + "Model name: {0}, " + nl + "envi Color: {1}, " + nl + "Cubic centimeter: {2}, " + nl + "Price: {3}",
                        deserializedCar.ModelName, deserializedCar.Color, deserializedCar.CubicCentimeter, deserializedCar.Price);
}

There is nothing much to explain about the above code. Its pretty much straight forward and is similar to  the code where we have serialized the Car class. That’ it about custom serialization using ISerializable interface. One very important point which I would like to reiterate again is that the “GetObjectData” and the special constructor will be executed only for binary serialization. For XML and SOAP serialization “GetObjectData” and the special constructor will not be executed. To implement custom serialization in XML and SOAP serialization you have to implement IXmlSerializable interface. We will have a look at IXmlSerializable interface implementation in my next blog. Till then try to know more.

Sandeep

Friday, December 11, 2009

Showing image when validation fails using validation control

As they say .NET is a big ocean and each day you come across something new. Even after working for six years on .NET every other day I learn something new. One such experience I would like to share with this blog. In this blog we will see how to show an image when there is a validation error.

Anyone who is a ASP.NET developer would have used validation control at some point or the other. So with this blog I would like to show a small technique whereby you can show an image next to a control whenever a validation fails using a validation control. The great thing about this approach is that, it is in-built into all the validation controls and to do this one need not write any server side code or client side code. Just placing an image tag in the “ErrorMessage” property of the validation control will do. Lets see the code.

Required Numeric:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1"            ErrorMessage='<img src=images/error.gif />' Display="Dynamic"></asp:RequiredFieldValidator>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CausesValidation="true" CommandName="Edit" />
<asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="" CausesValidation="False"
            OnClick="btnCancel_Click" />

If you see the above code I have placed a html image tag in the “ErrorMessage” property of the required field validator control. So when you click the submit button without entering any value in “TextBox1” an error image will pop next to the textbox. The screenshot is shown below.

image

In the above image you can see an image, adjacent to the textbox, which was assigned to the “ErrorMessage” property of the validation control. In the above screenshot one thing which is missing is the description about the error. Wouldn’t it be nice to have a description about the error alongside the image? To achieve just that just place the error message before the html image tag as shown below.

<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1"           ErrorMessage="Required.<img src=images/imagesCAJD7BX6.jpg />" Display="Dynamic"></asp:RequiredFieldValidator>

From the above you can notice that we have inserted “Required.” text before the image tag. The output of this is pasted below.

image

Now we have a message alongside the image which gives as the detail of what went wrong. Now all this is fine, but some others would like to make use of the validation summary and show the error messages in the validation summary and error images along side the controls. Hmm, is that tricky? Not at all, its very easy. Lets see how?

Error image along with validation summary control

To show error image alongside the control and validation message in validation summary you have to make some small adjustments in the above code. First thing, obviously, is to insert a validation summary control. Next, Place the image tag in between the starting and ending tags of the validation control. I know you will be little confused, lets clear your confusion with some code. Here is what you need to do.

<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1"            ErrorMessage="Required." Display="Dynamic"><img src=images/imagesCAJD7BX6.jpg /></asp:RequiredFieldValidator>

In the above code I have purposefully not included the validation summary control. You can find the whole code at the end of the blog. If you notice, we have placed the image tag in between the starting and ending tag of the required field validator. Also we have the error message in the “ErrorMessage” property. The output of the above code is pasted below.

image

One thing to note here is that you have to set the “Display” property of the validation control to “Dynamic”.  If you set the “Display” property to “None”, which we usually use with validation summary control, then the image will not be displayed. So its very important to set the “Display” property to “Dynamic'” for this to work. The whole code along with the validation summary is pasted below.

<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
Required Numeric:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="TextBox1"            ErrorMessage="Required." Display="Dynamic"><img src=images/imagesCAJD7BX6.jpg /></asp:RequiredFieldValidator>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CausesValidation="true" CommandName="Edit" />
<asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="" CausesValidation="False"            OnClick="btnCancel_Click" />

Try to learn more

Sandeep

Weird, CausesValidation not working.

Recently I faced a weird situation where I had some validation controls, a cancel and submit buttons in a page . Submit button would validate the page controls for errors and cancel button would just postback and execute some code on the server without validating the page. The weird thing was once submit button is clicked and if there are any validation errors in the page and then one clicks the cancel button it won’t clear postback. If the user clicks the cancel button for the second time it would trigger postback. This happened even after setting the “CausesValidation” property of the cancel button to “false'”. The cancel button code is pasted below.

<asp:Button ID="btnRemove" CssClass="buttonEnabled" CommandName="Delete" runat="server"                       meta:resourcekey="btnRemove" CausesValidation="false" />

One thing to note here is that the cancel button was inside a ListView control’ ItemTemplate section. So on click of the button  postback should happen and in the server some logic would be carried. The cancel would not work only when the user clicks the submit button and if there are any error and the user wishes to cancel the action then the cancel button would not post back. Only when the user clicks the cancel button for the second time, it would post back. If the user clicks the cancel button immediately after clicking the submit button and there are any validation errors displayed through the validation controls then the cancel button would not postback. This was weird. The solution was also simple. I need to set “Page_ValidationActive” javascript variable to false on the “OnClientClick” property of the cancel button. The modified cancel button HTML is pasted below.

<asp:Button ID="btnRemove" CssClass="buttonEnabled" CommandName="Delete" runat="server"                       meta:resourcekey="btnRemove" CausesValidation="false" OnClientClick="javascript:Page_ValidationActive = false;" />

Setting the “Page_ValidationActive” to false disables all the validations in the page. So please do keep this in mind. Anyway this is what I wanted and my problem was solved.

Try to know more.

Sandeep