May 30, 2009

Read n Write Cookie

A cookie can be used to store user data on the client side. Data may contain state information and user preferences. The cookie is stored as a text file on the client's system if the cookie is persistent or in browser's session's memory if the cookie is temporary. Using cookies is a handy way to store data on the client but the user, at the same time, can delete a cookie or disable cookie from the browser settings. A cookie is a better way to hold data, compared to hidden fields and query string, since the data can be stored on the client even if the client starts viewing a different page.

In Asp.Net application, a cookie can be created by adding a value to the Response.Cookies.HttpCookieCollection. Once a cookie is added, the value of the cookie can be read by using the Request.Cookies property.

In the following example, a cookie is added in the Page_Load method by adding a value to the Respose.Cookies collection and the value is read on a button click.

protected void Page_Load(object sender, EventArgs e)
    {
        Response.Cookies["name"].Value = "shahed"; //value of cookie "name"
        Response.Cookies["name"].Domain = "localhost"; // domain for the cookie
        Response.Cookies["name"].Expires = DateTime.Now.AddDays(1);//expire date
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        if (Request.Cookies["name"] != null)//check if cookie exist
        {
            Response.Write("Cookie name:\t" + Request.Cookies["name"].Name + "<br/>");//name of cookie
            Response.Write("Cookie Value:\t " + Request.Cookies["name"].Value + "<br/>");//value of cookie
            Response.Write("Cookie Expires:\t" + Request.Cookies["name"].Expires + "<br/>");//expiry date of cookie
            Response.Write("Cookie Domain:\t" + Request.Cookies["name"].Domain + "<br/>");//domain of cookie
        }       
    }


In Page_Load method, a cookie with name "name" is added. The expiry date is set to be one day and it is scoped for "localhost" domain. There is a button on the main which when clicked, checks if the cookie exists, and if so writes the properties of the cookie.

May 28, 2009

Find Properties of Child Controls

At times, we can have a lot of the same type of controls (like CheckBox, RadioButton) and we may need to find various values for the control like id, text and whether the controls have been checked or not. In this scenario, we can write lot of the same code only to find the required values like below.

Declare a RadioButton in .aspx page,
<asp:RadioButton ID="RadioButton1" runat="server" Text="1" />

and in code behind,
find the properties like:
string id = RadioButton1.UniqueID;
string text = RedioButton1.Text;

and so on.

This code is quite ok when we have only a few RadioButtons on the page. But, in case, we have a large number of RadioButtons, then this definitely not an efficient way to achieve this. Here, I will create a page with 10 RadioButtons and then display the information on the RadioButtons on a Button click.

My page looks like below:

<form id="form1" runat="server">
<asp:Panel ID="Panel1" runat="server">
<asp:RadioButton ID="RadioButton1" runat="server" Text="1" /><br />
<asp:RadioButton ID="RadioButton2" runat="server" Text="2" /><br />
<asp:RadioButton ID="RadioButton3" runat="server" Text="3" /><br />
<asp:RadioButton ID="RadioButton4" runat="server" Text="4" /><br />
<asp:RadioButton ID="RadioButton5" runat="server" Text="5" /><br />
<asp:RadioButton ID="RadioButton6" runat="server" Text="6" /><br />
<asp:RadioButton ID="RadioButton7" runat="server" Text="7" /><br />
<asp:RadioButton ID="RadioButton8" runat="server" Text="8" /><br />
<asp:RadioButton ID="RadioButton9" runat="server" Text="9" /><br />
<asp:RadioButton ID="RadioButton10" runat="server" Text="10" /><br />
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />

</asp:Panel>
</form>


In the body section of the page, there is a form within which there is a Panel and 10 RadioButtons and 1 Button are inside the Panel. The Button has a onclick handler that will display the information of the RadioButtons.

The Button1_Click() method looks like below:

protected void Button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < Panel1.Controls.Count; i++)
{
if (Panel1.Controls[i].GetType() == typeof(RadioButton))
{
RadioButton rb = new RadioButton();

rb = (RadioButton)Panel1.Controls[i];
Response.Write("\tid: " + rb.UniqueID);
Response.Write("\tText:" + rb.Text);
Response.Write("\tChecked:" + rb.Checked);
Response.Write("<br/>");
}
}
}


Here, there is a for loop that counts the number of child controls for the Panel.
for (int i = 0; i < Panel1.Controls.Count; i++)

Within the for loop, there is a if statement. The statement checks if the Child control of the Panel of type RadioButton or not.
if (Panel1.Controls[i].GetType() == typeof(RadioButton))

If the control is of type RadioButton then it assigns a RadioButton rb to the child control.
RadioButton rb = new RadioButton();

rb = (RadioButton)Panel1.Controls[i];


Then, the code writes the ID, Text and the Checked property of the RadioButton control to the page.
Response.Write("\tid: " + rb.UniqueID);

Response.Write("\tText:" + rb.Text);

Response.Write("\tChecked:" + rb.Checked);


Therefore, using this method, we can easily identify the type of a child control and find its properties.


Enable Trace in Web Application

To enable tracing in a web application, update the web.config file to have the trace element.


Here, I have enabled attribute to be "true". The implies that tracing is enabled for the application.

Having requestLimit to 10 means that a maximum of 10 records will be saved in the tracing.

Setting mostRecent attribute to "true" implies only the recent records will be displayed and after reaching the requestLimit, the older records will be overwritten.

Setting localOnly to "false" means the tracing feature can be viewed by anyone. Ideally, this should be set to "true" meaning tracing records can only be viewed internally by developers.

Setting traceMode to "SortByCategory" means the records will be sorted by category. The other option is to "SortByTime".

Setting pageOutput to false means tracing results will not be displayed on page but in a different page /root/Trace.axd .

Enabling tracing from the web.config files enables tracing for the whole website. Tracing can also be turned on or off for a page. To enable tracing for a page update the Trace attribute of page
directive.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="Default" Trace="true" %>

The settings is Page directive will take precedence over the web.config settings.

May 24, 2009

Response.Redirect in try catch finally block

We all have likely used the Redirect() method of the Response object. Basically, the Response objects redirects the user to view a different URL and a page from the server end. Few days back, I used the Redirect() method from within a try-catch-finally block and noticed unexpected behavior.

I first created a try-catch block with a Response.Redirect("page2.aspx") and then ran the method like below.

protected void Page_Load(object sender, EventArgs e)
{
string status = string.Empty;
try
{
status = "try";
Response.Redirect("page2.aspx?status"+status);
}
catch (Exception ex)
{
status="catch";
Response.Redirect("page2.aspx?status=" + status);
}
finally
{
status="finally";
Response.Redirect("page2.aspx?status="+status);
}

}

The page redirected to page2.aspx?status=finally. The try section got processed first and set the value of status variable to "try" and "throw" an exception System.Threading.ThreadAbortException. This exception is caused since the page is trying to kill the current thread.

The catch section is then processed and set the status variable to "catch". Then Response.Redirect("page2.aspx?status=" + status); in the catch section is then processed which instead of redirecting the page, transfers the control to the finally block. In the finally block, the status variable is set the "finally" and the page is then redirected to page2.aspx?status=finally. Commenting out the finally block shows an exception occurred in the try block.

To avoid having a System.Threading.ThreadAbortException caused by a Response.Redirect() in the try block, set the endResponse parameter to false.

Response.Redirect("page2.aspx?status=" + status, false);

In the next example, I changed the try block to throw an exception instead of doing a Response.Redirect() like below.
protected void Page_Load(object sender, EventArgs e)
{
string status = string.Empty;
try
{
status = "try";
throw new Exception();
//Response.Redirect("page2.aspx?status="+status, false);
}
catch (Exception ex)
{
status="catch";
Response.Redirect("page2.aspx?status=" + status, true);
}
finally
{
status="finally";
//Response.Redirect("page2.aspx?status="+status);
}

}

When I started debugging the page, a new page opened in the browser with url page2.aspx?status=catch. I thought the status property will get overridden in the finally block but the page redirected to page with query string status=catch. What happened here is an exception was thrown in the try block which transferred the control to catch section. When the catch section was processed, status was changed to "catch" and the redirected url for Response.Redirect was constructed. The url was then page2.aspx?status=catch. Instead of redirecting the page then, the control was transferred to finally block. The status variable was changed to "finally". The control was then transferred to the catch block's Response.Redirect. The url was already set to have query string status=catch. So, in the browser the url page2.aspx?status=catch was shown.

If I uncomment the Response.Redirect in the finally block, the url page2.aspx?status=finally will be shown in the browser.

May 17, 2009

The Asp.Net TextBox control contains two properties "Enabled" and "ReadOnly" that are kind of similar. Both the controls can be used to prevent a user from entering a value. The properties can be set in a TextBox control as follows.

<asp:TextBox ID="TextBox1" runat="server" Text="xyz" Enabled="false"></asp:TextBox>

<asp:TextBox ID="TextBox2" runat="server" Text="abc" ReadOnly="true"></asp:TextBox>

When the Enabled property is set to false, the disabled attribute of the html output is set to disabled. When the ReadOnly property is set to true, the ReadOnly property of the html output is set to ReadOnly.
<input name="TextBox1" type="text" value="xyz" id="TextBox1" disabled="disabled" />
<input name="TextBox2" type="text" value="abc" readonly="readonly" id="TextBox2" />
Both the properties, Enabled and ReadOnly prevents the user from the entering content on the text boxes, but the values can be updated by using javascript or from code-behind. This can be done by setting the TextBox's Text property.

When the values are updated programmatically, when a postback occurs, the value in a disabled TextBox is retained. That is, the control's Text property is posted back to the server. If the value is updated using javascript, the value is not posted back to the server during a postback. The value retained in the ViewState is the last value before the control was disabled or set from the server side.

For a readonly textbox, the value is posted back to the server regardless of whether the Text property is updated from client or server side. However, asp.net does not process a readonly textbox. This can be demonstrated by using setting a required field validation on the readonly control. While using a required field validator, the controls value is set to "".

Code used to demonstrate the above is below.
aspx page:

<head runat="server">

<title>Untitled Page</title>

<script type="text/javascript" language="javascript">

function testClick()
{

//window.alert("text");

document.getElementById("TextBox1").value = "text2";

document.getElementById("TextBox2").value = "text2";

document.getElementById("TextBox5").value = "text2";

document.getElementById("TextBox1").disabled = true;

document.getElementById("TextBox2").readonly = true;

}

</script> </head>

<body>

<form id="form1" runat="server">

<div>

Enabled="false" : <asp:TextBox ID="TextBox1" runat="server" Text="xyz" ></asp:TextBox><br
/>

ReadOnly="true" : <asp:TextBox ID="TextBox2" runat="server" Text="abc" ></asp:TextBox><br />

<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /><br />

<asp:ButtonID="Button2"runat="server" Text="Button2" /><br />

<asp:Button ID="Button3" runat="server" Text="Button3" onclick="Button3_Click" /><br/>

<asp:LabelID="Label1" runat="server"Text="Label" EnableViewState="false"></asp:Label>

<input id="Button4" type="button" value="button" onclick="testClick()" />

<asp:TextBoxID="TextBox5" runat="server" ReadOnly="true"></asp:TextBox>

<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" errorMessage="RequiredFieldValidator" ControlToValidate="TextBox5"></asp:RequiredFieldValidator>

</div> </form> </body>

Code behind:

protected void Button1_Click(object sender, EventArgs e)
{

TextBox1.Text =
"text1";
TextBox2.Text =
"text1";
}

protected void Button3_Click(object sender, EventArgs e)
{

Label1.Text = TextBox1.Text +
"<br/>" +
TextBox2.Text +
"<br/>" +
TextBox5.Text ;

}

May 14, 2009

Store data in HiddenField

Data can be stored in a page using asp.net HiddenField control. The HiddenField does not show any output to the page but can be viewed from the page source of the page. Also, one of the limitations of the HiddenField is that only string data can be stored in the page.

The HiddenField control is declared as follows.

<asp:HiddenField ID="HiddenField1" runat="server" />

String values can be added to the HiddenField using the value attribute.

<asp:HiddenField ID="HiddenField1" runat="server" Value="some data" />

The page source shows how the HiddenField is generated.

<input type="hidden" name="HiddenField1" id="HiddenField1" value="some data" />
The HiddenField control can be accessed from code-behind of the page using it's ID attribute like any other asp.net control. To assign values to thecontrol, use the following code,

HiddenField1.Value = "some new data";

To find the value of the control, use the following code,

string data = HiddenField1.Value;

May 7, 2009

Pass Values Using Query Strings

Query string is a common way to transfer values from one page to another or to store it in the page URL. The query string values are stored in the form of strings and are appended to the URL. A typical query string will http://shahed-kazi.blogspot.com/index.html?country=australia .

The browser understands the filename to be index.html and anything characters after the "?" as the query string. In this example, there is one query string with key country and value australia. Multiple values can be added to the URL like http://shahed-kazi.blogspot.com/index.html?firstname=shahed&city=sydney .
Here, there are 2 query strings country with value australia and city with value sydney. The query string value are separated with a "&".

One of the disadvantage of using query strings is that the values and the variable names are visible to the user. Also, a user can easily change the value of the variables and construct a different url. Therefore, sensitive information cannot be passed on page to another using this method.

Another disadvantage is that there is a limitation on the number of characters in a URL. The limit is 2083 characters. Therefore, large amount of data cannot be passed using query strings technique.

Sensitive information should not be stored in the query strings. For example, if we run a call in the database based on the data on the query string - a user can easily modify the URL and run a query that will hang the site. Also, if we are updating the data source based on a query string - a user modifying the query string may result in updating the data source with invalid data. That's
why it is important to validate the data.

Now, I will create an example page with 2 TextBox controls, create a URL with the textbox values and display the values in a second page.

First Page:

<form id="form1" runat="server">

<div>

First Name:<asp:TextBox ID="FirstNameTextBox" runat="server"></asp:TextBox><br />

Last Name: <asp:TextBox ID="LastNameTextBox" runat="server"></asp:TextBox><br />

<asp:ButtonID="Button1" runat="server" Text="Continue" onclick="Button1_Click" />

</div>

</form>

In code-behind, Button1 onclick event,

string firstname = FirstNameTextBox.Text;

string lastname = LastNameTextBox.Text;

Response.Redirect("page2.aspx?firstname=" + firstname + "&lastname=" + lastname);

page2.aspx looks like below,

<form id="form1" runat="server">

<div>

First Name : <asp:Label ID="FirstNameLabel" runat="server" Text=""></asp:Label><br
/>

Last Name: <asp:Label ID="LastNameLabel" runat="server" Text=""></asp:Label>

</div>

</form>

In this page, the label controls will be populated with values from the query string.

In Page_Load method in code-behind page,

protected void Page_Load(object sender, EventArgs e)

{

FirstNameLabel.Text = Server.HtmlEncode(Request.QueryString["firstname"]);

LastNameLabel.Text = Server.HtmlEncode(Request.QueryString["lastname"]);

}

The page will now show the values in the Label controls as in the query strings.

Also, note that I have encoded the string using Server.HtmlEncode. This method will automatically convert all the html characters into not html characters.

To use special characters like "&" in the query string, use the UrlEncode method of the Server class. For example, use the url like

string url = "http://shahed-kazi.blogspot.com/2009/05/pass-values-using-query-strings.html?id=" + Server.UrlEncode("hello & world");

When viewed in the browser, the URL will be automatically converted to http://shahed-kazi.blogspot.com/2009/05/pass-values-using-query-strings.html?id=hello+%26+world

May 6, 2009

Store Values in ViewState

ASP.NET has a built in mechanism for storing values of controls known as ViewState. The ViewState property provides a key-value object for storing values between multiple requests of the same page. ASP.NET saves the state of the page and controls as a hashed string in the page as a hidden variable, ViewState.

When a page is run, the ViewState property can be seen from the source code of the page.

<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" 
value
="/wEWAgL3ku32BwLs0bLrBqcPjj4o1kvxlT2D91sy/YSkJDTh" />

Custom data can be stored in the ViewState property. If a value has to be stored for a user in page, ViewState is an easy way to achieve this. Please note that ViewState property is only accessible from the page only. If the user visits a different page, the ViewState property will be lost.

Let's create a string containing a date and store it in the ViewState.

string date = DateTime.Now.ToString();

ViewState["date"] = date;

An alternative way of achieving this would be to

ViewState.Add("date", date);

The values stored in the ViewState can also be retrieved as follows.

if ((string)ViewState["date"] != null)

{

string date2 = (string)ViewState["date"];

}

Here, I am checking there a ViewState property named "date". If so, assign the value to string date2.

In ViewState, objects can also be stored/ For example, we can store a DateTime object like below

ViewState.Add("date3", DateTime.Now);

and retrieve the object like

DateTime date3 = (DateTime)ViewState["date3"];


May 5, 2009

Create User Control from Web Page

To create a user control from a aspx web page, create a web page first.

default2.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server"><title>Untitled Page</title></head>

<body>

<form id="form1" runat="server">

<div> </div>

</form> </body> </html>

code behind

public partial class Default2 : System.Web.UI.Page

{
protected
void Page_Load(object sender, EventArgs e)
{ //page load event }
}

Then,

  • Remove the html, head, body and form tags.
  • Change the @Page directive in default2.aspx page to @Control.
  • Change the filename to default2.ascx.
  • In code-behind, change the Inherits tag to System.Web.UI.UserControl.

The resultant page (user control) will like below.

default2.aspx,

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Default2.ascx.cs" Inherits="Default2" >

code-behind,

public partial class Default2 : System.Web.UI.UserControl
{

protected
void Page_Load(object sender, EventArgs e)
{
//page load event}
}

May 4, 2009

Dynamic Columns in GridView

From time to time, it may happen that we already have a DataTable object but it contains more fields that we want the user to view or maybe we want to combine 2 fields and display it to the GridView. In this scenarios, we can still bind the DataTable to the GridView but the fields in the GridView needs to be manually created.

First we create a DataTable object,

DataTable dt = new DataTable();

Then, we create schema to the DataTable. That is, we create dataColumns for the DataTable.

//assign schema to DataTable

dt.Columns.Add("id", typeof(int));

dt.Columns.Add("firstname", typeof(string));

dt.Columns.Add("lastname", typeof(string));

dt.Columns.Add("company", typeof(string));

dt.Columns.Add("is25", typeof(bool));

Now, DataColumns (id of type int, firstname, lastname, company of type string and is25 of type boolean) for the DataTable has been created.

Now, we add some dummy data to the DataTable.

//create rows for the DataTable

dt.Rows.Add(0, "shahed", "kazi", "ABCD", false);

dt.Rows.Add(1, "john", "smith", "XYZ", true);

dt.Rows.Add(2, "anne", "smith", "PQRS", false);

Now, DataRows for the DataTable have been created.

Now, we need to create a GridView and bind the DataTable to the GridView. We want to display the data in 4 columns.

The first column will display a hyperlink to the user data based on the id.
The second column will show first name.
The third column will show the last name.
And the fourth column will display the is25 field.

Now, we need to create a GridView and bind to the dataTable. We will create a method that will create the GridView.

public GridView GetGridView(DataTable dt)

{

GridView gv = new GridView();

gv.AutoGenerateColumns = false;

HyperLinkField hlf = new HyperLinkField();//creating a HyperLinkField

hlf.DataTextField = dt.Columns[0].ToString();

hlf.DataNavigateUrlFields = new string [] { "id" };

hlf.DataNavigateUrlFormatString = "details.aspx?id={0}";

hlf.HeaderText = "Details"; //setting title of column

gv.Columns.Add(hlf);//adding to GridView

BoundField firstnameField = new BoundField();//creating a BoundField

firstnameField.HeaderText = "first name";//setting title of column

firstnameField.DataField = "firstname";

gv.Columns.Add(firstnameField);//adding to GridView

BoundField lastnameField = new BoundField();//creating a BoundField

lastnameField.HeaderText = "last name"; //setting title of column

lastnameField.DataField = "lastname";

gv.Columns.Add(lastnameField);//adding to GridView

CheckBoxField ck =newCheckBoxField();//creating a CheckBoxField

ck.DataField = "is25";

ck.HeaderText = "Is 25?"; //setting title of column

gv.Columns.Add(ck);//adding to GridView

return gv;

}

In this method, we first create a GridView and set the AutoGenerateColumns property to false. Setting AutoGenerateColumns to true will automatically bind the DataTable to the GridView and therefore the GridView will end up having all the columns of the DataTable. Then, we added a HyperLinkField, 2 oundFields and a CheckBoxField and set its properties.

Then, add the GridView to the page. Here, I have created a panel on the page
first and adding the GridView to it.

GridView gv = GetGridView(dt);
gv.DataSource = dt;
gv.DataBind();

Panel1.Controls.Add(gv);

Reference: Shahed Kazi at AspNetify.com