Monday, June 25, 2007

Viewstate Cleared..!!

One of the most interesting features of ASP.NET 2.0 is the open way it allows the programmer to manipulate a control's viewstate. The viewstate should be the first choice to save data to access across postbacks


If the information is to be shared across different controls, it can be placed in the viewstate of the page, if it is to be accessed within the scope of a single control, then it can be placed within the viewstate of the control. The type of info one can save here may be simple data types or even complex user defined objects.



Storing Simple Data Types in the ViewState
Like most types of state management in ASP.NET, view state relies on a dictionary collection, where each item is indexed with a unique string name. For example, consider this code:

ViewState["ViewStateVariableName"] = 1;

This places the value 1 (or rather, an integer that contains the value 1) into the ViewState collection and gives it the descriptive name ViewStateVariable. If there is currently no item with the name ViewStateVariable, a new item will be added automatically. If there is already an item indexed under this name, it will be replaced.

You can access this variable anywhere within the page/control where the viewstate variable has been added. When retrieving a value, you use the key name.

int number = (int) ViewState["ViewStateVariable"];

You also need to cast the retrieved value to the appropriate data type. This is because the ViewState collection stores all items as generic objects which also give you the flexibility to store any type of basic data types in it. In fact, you can even store your custom objects in the view state.


Storing Objects in View State



You can store your own objects in view state just as easily as you store numeric and string types. However, to store an item in view state, ASP.NET must be able to convert it into a stream of bytes so that it can be added to the hidden input field in the page. This process is called serialization. If your objects aren't serializable (and by default they aren't), you'll receive an error message when you attempt to place them in view state.

To make your objects serializable, all you need to do is to add the 'Serializable' attribute before your class declaration. For example, here's an exceedingly simple Student class:

[Serializable]
public class Student
{
public string firstName;
public string lastName;

public Student(string fName, string lName)
{
firstName = fName;
lastName = lName;
}
}

Because the Student class is marked as serializable, it can be stored in view state:

// Storing a student in view state.
Student stud = new Student("John", "Doe");
ViewState["CurrentStudent"] = stud;

Remember, when using custom objects, you'll need to cast your data when you retrieve it from view state.

// Retrieve a student from view state.
Student stud = (Student) ViewState["CurrentCustomer"];

To be serializable, your classes you must meet these requirements:

• Your class must have the Serializable attribute.

• Any classes it derives from must have the Serializable attribute.

• All the private variables of the class must be serializable data types. Any nonserializable data type must be decorated with the NonSerialized attribute (which means it is simply ignored during the serialization process).

Example 1: Making a PostBackCounter
Let's say you want to keep track of the number of times a page is posted back to the server. This info can be kept inside the session, or even inside a hidden field control in the page. However, keeping it in the session forces you to clear up or reset this variable every time the user moves to a new page. Keeping it in a hidden filed or an invisible text box on the page might clutter your .aspx file with controls that can be changed by malicious users. Using the view state in this scenario is an elegant way to persist info across postbacks that will be accessible only to the programmer and the code.

Suppose our .aspx page control contains one button and one label inside the form.




On the code behind file we have the page load event and the event handler for the click event of button1.

protected void Page_Load(object sender, System.EventArgs e)
{
//First we check if the page is loaded for the first time,
if (!IsPostBack)
{
ViewState["PostBackCounter"] = 0;
}
//Now, we assign the variable value in the text box
int counter = (int)ViewState["PostBackCounter"];
Label1.Text = counter.ToString();
}

Now, the label will always display the post back count!

Let's say we increment the post back count only when our button is clicked. In this case, we need to write some code on the button click event handler.

protected void Button1_Click(object sender, System.EventArgs e)
{
int oldCount = (int)ViewState["PostBackCounter"];
int newCount = oldCount + 1;
//First, we assign this new value to the label
Label1.Text = newCount.ToString();
//Secondly, we replace the old value of the view state so that the new value is read the next //time
ViewState["PostBackCounter"] = newCount;
}

Now, every time the user will click on this button, the text will show an incremented number!

Example 2: Tracking Dynamic Controls
One of the main challenges with working with dynamically added controls is that these controls must be programmatically added on each postback. That is, you can't just load these controls on the first page load, and then not reload them on subsequent postbacks. Failure to explicitly add the controls on each postback will cause the controls to literally disappear on postbacks.

Let's build on our previous example. Only this time, instead of an integer, we'll keep a List in the view state. Instead of one label, we are going to dynamically add a new Label every time the button is clicked. And, the value of the new label will be given by the user inside a text box.

So, out .aspx page will look like this:





The placeholder will act as the container on which we shall load out Labels.

On the code behind cs file, we have page load event, which initializes the controls:

protected void Page_Load(object sender, System.EventArgs e)
{
//First we check if the page is loaded for the first time,
if(!IsPostBack)
{
List temp = new List();
ViewState["allTextData"] = temp;
}
List myTextData = (List) ViewState["allTextData"];
//Loading the dynamic controls
foreach(string data in myTextData)
{
AddDynamicLabel (data);
}
}

The AddDynamicLabel() function dynamically adds a label in the placeholder.

private void AddDynamicLabel (string data)
{
//Making the new label and giving it the appropriate value
Label l = new Label();
l.Text = data + "
";
//Adding the label into the page
PlaceHolder1.Controls.Add(l);
}

And finally we have the Button1 click event handler, where we add a brand new label in our placeholder.

protected void Button1_Click(object sender, System.EventArgs e) { //Adding the new text as a label inside the placeholder AddDynamicLabel (TextBox1.Text); //Adding the new text inside the viewstate List, for retreival on subsequent postbacks List myTextData = (List) ViewState["allTextData"]; myTextData.Add(TextBox1.Text); ViewState["allTextData"] = myTextData; }

When to use the ViewState
View state is a good way to store data in between postbacks, because it doesn't take up any memory on the server side and it doesn't impose any arbitrary usage limits (such as a timeout). So, what might force you to abandon view state for another type of state management? Here are three possible reasons:

• You need to store mission-critical data that the user cannot be allowed to tamper with. (An ingenious user could modify the view state information in a postback request.) In this case, consider session state.

• You need to store information that will be used by multiple pages. In this case, consider session state, cookies, or the query string.

• You need to store an extremely large amount of information, and you don't want to slow down page transmission times. In this case, consider using a database, or possibly session state.



Remember, any data that you put in the view state will be part of the data stream that goes to the client and then comes back to the server, so be very careful while putting large chunks of data in the ViewState!

Wednesday, April 18, 2007

Play & Enjoy SQL Joins

The SQL JOIN clause is used whenever we have to select data from 2 or more tables.

To be able to use SQL JOIN clause to extract data from 2 (or more) tables, we need a relationship between certain columns in these tables.

We are going to illustrate our SQL JOIN example with the following 2 tables:

Customers:

CustomerID FirstName LastName Email DOB Phone
1 John Smith John.Smith@yahoo.com 2/4/1968 626 222-2222
2 Steven Goldfish goldfish@fishhere.net 4/4/1974 323 455-4545
3 Paula Brown pb@herowndomain.org 5/24/1978 416 323-3232
4 James Smith jim@supergig.co.uk 20/10/1980 416 323-8888


Sales:

CustomerID Date SaleAmount
2 5/6/2004 $100.22
1 5/7/2004 $99.95
3 5/7/2004 $122.95
3 5/13/2004 $100.00
4 5/22/2004 $555.55


As you can see those 2 tables have common field called CustomerID and thanks to that we can extract information from both tables by matching their CustomerID columns.

Consider the following SQL statement:


SELECT Customers.FirstName, Customers.LastName, SUM(Sales.SaleAmount) AS SalesPerCustomer
FROM Customers, Sales
WHERE Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.FirstName, Customers.LastName




The SQL expression above will select all distinct customers (their first and last names) and the total respective amount of dollars they have spent.
The SQL JOIN condition has been specified after the SQL WHERE clause and says that the 2 tables have to be matched by their respective CustomerID columns.

Here is the result of this SQL statement:

FirstName LastName SalesPerCustomers
John Smith $99.95
Steven Goldfish $100.22
Paula Brown $222.95
James Smith $555.55


The SQL statement above can be re-written using the SQL JOIN clause like this:


SELECT Customers.FirstName, Customers.LastName, SUM(Sales.SaleAmount) AS SalesPerCustomer
FROM Customers JOIN Sales
ON Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.FirstName, Customers.LastName




There are 2 types of SQL JOINS – INNER JOINS and OUTER JOINS. If you don't put INNER or OUTER keywords in front of the SQL JOIN keyword, then INNER JOIN is used. In short "INNER JOIN" = "JOIN" (note that different databases have different syntax for their JOIN clauses).

The INNER JOIN will select all rows from both tables as long as there is a match between the columns we are matching on. In case we have a customer in the Customers table, which still hasn't made any orders (there are no entries for this customer in the Sales table), this customer will not be listed in the result of our SQL query above.

If the Sales table has the following rows:

CustomerID Date SaleAmount
2 5/6/2004 $100.22
1 5/6/2004 $99.95


And we use the same SQL JOIN statement from above:


SELECT Customers.FirstName, Customers.LastName, SUM(Sales.SaleAmount) AS SalesPerCustomer
FROM Customers JOIN Sales
ON Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.FirstName, Customers.LastName




We'll get the following result:

FirstName LastName SalesPerCustomers
John Smith $99.95
Steven Goldfish $100.22


Even though Paula and James are listed as customers in the Customers table they won't be displayed because they haven't purchased anything yet.

But what if you want to display all the customers and their sales, no matter if they have ordered something or not? We’ll do that with the help of SQL OUTER JOIN clause.

The second type of SQL JOIN is called SQL OUTER JOIN and it has 2 sub-types called LEFT OUTER JOIN and RIGHT OUTER JOIN.

The LEFT OUTER JOIN or simply LEFT JOIN (you can omit the OUTER keyword in most databases), selects all the rows from the first table listed after the FROM clause, no matter if they have matches in the second table.

If we slightly modify our last SQL statement to:


SELECT Customers.FirstName, Customers.LastName, SUM(Sales.SaleAmount) AS SalesPerCustomer
FROM Customers LEFT JOIN Sales
ON Customers.CustomerID = Sales.CustomerID
GROUP BY Customers.FirstName, Customers.LastName




and the Sales table still has the following rows:

CustomerID Date SaleAmount
2 5/6/2004 $100.22
1 5/6/2004 $99.95


The result will be the following:

FirstName LastName SalesPerCustomers
John Smith $99.95
Steven Goldfish $100.22
Paula Brown NULL
James Smith NULL


As you can see we have selected everything from the Customers (first table). For all rows from Customers, which don’t have a match in the Sales (second table), the SalesPerCustomer column has amount NULL (NULL means a column contains nothing).

The RIGHT OUTER JOIN or just RIGHT JOIN behaves exactly as SQL LEFT JOIN, except that it returns all rows from the second table (the right table in our SQL JOIN statement).

Monday, February 26, 2007

Response.Redirect Vs Server.Transfer

Response.Redirect will instruct browser to call a particular webpage. Then Request comes to browser and brower requests the the new page. This will increase one request and one response between the client and server.

· Resonse.redirect can be used both for aspx and html pages.But server.transfer is only used for aspx pages it will not work for html pages.

· Response.redirect supports only get method to send variables form one page to another page we need to append the data in query string

· But in server.transfer if we selected the second attribute to "TRUE" then it will post all the variable using the post method.

· Response.Redirect can be used to redirect to external web sites where as the Server.Transfer can be used only to transfer to other pages of the same web site.

· response.redirect has no support for encapsulating the code.whereas with a server.transfer we can overcome these overheads because server.transfer gets teh page from the server itself without needing a rountrip to the client.


· Response.redirect updates the url with newpage name in browser address bar. But Server.Transfer keeps oldpage url in address bar.