Monday, September 22, 2008

form authetication code in c#

form authetication code:::::
---------------------------------------


protected void Login_Authenticate(object sender, AuthenticateEventArgs e)
{
Config objcon = new Config();
DAL.TextEncryption objencryption = new DAL.TextEncryption();
string strUserName, strPassword;
int intUserID;
try
{
Login.Focus();
strUserName = this.Login.UserName;
strPassword = objencryption.Main(Login.Password, 0);
intUserID = objcon.AuthenticateUser(strUserName, strPassword);
Session["UserID"] = intUserID.ToString();
if (intUserID > 0)
{
e.Authenticated = true;
FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;

tkt = new FormsAuthenticationTicket(1,
this.Login.UserName,
DateTime.Now,
DateTime.Now.AddMinutes(30),
false,//chkPersistCookie.Checked
"Area");

cookiestr = FormsAuthentication.Encrypt(tkt);
ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
//if (chkPersistCookie.Checked)
// ck.Expires = tkt.Expiration;
ck.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(ck);

string strRedirect;
strRedirect = Request["ReturnUrl"];
char[] c ={ '/' };
string[] temp;
if (strRedirect == null)
{
strRedirect=Request.CurrentExecutionFilePath.ToString();

// "/area_devlopment/Admin/Login.aspx"
}

try
{
temp = strRedirect.Split(c);
//if (temp.ToString().Contains("localhost"))
//{
// strRedirect = "/" + temp[1].ToString() + "/" + temp[2].ToString() + "/welcome.aspx";

//}
//else
//{
// strRedirect = "/" + temp[1].ToString() + "/welcome.aspx";

//}
try
{
strRedirect = "~/Admin/Welcome.aspx";
}
catch
{
strRedirect = "~/Admin/Welcome.aspx";

}

}
catch { }
if (strRedirect == null)

strRedirect = "~/Admin/Welcome.aspx";
Response.Redirect(strRedirect, true);
// Response.Redirect("Welcome.aspx", false);
}
else
{
e.Authenticated = false;
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}


how to add cookies::
-----------------------------------------
// Code that runs when a new session is started
///Session["ActiveCountry"] = 66;
int cid=DAL.Country.GetUsaCountryId();
HttpContext.Current.Session["ActiveCountry"] = cid;
#region Get Culture Code

DataSet ds = new DataSet();
ds = DAL.Country.GetAllCountryDetailsById(cid);
if (ds.Tables.Count > 0)
{
DataRow drBasicInfo;
drBasicInfo = ds.Tables[0].Rows[0];
if (drBasicInfo != null)
{

HttpCookie cookie = Request.Cookies["Language"];
if (cookie == null)
{
cookie = new HttpCookie("Language");
}
cookie["LanguCode"] = drBasicInfo["Language"].ToString();

cookie.Expires = DateTime.Now.AddYears(1);
Response.Cookies.Add(cookie);

}
}
#endregion

Sunday, September 21, 2008

Form authentication without ticket

What is authentication? "To establish the authenticity of; prove genuine" (The American Heritage® Dictionary of the English Language). ASP.NET has buildt in authentication support for web page development making it really easy for any web developer to add personalized webpages or password-protect areas.

This tutorial is aimed at people who already have a good understanding of ASP.NET. If you want to learn ASP.NET, I have a beginner tutorial here: Guestbook.NET - a beginner tutorial to ASP.NET

There are three types of autentication in ASP.NET: forms authentication, windows authentication, and Passport authentication.

Windows Authentication - This is provided so that web pages can make use of the local Windows User and Groups.

Passport Authentication - This is Microsoft's initiative for a single authentication point. It is used for such things as Hotmail, MSN and Devhood. Find out more at www.passport.com

Forms Authentication - This is a cookie based authentication system where the username and passport is stored in a text file or a database. We will be focusing on this authentication model in this tutorial.

Let's start!

web.config file
The web.config file is an XML based configuration file which exists for every web application. The web.config file typical resides in the application root directory although it is possible to have multiple web.config files. If there is another web.config file placed in a directory below the application root, it will use those setting instead. The web.config file is where you will tell a web application to use either of the three types of autentication types.

Here we show you a basic example of what a web.config file looks like when it has be set to use form authentication. I will go in further detail and explain the tags.











































The first tag in the web.config file is the tag. It is the base tag for the web.config file and will contain all your configuration settings in here. The first tag specifies the settings that will apply to all the file in the same directory and the files below this directory.

tag
Here we come to our first tag for authentication, which is thence called . We see that there is one attribute for this tag and it specifies the type of authentication that will be applied to this site. The choices are Windows|Forms|Passport|None. This tutorial focuses on Forms authentication so that's what we got in there.

tag
Next we move to the tag. This tag is unique to the Forms authentication mode and will specify things such as the loginUrl, the type of protection and the timeout of inactivity.
loginUrl attribute - when a user does not have the correct credentials to view a page, the user will be forwarded to this url.
protection attribute - there are four(4) types of protection modes, All|None|Encryption|Validation. For simplicity sake, we're not going to go into this now, but if you want to know more, consult the MSDN documentation.
timeout attribute - this is an integer value specifying the number of minutes a user's cookie will be valid for. After this period of inactivity, the user will be forced to re-authenticate.

tag
This is an optional section if you want to specify the username/password combinations in here. We will first discuss authentication with passwords in the web.config file and I will later highlight how you can store the usernames and passwords in a database or XML file. The credentials tag also has an attribute called passwordFormat. Your choices for password format are: Clear|SHA1|MD5. We still stick with clear text passwords for now and talk about encrypting the passwords further down.

tag
This is also an optional tag (since it resides in the optional credentials tag). This tag is pretty straight forward, name attribute for the username and password attribute for the password.

tag
Now that we have specified our authentication type and the user accounts, we have to specify how the authentication is to be applied to our website. We used the authorization tag to mark this. The autorization tag is placed between the system.web tags. In the example above, we see that the authorization tag contains the tag. This allow tag will (as you can guess) specify which users have access to the website. And there is also a tag which will specify which users are denied access. The format of the users attributes is pretty simple. It's just a comma-delimited list of user names (i.e. users="jsmith, jdoe, blah"). There are also two special values that can be used in the users attribute. The first one is the * (asterix) character. This is used to denote "all users". So the example above allows access to all users. The second one is the ? (question mark) character. This is used to denote "anonymous" users. You can use this to deny anonymous access which will force users to authenticate before getting into some webpages (see the examples in the locations tags).

tag
Now what happens when we want some parts of the website to be protected and others to not be protected? ASP.NET did think of that and handles that by the tags. The location tag has one attribute, path, which is the path to apply a different set of security rules to. Inside the location tag, we have the system.web tag once again. The authorization tag is placed inside the system.web tag (just like the in first usage of ).

login.aspx file
Now that we have our web application all configured, we tackle the task of getting a user to authenticate themself by sending his/her username and password. In our tag, we specified that the loginUrl attribute is login.aspx and here is an example of a login page:



Login



Login




Username:

Password:









First, let's look at what the user sees. Our simple webpage example has two textboxes and a button. This webpage will be shown to the user anytime a request is made for a page and the user is does not have the proper credentials. This is a simple example, which you'll probably want to modify. Now we look at the code, this is where the authentication is done and the cookies are sent to the browser.

FormsAuthentication.Authenticate
The single login button on the webpage calls the Login_Click method when clicked. In this method, we use the FormsAuthentication.Authenticate(username,password) to get ASP.NET to check the credentials of the user. The parameters for this method is pretty straightforward and it just returns a boolean value.

FormsAuthentication.RedirectFromLoginPage
If the user is providing proper credentials, then we'll use the FormsAuthentication.RedirectFromLoginPage method. The parameters of this method are a username string and a boolean value. The first parameter is a username string and it is a name of the user for cookie authentication purposes. The value you put in there will be the user name that the client is associated with. It does not need to match the username used in the FormsAuthentication.Authenticate method but it is advisable to set the cookie to the username that was used to log in. The second parameter is a boolean value and it specifies whether or not a durable cookie (one that is saved across browser sessions) should be issued.
If you remember, when a user requests a page without proper authentication, they are redirected to the login page. After setting the cookie, the RedirectFromLoginPage will then send the user back to the page they came from.

There you go. You should have everything you need for a basic Forms based authentication system. Give it a try. If you want to extend the usage of authentication more, read on!

Advanced Part
Now we move to the more advanced topics on authenication. First we'll talk about encrypting your passwords then I'll tell you how to store your user accounts outside the web.config file.

Encrypting passwords
If you look at one of my tips, I say "Storing them as cleartext is asking for trouble." Why? Well, if your system gets comprimised, then someone can steal all your passwords. That's trouble. Also, sometimes people tend to use the same password in different sites because they don't want to memorize so many passwords. If you comprimse your password lists, then someone's going to be unhappy. That's trouble.
So how will you encrypt your passwords. ASP.NET has included some hashing functions to encrypt your passwords. What is a hashing function? Well, simply put, it sends your password to a function which spits out your password all garbled. The two hashing functions that SHA1 or MD5. Both hashing functions are suppose to not let malious users take the hashed password and get the original password. So how does this all work in ASP.NET? Passwords in the web.config file are stored as their hashed values. Then when a user tries to login, they will send they're password to the webserver and the webserver will hash the password and compare it to the hased password in the web.config file. If the two hashes match, then the password is correct. To hash a password, you can use the built in method called HashPasswordForStoringInConfigFile. You can call it like this: FormsAuthentication.HashPasswordForStoringInConfigFile("password","md5"). The first parameter is the password to be hashed. The second parameter is either "md5" or "sha1" depending on which hashing function you use. See your MSDN documentation for more detailed instructions. Make sure to update the passwordFormat attribute in the tag.

Users accounts stored elsewhere
Storing user accounts in the web.config file has it's limitations. A lot of larger website will prefer to store the passwords in an SQL database or maybe a seperate XML/text file. So in this case, we won't have those optional and tags. This tutorial does not concentrate on either of those technologies but we will show you an example of user accounts stored in an SQL database (so I'll assume you have some knowledge of reading data from a database.).

First, our example will assume the existence of a tabled called Users with the fields username and password.

Let's go back to the login.aspx page. We'll change the Login_Click method to look like this:


void Login_Click(Object sender, EventArgs e) {
String sHashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(password.Text,"MD5");
String sqlStmt = "Select username from Users where username='" + UserName.Text + "' and password='" + sHashedPassword + "'";
SqlConnection sqlConn = new SqlConnection("server=localhost;uid=sa;pwd=password;database=master;");
SqlCommand sqlCmd = new SqlCommand(sqlStmt, sqlConn);
sqlCmd.Connection.Open();
SqlDataReader sqlReader = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection);

if (sqlReader.Read())
FormsAuthentication.RedirectFromLoginPage(username.Text, true);
else
status.InnerHtml += "Invalid Login";
}




In this function, we've replaced the FormsAuthentication.Authenticate function with some SQL code that will query the database for a username/password pair. If such a pair if found, then the credentials are correct and the user can be issued a cookie and redirected back to the webpage. Also, notice in this example, I've used the HashPasswordForStoringInConfigFile method (see the section above for encrypting password). This function is used because the database will have the passwords hashed. The code above could easily be changed to look in an XML file or a text file. Just remember the key methods that you will have to use is "FormsAuthentication.RedirectFromLoginPage".


Tips

web.config file is cAsE-sEnSiTivE. Be careful how you type the tags and attributes.
Since the web.config file is an XML file, all opened tags must have a closing tag. Or a single tag must look like this: (notice the slash near the end).
Encrypt your passwords! Storing them as cleartext is asking for trouble.
Make sure you hash your passwords with the right hash algorithm and that you don't get them mixed up.
loginUrl has to be absolute. not relative
don't forget to make the password box of type password

how to read and add cookies in .net c#

C# And Cookies
--------------
Cookies allow you to store small bits of data on the user's computer. They take up a small amount of space on the user's hard drive and are often useful for storing nonessential information, such as user preferences.


ReadCoookies.aspx: Reading Cookies Written from the WriteCookies Example
1: <%@ language="C#" %>
2:
23:
24:
25: Use the button below to read a cookie

26:

27: Cookie Name
28:
29:
30: Write Cookies
31:
32:



WriteCookies.aspx: Writing Arbitrary Cookies
1: <%@ language="C#" %>
2:
22:
23:
24:

Use the button below to write cookies to your browser


25: The cookies will expire in one minute.
26:

27: Cookie Name

28: Cookie Value

29:

30:
31: Read the cookies
32:
33:




ReadCookies.aspx page reads cookies stored on a user's browser.

To write a cookie, create a new HttpCookie object (Line 6 of Listing 3.2), assign a string to its Value property (Line 9), and then call the Add() method on the Response.Cookies object (Line 17). You can also set the time of expiration for a cookie by setting the Expires property to a DateTime value (Line 14).

ReadCookies.aspx in Listing 3.3 shows that it's equally easy to read cookies back, using the Request.Cookies collection (Line 9), which is indexed by cookie name.

Cookies can store only strings, so if you need to store a more complex data type, it must be converted into a string. One possibility for storing complicated data structures is to write the structure out as an XML string and convert it back when reading the cookie.

You can store multiple strings in a cookie by treating each cookie as a collection object. For example, the following would work fine:

HttpCookie cookie = new HttpCookie("UserFavorites");
cookie["FavoriteColor"] = "blue";
cookie["FavoriteFlavor"] = "chocolate";
cookie["FavoriteDrink"] = "coffee";



Advanced Properties of the HttpCookie Class
Property
Description

Domain
Gets/sets the domain name that this cookie belongs to. If set, it restricts access to this cookie from Web servers in the specified domain, such as mycompany.com.

Path
Gets/sets the path that this cookie belongs to. If set, it restricts access to this cookie from Web pages in the specified path.

Secure
Gets/sets a flag that tells whether the cookie should be transmitted securely to the client browser using the HTTPS protocol. You must have HTTPS set up on your Web server for this option to work.

HasKeys
Tells whether the cookie is made up of a collection of strings.


Event delegation from user control to aspx page in ASP.NET,C#

“What is delegate?” we all have faced this question in one or more interview. and the most common answer is “Function pointer”. Here I am showing a simple example of delegate. I have one user control and one aspx page. The user control contains one button. When user click on this button I will call a method on main page using delegate. Here is my user control,

<%@ Control Language=”C#” AutoEventWireup=”true” CodeFile=”WebUserControl.ascx.cs” Inherits=”Dalegate_WebUserControl” %>



Fig - (1) WebUserControl.ascx

On WebUserControl.ascx.cs I have written simple delegate and event handler as shown below,

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

// Delegate declaration
public delegate void OnButtonClick(string strValue);

// Event declaration
public event OnButtonClick btnHandler;

// Page load
protected void Page_Load(object sender, EventArgs e)
{

}

protected void btnTest_Click(object sender, EventArgs e)
{
// Check if event is null
if (btnHandler != null)
btnHandler(string.Empty);

// Write some text to output
Response.Write(“User Control’s Button Click
”);
}
}

Fig - (2) WebUserControl.ascx.cs

Above code first check whether btnHandler is not null and than raise the event by passing argument. You can pass any number of argument in event. You need to change public delegate void OnButtonClick(string strValue) and btnHandler(string.Empty) lines for changing number of arguments. Now take a look at aspx page,

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

<%@ Register Src=”WebUserControl.ascx” TagName=”WebUserControl” TagPrefix=”uc1″ %>





Untitled Page




runat=”server”>

Chirag
Dipak
Shailesh












Fig - (3) Default.aspx

Default.aspx has one drop down list and a user control as shown in above code. Lets look at cs file,

public partial class Dalegate_Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Declare and Define Event of User Control. When User Clicks on button
(which is inside UserControl)
// below event is raised as I have called raised that event on Button Click
WebUserControl1.btnHandler += new
Dalegate_WebUserControl.OnButtonClick(WebUserControl1_btnHandler);

}

void WebUserControl1_btnHandler(string strValue)
{
Response.Write(“Main Page Event
Selected Value: “ +
ddlTemp.SelectedItem.Text + “
”);
}
}

Fig - (4) Default.aspx.cs

Now when you run the application and clicks on button you can see that when user click on button the user control raise the click event and calls the WebUserControl1_btnHandler(string strValue) method on main page.

From Custom Authentication to ASP.NET Forms Authentication

Introduction
One of the first projects I tackled with .NET, after doing the customary "Hello World" example, was converting a commercial ASP application into ASP.NET.

The application tasks were to process, store and acknowledge (via email) customers' answers to a competition question and to provide a secure area for company officials to view customer entries and send out bulk mail.

Apart from learning how to implement each step in ASP.NET, I also restructured the application to make it more object-oriented. For the secure area of the site I initially more-or-less faithfully reproduced the original functionality. Then I discovered and investigated ASP.NET's built-in Forms Authentication.

What is authentication?
Authentication is the process of obtaining identification credentials, such as name and password, from a user and validating those credentials against some authority. If the credentials are valid, the entity that submitted the credentials is considered an authenticated identity. Once an identity has been authenticated, the authorization process determines whether that identity has access to a given resource.

ASP.NET provides two other methods of authentication that are platform-specific with respect to the client, whereas Forms Authentication isn't. A couple of other articles on this site provide more in-depth insight into Forms Authentication. Here, I just provide the basics and discuss the issues I needed to address in my authentication process.

The Problem
A company official (also referred to as an administrator) wants to view the list of names and email addresses of the people who have entered the competition and the answers they've provided. The official may then perform other tasks, such as running queries or sending bulk mail.

The security requirements are:

Access to the pages in the secure area requires the official to log in with a valid user name and password.
Any attempt to navigate to a page in the secure area should redirect a user to the Login page.
It should not be possible to view any page when the browser is in offline mode, thereby bypassing security.
There should be a limit on the number of login attempts within any browser session.
Now, this isn't an e-commerce application. No credit card details are being processed. It's not necessary to have rock-solid security. Nevertheless it's worth exploring how security can be breached.

There is no direct navigation from the customer pages to the secure area but suppose somehow a customer or other user discovers the URL to one of the pages in the secure area. Then our security mechanism will force them to login. It will throw them out after a specified number of invalid attempts (say 3). Though they can shut down the browser and try again, but they don't know that. Hopefully they'll be discouraged. But if not, they'll still have a hard time discovering the correct user name and password. An administrator will be aware that they can restart the browser though. So if they forget their login details they can try again to their heart's content.

A more serious breach would be a malicious user's hacking the web site, downloading the database and extracting the login details. For this application we are just using a simple Microsoft Access database. The database is password-protected so it can't be opened in Access. But you can open the database in a text editor and perhaps have a poke around (it's mostly gibberish but it does contain the odd English word fragment). We could encrypt the database but we haven't.

The last possibility (I think) is a network sniffer's intercepting and extracting the user name and password as they are transported across the network. I have not catered for this. But it can be addressed by using Secure Sockets Layer (SSL) to encrypt the user name and password as they are passed over the network. If there is a security breach then a hacker would have access to the names and email addresses of our customers and could send them junk mail. That's it. In the initial design, at least, company officials cannot directly update the database via the web. All operations are read-only. So these restrictions would apply to a hacker too.

Initial Solution
We roll our own authentication functionality. First, define some Session objects in Global.asax.

protected void Session_Start(Object sender, EventArgs e)
{
// Administrator will only be allowed a certain number of login attempts
Session["MaxLoginAttempts"] = 3;
Session["LoginCount"] = 0;

// Track whether they're logged in or not
Session["LoggedIn"] = "No";
}

The login code looks like this.

Collapse
// Note: here we are just faithfully reproducing the original ASP behaviour.
// Otherwise we would use ASP.NET authentication.

// Check number of login attempts not exceeded. If it is redirect to failed
// login page.
int maxLoginAttempts = (int)Session["MaxLoginAttempts"];

if (Session["LoginCount"].Equals(maxLoginAttempts))
{
Response.Redirect("LoginFail.aspx?reason=maxloginattempts");
}

// Attempt login
if (Request.Form["txtUserName"].Trim() == AdministratorLogin.UserName &&
Request.Form["txtPassword"].Trim() == AdministratorLogin.Password)
{
// Success, so we can access customer details.
Session["LoggedIn"] = "Yes";
Response.Redirect("CustomerDetails.aspx");
}
else // Fail to login
{
// Report failure
string invalidLogin = "Invalid Login.";
lblMessage.Text = invalidLogin;

// Track the number of login attempts
int loginCount = (int)Session["LoginCount"];
loginCount += 1;
Session["LoginCount"] = loginCount;
}

When the login page is loaded it first checks to see whether the maximum number of login attempts has been exceeded. If it has the user is redirected to the "failed login" page.

If the user has not exceeded the maximum number of login attempts the user name and password are validated against those returned by the AdministratorLogin object. Here I have just provided a couple of read-only properties which retrieve the user name and password from a persistent store (in this case, a database). If all is OK the user can access the customer details page. If not, an invalid login message is displayed to the user and they can try again up until the allowable number of attempts.

Once the allowable number of login attempts has been exceeded the user will be unable to attempt a login again without being redirected to the "failed login" page.

If the user tries to access any other page in the secure area they are automatically directed to the login page. This is because the Page_Load event of each page calls a custom authentication function that looks like this.

///
/// Authenticates user for access to administration pages.
/// Ensures that page can't be navigated to
/// without user's being online and logged in.
///

protected void AuthenticateUser()
{
// Prevent caching, so can't be viewed offline
Response.Cache.SetCacheability(HttpCacheability.NoCache);

// Can't navigate to the page unless already logged in.
// If not already logged in go to login page.
if (Session["LoggedIn"].Equals("No"))
{
Response.Redirect("Login.aspx");
}
}

Without the first line users can navigate to a secure page when the browser is offline, if the page is in the history list, which is not what we want!

Forms Authentication Solution
The principal effect of using ASP.NET's Forms Authentication mechanism is that we no longer need to track the login state. The AuthenticateUser function above disappears. Nor do we have to write our own code to retrieve the user name and password from the database. But in order to use the mechanism we must add some sections to the web.config file in the application root directory. In the authentication section we replace the default settings with the following:
















Then, after the closing system.web tag:










The effect of these settings is that all pages in the directory are protected from access except through the login mechanism. Any files in sub-directories are also protected unless they contain their own web.config files with different settings.

In the authentication section, "FwLoginCookie" is the name of the cookie created by the authentication mechanism. Sometimes we may not want to use cookies. But for the present purposes these pages are for access only by company officials. They won't mind having cookies from themselves so to speak!

"Login.aspx" is the page to be redirected to if a user accesses any other page in the directory. The credentials section contains a list of valid user names and passwords in clear format. An alternative is to encrypt them. (There is a framework function that can do this.) Instead of putting the user name and password in the web.config file they could be placed in an external XML Users file (or a database). This is the solution we would go for if we wanted to add new users to the system.

The authorization section's settings deny anonymous (i.e., unauthenticated) users access to our pages.

The location section allows us to override the authentication and authorization checks for the LoginFail.aspx page. We need to do this so that an unauthenticated user can be redirected here when their login fails (i.e., after exceeding the allowable number of login attempts). An alternative is to put the LoginFail.aspx page in another directory or in a sub-directory with its own web.config file.

The revised code looks like this. The Session["LoggedIn"] object is no longer required:

protected void Session_Start(Object sender, EventArgs e)
{
// Administrator will only be allowed a certain number of login attempts
Session["MaxLoginAttempts"] = 3;
Session["LoginCount"] = 0;
}

The Login code now just uses ASP.NET's Forms Authentication methods instead of the custom user name and password checking functionality implemented in the initial solution:

Collapse
// Check number of login attempts not exceeded. If it is redirect to
// failed login page.
int maxLoginAttempts = (int)Session["MaxLoginAttempts"];

if (Session["LoginCount"].Equals(maxLoginAttempts))
{
Response.Redirect("LoginFail.aspx?reason=maxloginattempts");
}

// Attempt login
if (FormsAuthentication.Authenticate(txtUserName.Text.Trim(),
txtPassword.Text.Trim()))
{
// Success, create non-persistent authentication cookie.
FormsAuthentication.SetAuthCookie(txtUserName.Text, false);

// Navigate to Customer Details
Response.Redirect("CustomerDetails.aspx");
}
else // Fail to login
{
// Report failure
string invalidLogin = "Invalid Login.";
lblMessage.Text = invalidLogin;

// Track the number of login attempts
int loginCount = (int)Session["LoginCount"];
loginCount += 1;
Session["LoginCount"] = loginCount;
}

In the Page_Load event in each protected page we still need to prevent offline viewing.

// Prevent caching, so can't be viewed offline
Response.Cache.SetCacheability(HttpCacheability.NoCache);

That's it. Again, to make it solid, we should also apply SSL to prevent user name and password interception.

Insert,Update and Delete in XML file with xmldoc nad xmlelement

How to Read XML and insert a node in xml file
--------------------------------------------

'Insert in xml if not available.....
Dim strXmlPath As String = Server.MapPath("~/App_Data/reminder.xml")
Dim xmlDoc As New XmlDocument()
xmlDoc.Load(strXmlPath)
Dim nodeList As XmlNodeList = xmlDoc.SelectNodes("/reminder_list/reminder[@ID='" & Session("UserName").ToString().ToLower() & "']")

Dim xmlNamespace As String = [String].Empty
Dim parentNode As XmlElement = xmlDoc.CreateElement("reminder", xmlNamespace)
xmlDoc.DocumentElement.AppendChild(parentNode)
Dim t As XmlNode = xmlDoc.SelectSingleNode("/reminder_list/reminder[@rem_id='" & objReminder.ReminderId & "' and @ID='" & Session("UserName").ToString().ToLower() & "' and @subject='" & txtSuject.Text.Trim & "']")
If Convert.ToString(t) <> "" Then
t.ParentNode.RemoveChild(t)
parentNode.SetAttribute("end_date", strRemDateTime)
parentNode.SetAttribute("ID", Session("UserName").ToString().ToLower())
parentNode.SetAttribute("rem_id", hidremid.Value)
parentNode.SetAttribute("subject", txtSuject.Text.Trim)
parentNode.SetAttribute("start_date", Date.Now)
parentNode.SetAttribute("reminder", txtmsg.Text)
parentNode.SetAttribute("flag", 1)
xmlDoc.Save(strXmlPath)
Else
parentNode.SetAttribute("end_date", strRemDateTime)
parentNode.SetAttribute("ID", Session("UserName").ToString().ToLower())
parentNode.SetAttribute("rem_id", hidremid.Value)
parentNode.SetAttribute("subject", txtSuject.Text.Trim)
parentNode.SetAttribute("start_date", Date.Now)
parentNode.SetAttribute("reminder", txtmsg.Text)
parentNode.SetAttribute("flag", 1)
xmlDoc.Save(strXmlPath)
End If

Custom Paging in ASP.NET with C# and SQL SERVER Stored Procedures

how to do custom paging::
------------------------------------

stored procedure::

ALTER PROCEDURE [dbo].[GetProductListBySearch1]
(
@currentpage varchar(100) = null,
@pagesize int
)

AS
SET NOCOUNT ON
declare @query varchar(4000)
declare @querycnt varchar(4000)

declare @skiprecords int
set @skiprecords=(@currentpage -1) * @pagesize

if(@skiprecords <0)
set @skiprecords=0

SELECT ROW_NUMBER() OVER (ORDER BY id desc) as id,title
FROM article

declare @totalrecords int
declare @no int
declare @pageno int

set @totalrecords= (select count(*) from article)
set @pageno=(@totalrecords / convert(varchar,@pagesize))

if((@totalrecords / convert(varchar,@pagesize))>0)
begin
set @pageno=@pageno+1
end

select @pageno as total_pages, @totalrecords
return



aspx.cs page:::
---------------------------

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using DLL;
using System.IO;
public partial class Default2 : System.Web.UI.Page
{
PagedDataSource page = new PagedDataSource();
DataTable dt=new DataTable();
int index = 0;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
getdata();
}
}

public void getdata()
{
dt = Class1.getdata();
if (dt.Rows.Count > 0)
{
page.DataSource = dt.DefaultView;
page.AllowPaging = true;
page.PageSize = 2;
page.CurrentPageIndex = index;


ArrayList array = new ArrayList();
for (int i = 0; i < page.Count; i++)
{
array.Add((i + 1).ToString());
}

rpt.DataSource = array;
rpt.DataBind();
// changecolor();
GridView1.DataSource = page;
GridView1.DataBind();
}
}


protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = GridView1.Rows[e.RowIndex];

}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
}
protected void rpt_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "change")
{
index = Convert.ToInt32(e.CommandArgument.ToString()) - 1;
getdata();
}
}
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (rpt.Items.Count >= 0)
{
LinkButton lnk = (LinkButton)e.Item.FindControl("lnk");

lnk.ForeColor = System.Drawing.Color.Red;
changecolor();
}
}
}
--------------------------

aspx page:::::::
------------------------------------

































<%#Container.DataItem %>


Monday, August 18, 2008

EPDQ Integration \\\

EPDQ Integration

Document Date: 16th July, 2008


(1) Code for the checkout page, from where the payment gateway is to be called for:

#region Generate EPDQ
public void Generate_EPDQ(int Booking_Id, float Total)
{
string clientid = ConfigurationManager.AppSettings["clientid"];
string password = ConfigurationManager.AppSettings["password"];
string chargetype = ConfigurationManager.AppSettings["chargetype"]; // Text string indicating the chargetype specified for the transaction.
string currencycodeGBP = ConfigurationManager.AppSettings["currencycodeGBP"];
string currencycodeEuro = ConfigurationManager.AppSettings["currencycodeEuro"];
string Encryption_URL = ConfigurationManager.AppSettings["Encryption_URL"];
string Postdata = "clientid=" + clientid + "&password=" + password + "&oid=" + Booking_Id + "&chargetype=" + chargetype + "¤cycode=[currencycode]&total=" + Total;

//The Following Creates the WebClient Object
WebClient Web = new WebClient();

//The Header Content Type is then set
Web.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

//if (rad_euro.Checked)
//{
// Postdata = Postdata.Replace("[currencycode]", currencycodeEuro);
//}
//else if (rad_Pound.Checked)
//{
// Postdata = Postdata.Replace("[currencycode]", currencycodeGBP);
//}
Postdata = Postdata.Replace("[currencycode]", currencycodeGBP);

//PostData is then declared as data type Byte and populated with the post data
Byte[] PostData = Encoding.ASCII.GetBytes(Postdata);

//The Web object is then used to upload the postdata to the Encryption URL and the response is stored in the Response variable
Byte[] Response = Web.UploadData(Encryption_URL, "POST", PostData);

//The response from the post is then converted from Type Byte to String and stored in the session variable
Session["Response"] = (Encoding.ASCII.GetString(Response));
div_Payment.InnerHtml = "";
//+ "\n" + Session["Response"] +
//div_Payment.InnerHtml;

}
#endregion



(2) Code for the callback [Thankyou] page :
#region Page_Load
protected void Page_Load(object sender, EventArgs e)
{
CheckPaymentResponse();
}
#endregion

#region CheckPaymentResponse
public void CheckPaymentResponse()
{
if (Request.QueryString != null)
{
if (Request.QueryString.Keys.Count > 0)
{
if (Request["oid"] != null)
{
if (Request["oid"].ToString() != "")
{
DataRow drmail = null;
int oid = int.Parse(Request["oid"].ToString());
drmail=DAL.Booking.GetMailDetails(oid);
if (drmail != null)
{
if (drmail.ItemArray.Length > 0)
{
string FromEmail = ConfigurationManager.AppSettings["FromEmail"].ToString();
string MailBCC = ConfigurationManager.AppSettings["BookingBCC"].ToString();
Mail.SendMail(FromEmail, drmail["propertytitle"].ToString(), drmail["Email"].ToString(), drmail["mailtext"].ToString(), "Booking detail for " + drmail["propertytitle"].ToString(),"",MailBCC);
}
}
}
}
}
}
string Paymentchk = "";
Paymentchk = Request.Url.ToString() + "
";
Paymentchk += Request.ServerVariables["request_method"] + "
";
Paymentchk += Request.Form["transactionstatus"] + "
";
Paymentchk += Request.Form["Oid"] + "
";
Paymentchk += Request.Form["total"] + "
";
Paymentchk += Request.Form["Clientid"] + "
";
Paymentchk += Request.Form["chargetype"] + "
";
Paymentchk += Request.Form["datetime"] + "
";
Paymentchk += Request.Form["ecistatus"] + "
";
Paymentchk += Request.Form["cardprefix"] + "
";
div_paymentchk.InnerHtml = Paymentchk;

if (Request.ServerVariables["request_method"].ToLower() == "post")
{
if (Request.Form["transactionstatus"].ToLower() == "success")
{
td_Failure.Visible = false;
td_success.Visible = true;
int orderid = int.Parse(Request.Form["Oid"].ToString()); //Text string containing the order identification number. If a value was not supplied in your originating request, a unique order number will be generated by ePDQ. Size: Up to 36 characters
int check = DAL.Booking.UpdateOrderStatusToPaid(orderid);

//PLACE MAIL SEND CODE

/*Request.Form["transactionstatus"]; //Success,DECLINED
Request.Form["total"]; //Total numeric value presented for authorisation. Range: 1.00 to 999999999.00 Size: Up to 12 characters
Request.Form["Clientid"]; //Numeric client id (also known as your Store ID) assigned by Barclaycard Business . This is different to your merchant id and terminal id.
Request.Form["chargetype"]; //Text string indicating the chargetype specified for the transaction. (Either Auth or PreAuth).
Request.Form["datetime"]; //Text string indicating when the order was submitted by the ePDQ CPI checkout. The date will always be in this format. e.g. Jan 23 2005 15:45:51
Request.Form["ecistatus"]; //The Internet Authentication response. Only provided if you are enrolled in Internet Authentication and the transaction was Visa or MasterCard.
Request.Form["cardprefix"]; //First digit of the supplied card number. Only provided if you are enrolled in Internet Authentication and the transaction was Visa or MasterCard.*/
}
else
{
//Response.Redirect("failure.aspx", false);
td_Failure.Visible = true;
td_success.Visible = false;
}
}
else
{
//Response.Redirect("failure.aspx", false);
td_Failure.Visible = true;
td_success.Visible = false;
}
}
#endregion


(3)Js to be placed on the aspx page from where the payment gateway is to be called:

function loadEPDQ()
{
var payment_URL = '<%= ConfigurationManager.AppSettings["Payment_URL"] %>';
document.form1.method= "POST";
document.form1.action= payment_URL ;
document.form1.submit();
}


Is the div on whose innerHTML, the above js will be registered.
This can be viewed in the function GenerateEPDQ in point (1).

(4) Hidden fields to be placed on the aspx page from where the payment gateway is to be called:

<%= Session["Response"] %>








Note: These input fields should be placed above the “div_Payment” div.


(5) Web.config keys














Note:
- the page url should be completely in lowercase
- the hidden fields should not be within the ajax

Wednesday, July 30, 2008

This is ultimate grid from etcjs.com site a totally javascript grid which makes your site too fast you can't imagine...

This is ultimate grid from etcjs.com site a totally javascript grid which makes your site too fast you can't imagine...
=======================================================

Register this .js files and .css files for this grid display and work
===================================










ASCX control
============

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



==============================

dashboard.aspx.cs file
=====================




using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Text;

public partial class ascx_controls_DashBoardOrder : System.Web.UI.UserControl
{
#region Variable
private int _OrderType;
public string Details;
#endregion

#region Property
public int OrderType
{
get { return _OrderType; }
set { _OrderType = value; }
}
#endregion

#region PageLoad
protected void Page_Load(object sender, EventArgs e)
{


DataTable dt_Orders = DAL.Order.GetDashboardOrder(_OrderType);

StringBuilder sb = new StringBuilder();

foreach (DataRow dr in dt_Orders.Rows)
{
sb.AppendFormat("['{0}','{1}','{2}','{3}','
£{4}
','{5}'],", dr["Id"], dr["CustomerName"], dr["OrderItem"], dr["OrderStatus"], dr["OrderTotal"], dr["PNumber"]);
}


string Final;
Final = "[" + sb.ToString().TrimEnd(',') + "]";

string ScriptToRegister = @" Ext.onReady(function(){

Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

var myData"+this.ClientID+ @" = "+Final+@"

// create the data store
var store"+this.ClientID+ @" = new Ext.data.SimpleStore({
fields: [{name: 'Id'},
{name: 'CustomerName'},
{name: 'OrderItem'},
{name: 'OrderStatus'},
{name: 'Total'},
{name: 'PNumber'}]
});
store" + this.ClientID + @".loadData(myData" + this.ClientID + @");

// create the Grid
var grid" + this.ClientID + @" = new Ext.grid.GridPanel({
store: store" + this.ClientID + @",
columns: [
{header: 'Order No.', width: 70, sortable: false, dataIndex: 'Id'},
{header: 'Customer', sortable: true, dataIndex: 'CustomerName', width:150},
{header: 'Items', sortable: true, dataIndex: 'OrderItem', width: 60},
{header: 'Total', sortable: true, dataIndex: 'Total',width:70},
{id:'OrderStatus',header: 'Status', sortable: true, dataIndex: 'OrderStatus',width:125}
" + (OrderType==3?",{id:'PNumber',header: 'P Number', sortable: true, dataIndex: 'PNumber',width:100}":"")+@"
],
stripeRows: true,

height:255,
width:440
});

grid" + this.ClientID + @".render('" + div_Details.ClientID + @"');

grid" + this.ClientID + @".getSelectionModel().selectFirstRow();
});";//autoExpandColumn: 'OrderStatus',
Page.ClientScript.RegisterClientScriptBlock(typeof(string), "JsBlock"+this.ClientID, ScriptToRegister, true);
}
#endregion
}

Tuesday, July 29, 2008

Extending Linq class

Extending Linq.
Filed under: Extension Methods, IQueryable, Linq — Tags: DataSet, DataTable, Extension Methods, Linq — peteohanlon @ 12:47 pm

Sorry for the delay in continuing with the discussions on regular expressions, but I got a little sidetracked with the upgrade to Visual Studio 2008 (.NET 3.5), and all the “goodies” that it brings to you. For the moment I’m going to be putting the discussion on regular expressions to one side. I will get back to them but, for the moment, I want to take you on a journey into .NET 3.5.

Possibly the biggest headline in .NET 3.5 is the introduction of Linq. I have to admit that I was highly skeptical about how useful it will actually be in the “real world”, but having played around with it for a little while I have to admit that I’m actually quite impressed. It’s a well thought out area that actually does do a lot to increase productivity. Now, in this entry I’m not going to delve into the internals of Linq and how to use it. Instead, I’m going to talk about a feature of .NET 3.5 and how it can be used to “extend” the behaviour of Linq. Specifically, we’re going to look at how to use Extension Methods to add the ability to return a DataSet and DataTable from Linq in the same way you’d return a generic list.

The following code shows what you actually need to do to extend the IQueryable object in Linq. For the moment, don’t worry about what IQueryable actually does - once you’ve used Linq for a little while it becomes apparent what this interface is for, and where it fits into the big Linq picture.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
using System.Data.Common;
using System.Data;
using System.Data.SqlClient; namespace LinqTesting
{
///
/// This class contains miscellaneous extension methods for Linq to Sql.
///

public static class LinqDataExtensions
{
///
/// Add the ability to return a DataTable based on a particular query
/// to a queryable object.
///

/// The IQueryable object to extend.
/// The query to execute.
/// The name of the datatable to be added.
/// The populated DataTable.
public static DataTable ToDataTable(this IQueryable extenderItem,
DbCommand query,
string tableName)
{
if (query == null)
{ throw new ArgumentNullException("query");
}
SqlCommand cmd = (SqlCommand)query;
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
DataTable dt = new DataTable(tableName);
try
{
cmd.Connection.Open();
adapter.Fill(dt);
}
finally
{
cmd.Connection.Close(); }
return dt;
}
///
/// Add the ability to return a DataSet based on a particular query
/// to a queryable object.
///

/// The IQueryable object to extend.
/// The query to execute.
/// The name of the DataTable to be added.
/// The populated dataset.
public static DataSet ToDataSet(this IQueryable extenderItem,
DbCommand query,
string tableName)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
return ToDataSet(extenderItem, query, null, tableName);
} ///
/// Add the ability to return a dataset based on a particular query
/// to a queryable object.
///

/// The IQueryable object to extend.
/// A generic dictionary containing the
/// query to execute along with the name of the table to add it to.
/// The populated dataset.
public static DataSet ToDataSet(this IQueryable extenderItem,
Dictionary query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
if (query.Count == 0)
{
throw new ArgumentException("query");
}
return ToDataSet(extenderItem, query, null);
} ///
/// Add the ability to return a dataset based on a particular query /// to a queryable object.
///

/// The IQueryable object to extend.
/// A generic dictionary containing the
/// query to execute along with the name of the table to add it to.
/// An optional DataSet. This allows application
/// to add multiple tables to the dataset.
/// The populated dataset.
public static DataSet ToDataSet(this IQueryable extenderItem,
Dictionary DbCommand> query,
DataSet dataSet)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
if (query.Count == 0)
{
throw new ArgumentException("query");
}
if (dataSet == null) dataSet = new DataSet();

foreach (KeyValuePair kvp in query)
{
dataSet = LinqDataExtensions.ToDataSet(extenderItem,
kvp.Value,
dataSet,
kvp.Key);
}
return dataSet;
} ///
/// Add the ability to return a dataset based on a particular
/// query to a queryable object.
///

/// The IQueryable object to extend.
/// The query to execute.
/// An optional DataSet. This allows
/// application to add multiple tables to the dataset.
/// The name of the DataTable to be added.
/// The populated dataset.
public static DataSet ToDataSet(this IQueryable extenderItem,
DbCommand query,
DataSet dataSet,
string tableName)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
if (dataSet == null)
dataSet = new DataSet();
DataTable tbl = LinqDataExtensions.ToDataTable(extenderItem,
query,
tableName);
if (tbl != null)
{
if (dataSet.Tables.Contains(tableName))
dataSet.Tables.Remove(tableName);
dataSet.Tables.Add(tbl);
}
return dataSet;
}
}
}

A couple of points to note about the class. Extension methods have to be in static classes, and they have to be static methods. In order to note what class is being extended, you use the “this” keyword before the first parameter. The code itself is fairly self explanatory and doesn’t do anything clever. The clever bit actually occurs in the Linq side. Here’s an example:

public DataSet GetDataSet()
{
IQueryable q = GetAllQuery();
return q.ToDataSet(context.GetCommand(GetAllQuery()), null, "MyTable");
}

private IQueryable GetAllQuery()
{
IQueryable q = from p in context.MyTables
select p; return q;
}

Why Constructors?

Why Constructors?

Initialization of values of different variables is critical in any application development. C# does initialize simple data-types to default values as per the language specification in the .Net framework, but for classes that are user specific, it is obvious that you would be the only one who can decide what is an ideal default value. The means of achieving this is Constructors. There is also a perception that constructors can only be used beyond initialization, which is true to some extent. We will examine them in the following sections.

Features of a Constructor

A Method that does not have a return type. E.g.

public class in4DataGrid
{
//Constructor declaration. Note after the modifier "public" keyword, there is no
//mention of a datatype or void. Also the name is same as that of class.
public in4DataGrid()
{
// Some Code Here.
}
}


Can either be static or Instance based. E.g.

public class in4DataGrid
{
//Static Constructor. Modifiers are irrelevant here.
static in4DataGrid()
{
// Some Code Here.
}
//Instance based
public in4DataGrid()
{
// Some Code Here.
}
}


Take parameters and behave just like any other method, which means that any instructions can be encapsulated in a constructor. E.g.

public class in4DataGrid
{
private int intWidth;
private int intHeight;
//Parameters intWidth and intHeight of type int.
public in4DataGrid(int Width, int Height)
{
intWidth = Width;
intHeight = Height;
//Some Code Here.
}
}


Constructors can be declared "private or protected" even though declaring them public is a common scenario. When declared as private, one cannot create an instance of the class or derive the class.


Can be overloaded. Further, one overloaded constructor can call the other one to take advantage of encapsulation and take negate the risks of code duplication within overloaded constructors (See the following section examples).
The following section deals with the how best to leverage the features of Constructors in our classes.

How to Use?

Use application logic in constructors carefully. Try to minimize unnecessary database operations in constructors like loading a Dataset that is used only in specific sections or on demand from the calling class. This is a performance overhead.


Do not write redundant code in overloaded constructors. This will become a huge maintenance issue as your class hierarchy grows and you start implementing more overloaded constructors in your derived classes. The following example shows a common section where in validation of initialization logic happens. E.g.

public class in4DataGrid
{
private int intWidth;
private int intHeight;
//Overloaded constructor 1 with no parameters. But the constructor initializes //the values by calling the other constructor which holds common business //validations by using the keyword "this".
public in4DataGrid():this(200,300)
{
//Some Code Here.
}
//Overloaded constructor 2 with parameters intWidth and intHeight of type //int.
public in4DataGrid(int Width, int Height)
{
intWidth = Width;
intHeight = Height;
// Do some business validation here.
if(intWidth > intHeight)
{
//Some code here
}
}
}


Try to use static constructors and variables when you are dealing with Global variables. This is especially a good design practice since you can initialize the static variables easily within static constructors instead of using constant variables. Other advantage would be to encapsulate your instruction logic for these variables. E.g.

public class in4DataGrid
{
private int intWidth;
private int intHeight;
private static int intMinimumHeight;
//Overloaded static constructor 1 with no parameters. But the constructor initializes the values by calling the other constructor.
static in4DataGrid()
{
//Some Business logic Here.
//Initialize the value based on logic.
intMinimumHeight=100;
}
//Overloaded instance based constructor 2 with parameters intWidth and //intHeight of type int.
public in4DataGrid(int Width, int Height)
{
if(Width > intMinimumWidth)
{
intWidth = Width;
intHeight = Height;
}
else
{
//Some Code Here.
}
}
}


Overloaded static constructors are dangerous when used to call other constructors, so try not to call other static constructor from within.


Design your derived class constructors carefully. This is because when an instance of derived class is created there is more than one constructor that will be called, i.e. both the base class and the derived class in the hierarchy. The constructors of the derived class first will run constructors of base class. The issue arises when you have overloaded constructor definitions in the base and derived classes. Overlooking here would prove costly. Make sure you use the keyword "base()" to make calls to overloaded base classes. E.g.

public class in4DataGrid: System.Data.DataGrid
{
//Constructor declaration. Use of keyword "base()" makes sure that the call is made to the base class(here it is System.Data.DataGrid). One can call any overloaded constructor of the base class this way.
public in4DataGrid(): base()
{
// Some Code Here.
}
}
Also note that the constructor initializers "base" and "this" are the only keywords that can be used when making a call to the base constructor, also any one among these can be specified.

Conclusion

Proper design of constructors goes a long way in solving some core problems faced in your class design. C# supports enormous flexibility to accommodate the use of various types of constructors. One has to judge the need of the application and never overlook the importance of constructors.

Class Modifiers and their uses in C# .Net

Class Modifiers and their uses in C# .Net
Filed under: Computer Science — Tags: Basic Programming, C#.Net, OOP — sadi02 @ 6:56 am

Class/Interface (Base class)
Inheritance (Inherited class)

Implementation (Interface)

(Child)
(Instance)

Is initiated??

General
Abstract
Sealed
Static*

General
Yes
Yes
Yes
No
No
Yes

Abstract
Yes
Yes
Yes
No
No
No

Sealed
No
No
No
No
No
Yes

Static
No
No
No
No
No
No

Interface
Yes
Yes
Yes
No
Yes
No





















This table is for showing relationship between a base class and child class

In this table I want to show the accessibility among the various types of classes and interface. From this table you also can know what type of class can be initiated. This is one example that helps you to understand the table.

If you use Abstract class as base class and take a general class as child and want to inherit, this will possible …here you can see..

Base: Abstract (ASadi)

Child: Interface (Sadi)

Accessibility: Yes

abstract class Sadi : ASadi

{

#region ASadi Members

public int getint() {

throw new Exception(“The method or operation is not implemented.”); }

#endregion

}

If you execute this code, it executes properly

From the first column of the table we can say that general class inherites both general and abstract class and also implements an interface. Theses classes can not inherites sealed as well as static class. only General and Sealed classes can be initiated.

From the table and above disscussion we can conclude that,

Abstract Class

A class defined as abstract is used as a base class. Such a class is used for the purpose of inheritance only i.e. other classes are derived from this class. We cannot create an object of an abstract class.An abstract class may contain methods and properties. The classes derived from the abstract class inherit these methods and properties. The abstract class may also contain abstract methods and properties. Abstract method and properties do not have any functionality. The derived class defines their full functionality.

Here is an example of an abstract class:

abstract class MyAbstract { public abstract void AbMethod(); }

Sealed Class

Classes can be declared as sealed. This is accomplished by putting the sealed keyword before the keyword class in the class definition. For example:

public sealed class classSealed { // Class members here. public string ID; public double Price; } A sealed class cannot be used as a base class. For this reason, it cannot also be an abstract class. Sealed classes are primarily used to prevent derivation. Because they can never be used as a base class, some run-time optimizations can make calling sealed class members slightly faster. Sealing a class means one can not derive from it. Sealing a method means one can not override it. In C# structs are implicitly sealed; therefore, they cannot be inherited. If we try to inherit from a sealed class in another class we will get compile time error about Inconsistent accessibility (code is shown in following code listing). In C# a method can not be declared as sealed. However when we override a method in a derived class, we can declare the overridden method as sealed as shown below. By declaring it as sealed, we can avoid further overriding of this method.

Static Class


Static classes are classes that contain only static members. Following is an example of static class. public static MyClass { …..}

A class defined as abstract is used as a base class. Such a class is used for the purpose of inheritance only i.e. other classes are derived from this class. We cannot create an object of an abstract class.An abstract class may contain methods and properties. The classes derived from the abstract class inherit these methods and properties. The abstract class may also contain abstract methods and properties. Abstract method and properties do not have any functionality. The derived class defines their full functionality.

Here is an example of an abstract class:

abstract class MyAbstract { public abstract void AbMethod(); }

Difference between class and struct in C# .Net

Difference between class and struct in C# .Net
Filed under: Computer Science — Tags: Basic Programming, C#.Net, OOP — sadi02 @ 8:40 am
1. Classes are reference types and structs are value types.
Since classes are reference type, a class variable can be assigned null.But we cannot assign null to
a struct variable, since structs are value type.
2. When you instantiate a class, it will be allocated on the heap.When you instantiate a struct, it gets created on the stack.
3. You will always be dealing with reference to an object ( instance ) of a class. But you will not be dealing with references to an instance of a struct ( but dealing directly with them ).
4. When passing a class to a method, it is passed by reference. When passing a struct to a method, it’s passed by value instead of as a reference.
5. You cannot have instance Field initializers in structs.But classes can have
example:
class MyClass
{
int myVar =10; // no syntax error.
public void MyFun( )
{
// statements
}
}
struct MyStruct
{
int myVar = 10; // syntax error.
public void MyFun( )
{
// statements
}
}
6. Classes can have explicit parameterless constructors. But structs cannot have
7. Classes must be instantiated using the new operator. But structs can be
8. Classes support inheritance.But there is no inheritance for structs.
( structs don’t support inheritance polymorphism )
9. Since struct does not support inheritance, access modifier of a member of a struct cannot be protected or protected internal.11. A class is permitted to declare a destructor.But a struct is not
12. classes are used for complex and large set data. structs are simple to use.

captcha class for c# developer

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;



public class CaptchaImage
{
// Public properties (all read-only).
public string Text
{
get { return this.text; }
}
public Bitmap Image
{
get { return this.image; }
}
public int Width
{
get { return this.width; }
}
public int Height
{
get { return this.height; }
}

// Internal properties.
private string text;
private int width;
private int height;
private string familyName;
private Bitmap image;

// For generating random numbers.
private Random random = new Random();

// ====================================================================
// Initializes a new instance of the CaptchaImage class using the
// specified text, width and height.
// ====================================================================
public CaptchaImage(string s, int width, int height)
{
this.text = s;
this.SetDimensions(width, height);
this.GenerateImage();
}

// ====================================================================
// Initializes a new instance of the CaptchaImage class using the
// specified text, width, height and font family.
// ====================================================================
public CaptchaImage(string s, int width, int height, string familyName)
{
this.text = s;
this.SetDimensions(width, height);
this.SetFamilyName(familyName);
this.GenerateImage();
}

// ====================================================================
// This member overrides Object.Finalize.
// ====================================================================
~CaptchaImage()
{
Dispose(false);
}

// ====================================================================
// Releases all resources used by this object.
// ====================================================================
public void Dispose()
{
GC.SuppressFinalize(this);
this.Dispose(true);
}

// ====================================================================
// Custom Dispose method to clean up unmanaged resources.
// ====================================================================
protected virtual void Dispose(bool disposing)
{
if (disposing)
// Dispose of the bitmap.
this.image.Dispose();
}

// ====================================================================
// Sets the image width and height.
// ====================================================================
private void SetDimensions(int width, int height)
{
// Check the width and height.
if (width <= 0)
throw new ArgumentOutOfRangeException("width", width, "Argument out of range, must be greater than zero.");
if (height <= 0)
throw new ArgumentOutOfRangeException("height", height, "Argument out of range, must be greater than zero.");
this.width = width;
this.height = height;
}

// ====================================================================
// Sets the font used for the image text.
// ====================================================================
private void SetFamilyName(string familyName)
{
// If the named font is not installed, default to a system font.
try
{
Font font = new Font(this.familyName, 12F);
this.familyName = familyName;
font.Dispose();
}
catch (Exception ex)
{
this.familyName = System.Drawing.FontFamily.GenericSerif.Name;
}
}

// ====================================================================
// Creates the bitmap image.
// ====================================================================
private void GenerateImage()
{
// Create a new 32-bit bitmap image.
Bitmap bitmap = new Bitmap(this.width, this.height, PixelFormat.Format32bppArgb);

// Create a graphics object for drawing.
Graphics g = Graphics.FromImage(bitmap);
g.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(0, 0, this.width, this.height);

// Fill in the background.
HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White);
g.FillRectangle(hatchBrush, rect);

// Set up the text font.
SizeF size;
float fontSize = rect.Height + 1;
Font font;
// Adjust the font size until the text fits within the image.
do
{
fontSize--;
font = new Font(this.familyName, fontSize, FontStyle.Bold);
size = g.MeasureString(this.text, font);
} while (size.Width > rect.Width);

// Set up the text format.
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;

// Create a path using the text and warp it randomly.
GraphicsPath path = new GraphicsPath();
path.AddString(this.text, font.FontFamily, (int)font.Style, font.Size, rect, format);
float v = 4F;
PointF[] points =
{
new PointF(this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),
new PointF(rect.Width - this.random.Next(rect.Width) / v, this.random.Next(rect.Height) / v),
new PointF(this.random.Next(rect.Width) / v, rect.Height - this.random.Next(rect.Height) / v),
new PointF(rect.Width - this.random.Next(rect.Width) / v, rect.Height - this.random.Next(rect.Height) / v)
};
Matrix matrix = new Matrix();
matrix.Translate(0F, 0F);
path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);

// Draw the text.
hatchBrush = new HatchBrush(HatchStyle.LargeConfetti, Color.Red, Color.Red);
g.FillPath(hatchBrush, path);

// Add some random noise.
int m = Math.Max(rect.Width, rect.Height);
for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
{
int x = this.random.Next(rect.Width);
int y = this.random.Next(rect.Height);
int w = this.random.Next(m / 50);
int h = this.random.Next(m / 50);
g.FillEllipse(hatchBrush, x, y, w, h);
}

// Clean up.
font.Dispose();
hatchBrush.Dispose();
g.Dispose();

// Set the image.
this.image = bitmap;
}
}

compress a ASPX pagesthrough this class

compress a ASPX pgaeg through this class
========================================


#region Using



using System;

using System.Web;

using System.IO.Compression;



#endregion
///

/// Compresses the output using standard gzip/deflate.

///


namespace DAL
{
public class CompressionModule : IHttpModule
{
#region IHttpModule Members
void IHttpModule.Dispose()
{
// Nothing to dispose;
}
void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
#endregion

#region Compression
private const string GZIP = "gzip";
private const string DEFLATE = "deflate";

void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
if (app.Request.RawUrl.Contains(".aspx") || app.Request.RawUrl.Contains(".htm") )
{
if (IsEncodingAccepted(GZIP))
{
app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);
SetEncoding(GZIP);
}
else if (IsEncodingAccepted(DEFLATE))
{
app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);
SetEncoding(DEFLATE);
}
}
}

///
/// Checks the request headers to see if the specified
/// encoding is accepted by the client.
///

private bool IsEncodingAccepted(string encoding)
{
return HttpContext.Current.Request.Headers["Accept-encoding"] != null && HttpContext.Current.Request.Headers["Accept-encoding"].Contains(encoding);
}

///
/// Adds the specified encoding to the response headers.
///

///
private void SetEncoding(string encoding)
{
HttpContext.Current.Response.AppendHeader("Content-encoding", encoding);
}
#endregion
}
}

best perfomance in LINQ query

the performance can be drastically improved by turning off the change tracking service (context.ObjectTrackingEnabled=false) and by precompiling the queryies (CompiledQuery.Compile<>()).
Jim Wooley
http://blogs.msdn.com/alikl/archive/2007/12/18/asp-net-3-5-extensions-basic-steps-to-create-dynamic-data-web-application-focus-on-security-and-performance.aspx
http://www.codeplex.com/LINQ2SQLEB/SourceControl/ListDownloadableCommits.aspx
trouble shooting for LINQ
http://msdn2.microsoft.com/en-us/library/bb386996.aspx
\
http://blogs.msdn.com/mattwar/archive/2008/01/16/linq-building-an-iqueryable-provider-part-ix.aspx

http://blogs.msdn.com/adonet/archive/2008/03/27/ado-net-entity-framework-performance-comparison.aspx

To better understand how the query process affects performance, here’s the basic logic of a query, in order of execution.
• Parts of the query are broken up to allow for query caching to occur resulting in a query plan.
• Query is passed through to the .NET Framework data provider and executed against the database.
• The results are returned and the user iterates over the results.
• On each entity, the key properties are used to create an EntityKey.
• If the query is a tracking query then the EntityKey is used to do identity resolution.
• If the EntityKey is not found, the object is created and the properties copied into the object.
• The object is added to the ObjectStateManager for tracking.
• If merge options are used, then the properties follow the merge option rules.
• If the object is related to other objects in the ObjectContext, then the relationships between the entities are connected.

In my next post, I’ll show some of the performance improvements that can be made on the query itself and how Entity SQL and LINQ to Entities perform.
When optimizing query performance in the Entity Framework, you should consider what works best for your particular programming scenario. Here are a few key takeaways:
• Initial creation of the ObjectContext includes the cost of loading and validating the metadata.
• Initial execution of any query includes the costs of building up a query cache to enable faster execution of subsequent queries.
• Compiled LINQ queries are faster than Non-compiled LINQ queries.
• Queries executed with a NoTracking merge option work well for streaming large data objects or when changes and relationships do not need to be tracked.

Linq to SQL Deferred Loading - Lazy Load
Consider the Blog Site database I used in previous posts about Linq to SQL:

Linq to SQL Deferred Loading
If we query for the available blogs in the site using Linq to SQL, the query should look like this:
BlogDataContext ctx = new BlogDataContext(...);

var query = from b in ctx.Blogs
select b;

foreach (Blog b in query)
{
Console.WriteLine("{0}", b.BlogName);
}
This Linq query will result in the following SQL statement being sent to the DB:
SELECT [t0].[BlogID], [t0].[BlogName], [t0].[Owner]
FROM [dbo].[Blogs] AS [t0]
and the output will be:

Now, if we change the statement that outputs the name of the blog, and let it also print the number of posts in the blog:
foreach (Blog b in query)
{
Console.WriteLine("{0} has {1} posts", b.BlogName, b.Posts.Count);
}
This time, the output will be:

What Linq to SQL does is whenever it runs into the expression b.Posts.Count, it knows that the Posts collection of the blog was not yet retrieved, so it automatically generates the appropriate select statement and gets the posts. For example:
SELECT [t0].[PostID], [t0].[BlogID], [t0].[Title], [t0].[Body], [t0].[PublishDate]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[BlogID] = 'bursteg'
The problem is that a similar query is executed for each blog instance. So if we have a long list of blogs, than this simple loop can be a performance hit.
This behavior is called Linq to SQL Deferred Loading, and it is turned on by default. In order to turn it of, you can set the DeferredLoadingEnabled property to false.
BlogDataContext ctx = new BlogDataContext(...);

ctx.DeferredLoadingEnabled = false;

var query = from b in ctx.Blogs
select b;

foreach (Blog b in query)
{
Console.WriteLine("{0} has {1} posts", b.BlogName, b.Posts.Count);
}
Now, this query returns 0 as the number of posts of each blog.

Asynchronous Pages in ASP.NET 2.0

Asynchronous Pages in ASP.NET 2.0
============================
ASP.NET 2.0 is replete with new features ranging from declarative data binding and Master Pages to membership and role management services. But my vote for the coolest new feature goes to asynchronous pages, and here's why.
When ASP.NET receives a request for a page, it grabs a thread from a thread pool and assigns that request to the thread. A normal, or synchronous, page holds onto the thread for the duration of the request, preventing the thread from being used to process other requests. If a synchronous request becomes I/O bound—for example, if it calls out to a remote Web service or queries a remote database and waits for the call to come back—then the thread assigned to the request is stuck doing nothing until the call returns. That impedes scalability because the thread pool has a finite number of threads available. If all request-processing threads are blocked waiting for I/O operations to complete, additional requests get queued up waiting for threads to be free. At best, throughput decreases because requests wait longer to be processed. At worst, the queue fills up and ASP.NET fails subsequent requests with 503 "Server Unavailable" errors.
Asynchronous pages offer a neat solution to the problems caused by I/O-bound requests. Page processing begins on a thread-pool thread, but that thread is returned to the thread pool once an asynchronous I/O operation begins in response to a signal from ASP.NET. When the operation completes, ASP.NET grabs another thread from the thread pool and finishes processing the request. Scalability increases because thread-pool threads are used more efficiently. Threads that would otherwise be stuck waiting for I/O to complete can now be used to service other requests. The direct beneficiaries are requests that don't perform lengthy I/O operations and can therefore get in and out of the pipeline quickly. Long waits to get into the pipeline have a disproportionately negative impact on the performance of such requests.
The ASP.NET 2.0 Beta 2 async page infrastructure suffers from scant documentation. Let's fix that by surveying the landscape of async pages. Keep in mind that this column was developed with beta releases of ASP.NET 2.0 and the .NET Framework 2.0.


Asynchronous Pages in ASP.NET 1.x
ASP.NET 1.x doesn't support asynchronous pages per se, but it's possible to build them with a pinch of tenacity and a dash of ingenuity. For an excellent overview, see Fritz Onion's article entitled "Use Threads and Build Asynchronous Handlers in Your Server-Side Web Code" in the June 2003 issue of MSDN®Magazine.
The trick here is to implement IHttpAsyncHandler in a page's codebehind class, prompting ASP.NET to process requests not by calling the page's IHttpHandler.ProcessRequest method, but by calling IHttpAsyncHandler.BeginProcessRequest instead. Your BeginProcessRequest implementation can then launch another thread. That thread calls base.ProcessRequest, causing the page to undergo its normal request-processing lifecycle (complete with events such as Load and Render) but on a non-threadpool thread. Meanwhile, BeginProcessRequest returns immediately after launching the new thread, allowing the thread that's executing BeginProcessRequest to return to the thread pool.
That's the basic idea, but the devil's in the details. Among other things, you need to implement IAsyncResult and return it from BeginProcessRequest. That typically means creating a ManualResetEvent object and signaling it when ProcessRequest returns in the background thread. In addition, you have to provide the thread that calls base.ProcessRequest. Unfortunately, most of the conventional techniques for moving work to background threads, including Thread.Start, ThreadPool.QueueUserWorkItem, and asynchronous delegates, are counterproductive in ASP.NET applications because they either steal threads from the thread pool or risk unconstrained thread growth. A proper asynchronous page implementation uses a custom thread pool, and custom thread pool classes are not trivial to write (for more information, see the .NET Matters column in the February 2005 issue of MSDN Magazine).
The bottom line is that building async pages in ASP.NET 1.x isn't impossible, but it is tedious. And after doing it once or twice, you can't help but think that there has to be a better way. Today there is—ASP.NET 2.0.


Asynchronous Pages in ASP.NET 2.0
ASP.NET 2.0 vastly simplifies the way you build asynchronous pages. You begin by including an Async="true" attribute in the page's @ Page directive, like so:
Copy Code
<%@ Page Async="true" ... %>
Under the hood, this tells ASP.NET to implement IHttpAsyncHandler in the page. Next, you call the new Page.AddOnPreRenderCompleteAsync method early in the page's lifetime (for example, in Page_Load) to register a Begin method and an End method, as shown in the following code:
Copy Code
AddOnPreRenderCompleteAsync (
new BeginEventHandler(MyBeginMethod),
new EndEventHandler (MyEndMethod)
);
What happens next is the interesting part. The page undergoes its normal processing lifecycle until shortly after the PreRender event fires. Then ASP.NET calls the Begin method that you registered using AddOnPreRenderCompleteAsync. The job of the Begin method is to launch an asynchronous operation such as a database query or Web service call and return immediately. At that point, the thread assigned to the request goes back to the thread pool. Furthermore, the Begin method returns an IAsyncResult that lets ASP.NET determine when the asynchronous operation has completed, at which point ASP.NET extracts a thread from the thread pool and calls your End method. After End returns, ASP.NET executes the remaining portion of the page's lifecycle, which includes the rendering phase. Between the time Begin returns and End gets called, the request-processing thread is free to service other requests, and until End is called, rendering is delayed. And because version 2.0 of the .NET Framework offers a variety of ways to perform asynchronous operations, you frequently don't even have to implement IAsyncResult. Instead, the Framework implements it for you.
The codebehind class in Figure 1 provides an example. The corresponding page contains a Label control whose ID is "Output". The page uses the System.Net.HttpWebRequest class to fetch the contents of http://msdn.microsoft.com. Then it parses the returned HTML and writes out to the Label control a list of all the HREF targets it finds.
Figure 1 AsyncPage.aspx.cs
Copy Code
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

public partial class AsyncPage : System.Web.UI.Page
{
private WebRequest _request;

void Page_Load (object sender, EventArgs e)
{
AddOnPreRenderCompleteAsync (
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler (EndAsyncOperation)
);
}

IAsyncResult BeginAsyncOperation (object sender, EventArgs e,
AsyncCallback cb, object state)
{
_request = WebRequest.Create("http://msdn.microsoft.com");
return _request.BeginGetResponse (cb, state);
}
void EndAsyncOperation (IAsyncResult ar)
{
string text;
using (WebResponse response = _request.EndGetResponse(ar))
{
using (StreamReader reader =
new StreamReader(response.GetResponseStream()))
{
text = reader.ReadToEnd();
}
}

Regex regex = new Regex ("href\\s*=\\s*\"([^\"]*)\"",
RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(text);

StringBuilder builder = new StringBuilder(1024);
foreach (Match match in matches)
{
builder.Append (match.Groups[1]);
builder.Append("
");
}

Output.Text = builder.ToString ();
}
}

Since an HTTP request can take a long time to return, AsyncPage.aspx.cs performs its processing asynchronously. It registers Begin and End methods in Page_Load, and in the Begin method, it calls HttpWebRequest.BeginGetResponse to launch an asynchronous HTTP request. BeginAsyncOperation returns to ASP.NET the IAsyncResult returned by BeginGetResponse, resulting in ASP.NET calling EndAsyncOperation when the HTTP request completes. EndAsyncOperation, in turn, parses the content and writes the results to the Label control, after which rendering occurs and an HTTP response goes back to the browser.

Figure 2 Synchronous vs. Asynchronous Page Processing
Figure 2 illustrates the difference between a synchronous page and an asynchronous page in ASP.NET 2.0. When a synchronous page is requested, ASP.NET assigns the request a thread from the thread pool and executes the page on that thread. If the request pauses to perform an I/O operation, the thread is tied up until the operation completes and the page lifecycle can be completed. An asychronous page, by contrast, executes as normal through the PreRender event. Then the Begin method that's registered using AddOnPreRenderCompleteAsync is called, after which the request-processing thread goes back to the thread pool. Begin launches an asynchronous I/O operation, and when the operation completes, ASP.NET grabs another thread from the thread pool and calls the End method and executes the remainder of the page's lifecycle on that thread.

Figure 3 Trace Output Shows Async Page's Async Point
The call to Begin marks the page's "async point." The trace in Figure 3 shows exactly where the async point occurs. If called, AddOnPreRenderCompleteAsync must be called before the async point—that is, no later than the page's PreRender event.


Asynchronous Data Binding
It's not all that common for ASP.NET pages to use HttpWebRequest directly to request other pages, but it is common for them to query databases and data bind the results. So how would you use asynchronous pages to perform asynchronous data binding? The codebehind class in Figure 4 shows one way to go about it.
Figure 4 AsyncDataBind.aspx.cs
Copy Code
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Configuration;

public partial class AsyncDataBind : System.Web.UI.Page
{
private SqlConnection _connection;
private SqlCommand _command;
private SqlDataReader _reader;


protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Hook PreRenderComplete event for data binding
this.PreRenderComplete +=
new EventHandler(Page_PreRenderComplete);

// Register async methods
AddOnPreRenderCompleteAsync(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation)
);
}
}
IAsyncResult BeginAsyncOperation (object sender, EventArgs e,
AsyncCallback cb, object state)
{
string connect = WebConfigurationManager.ConnectionStrings
["PubsConnectionString"].ConnectionString;
_connection = new SqlConnection(connect);
_connection.Open();
_command = new SqlCommand(
"SELECT title_id, title, price FROM titles", _connection);
return _command.BeginExecuteReader (cb, state);
}

void EndAsyncOperation(IAsyncResult ar)
{
_reader = _command.EndExecuteReader(ar);
}

protected void Page_PreRenderComplete(object sender, EventArgs e)
{
Output.DataSource = _reader;
Output.DataBind();
}

public override void Dispose()
{
if (_connection != null) _connection.Close();
base.Dispose();
}
}

AsyncDataBind.aspx.cs uses the same AddOnPreRenderCompleteAsync pattern that AsyncPage.aspx.cs uses. But rather than call HttpWebRequest.BeginGetResponse, its BeginAsyncOperation method calls SqlCommand.BeginExecuteReader (new in ADO.NET 2.0), to perform an asynchronous database query. When the call completes, EndAsyncOperation calls SqlCommand.EndExecuteReader to get a SqlDataReader, which it then stores in a private field. In an event handler for the PreRenderComplete event, which fires after the asynchronous operation completes but before the page is rendered, it then binds the SqlDataReader to the Output GridView control. On the outside, the page looks like a normal (synchronous) page that uses a GridView to render the results of a database query. But on the inside, this page is much more scalable because it doesn't tie up a thread-pool thread waiting for the query to return.


Calling Web Services Asynchronously
Another I/O-related task commonly performed by ASP.NET Web pages is callouts to Web services. Since Web service calls can take a long time to return, pages that execute them are ideal candidates for asynchronous processing.
Figure 5 shows one way to build an asynchronous page that calls out to a Web service. It uses the same AddOnPreRenderCompleteAsync mechanism featured in Figure 1 and Figure 4. The page's Begin method launches an asynchronous Web service call by calling the Web service proxy's asynchronous Begin method. The page's End method caches in a private field a reference to the DataSet returned by the Web method, and the PreRenderComplete handler binds the DataSet to a GridView. For reference, the Web method targeted by the call is shown in the following code:
Copy Code
[WebMethod]
public DataSet GetTitles ()
{
string connect = WebConfigurationManager.ConnectionStrings
["PubsConnectionString"].ConnectionString;
SqlDataAdapter adapter = new SqlDataAdapter
("SELECT title_id, title, price FROM titles", connect);
DataSet ds = new DataSet();
adapter.Fill(ds);
return ds;
}
Figure 5 AsyncWSInvoke1.aspx.cs
Copy Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class AsyncWSInvoke1 : System.Web.UI.Page
{
private WS.PubsWebService _ws;
private DataSet _ds;

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Hook PreRenderComplete event for data binding
this.PreRenderComplete +=
new EventHandler(Page_PreRenderComplete);

// Register async methods
AddOnPreRenderCompleteAsync(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation)
);
}
}

IAsyncResult BeginAsyncOperation (object sender, EventArgs e,
AsyncCallback cb, object state)
{
_ws = new WS.PubsWebService();
// Fix up URL for call to local VWD-hosted Web service
_ws.Url = new Uri(Request.Url, "Pubs.asmx").ToString();
_ws.UseDefaultCredentials = true;
return _ws.BeginGetTitles (cb, state);
}

void EndAsyncOperation(IAsyncResult ar)
{
_ds = _ws.EndGetTitles(ar);
}

protected void Page_PreRenderComplete(object sender, EventArgs e)
{
Output.DataSource = _ds;
Output.DataBind();
}

public override void Dispose()
{
if (_ws != null) _ws.Dispose();
base.Dispose();
}
}

That's one way to do it, but it's not the only way. The .NET Framework 2.0 Web service proxies support two mechanisms for placing asynchronous calls to Web services. One is the per-method Begin and End methods featured in .NET Framework 1.x. and 2.0 Web service proxies. The other is the new MethodAsync methods and MethodCompleted events found only in the Web service proxies of the .NET Framework 2.0.
If a Web service has a method named Foo, then in addition to having methods named Foo, BeginFoo, and EndFoo, a .NET Framework version 2.0 Web service proxy includes a method named FooAsync and an event named FooCompleted. You can call Foo asynchronously by registering a handler for FooCompleted events and calling FooAsync, like this:
Copy Code
proxy.FooCompleted += new FooCompletedEventHandler (OnFooCompleted);
proxy.FooAsync (...);
...
void OnFooCompleted (Object source, FooCompletedEventArgs e)
{
// Called when Foo completes
}
When the asynchronous call begun by FooAsync completes, a FooCompleted event fires, causing your FooCompleted event handler to be called. Both the delegate wrapping the event handler (FooCompletedEventHandler) and the second parameter passed to it (FooCompletedEventArgs) are generated along with the Web service proxy. You can access Foo's return value through FooCompletedEventArgs.Result.
Figure 6 presents a codebehind class that calls a Web service's GetTitles method asynchronously using the MethodAsync pattern. Functionally, this page is identical to the one in Figure 5. Internally, it's quite different. AsyncWSInvoke2.aspx includes an @ Page Async="true" directive, just like AsyncWSInvoke1.aspx. But AsyncWSInvoke2.aspx.cs doesn't call AddOnPreRenderCompleteAsync; it registers a handler for GetTitlesCompleted events and calls GetTitlesAsync on the Web service proxy. ASP.NET still delays rendering the page until GetTitlesAsync completes. Under the hood, it uses an instance of System.Threading.SynchronizationContext, another new class in 2.0, to receive notifications when the asynchronous call begins and when it completes.
Figure 6 AsyncWSInvoke2.aspx.cs
Copy Code
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class AsyncWSInvoke2 : System.Web.UI.Page
{
private WS.PubsWebService _ws;
private DataSet _ds;

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Hook PreRenderComplete event for data binding
this.PreRenderComplete +=
new EventHandler(Page_PreRenderComplete);

// Call the Web service asynchronously
_ws = new WS.PubsWebService();
_ws.GetTitlesCompleted += new
WS.GetTitlesCompletedEventHandler(GetTitlesCompleted);
_ws.Url = new Uri(Request.Url, "Pubs.asmx").ToString();
_ws.UseDefaultCredentials = true;
_ws.GetTitlesAsync();
}
}

void GetTitlesCompleted(Object source,
WS.GetTitlesCompletedEventArgs e)
{
_ds = e.Result;
}

protected void Page_PreRenderComplete(object sender, EventArgs e)
{
Output.DataSource = _ds;
Output.DataBind();
}

public override void Dispose()
{
if (_ws != null) _ws.Dispose();
base.Dispose();
}
}

There are two advantages to using MethodAsync rather than AddOnPreRenderCompleteAsync to implement asynchronous pages. First, MethodAsync flows impersonation, culture, and HttpContext.Current to the MethodCompleted event handler. AddOnPreRenderCompleteAsync does not. Second, if the page makes multiple asynchronous calls and must delay rendering until all the calls have been completed, using AddOnPreRenderCompleteAsync requires you to compose an IAsyncResult that remains unsignaled until all the calls have completed. With MethodAsync, no such hijinks are necessary; you simply place the calls, as many of them as you like, and the ASP.NET engine delays the rendering phase until the final call returns.


Asynchronous Tasks
MethodAsync is a convenient way to make multiple asynchronous Web service calls from an asynchronous page and delay the rendering phase until all the calls complete. But what if you want to perform several asynchronous I/O operations in an asynchronous page and those operations don't involve Web services? Does that mean you're back to composing an IAsyncResult that you can return to ASP.NET to let it know when the last call has completed? Fortunately, no.
In ASP.NET 2.0, the System.Web.UI.Page class introduces another method to facilitate asynchronous operations: RegisterAsyncTask. RegisterAsyncTask has four advantages over AddOnPreRenderCompleteAsync. First, in addition to Begin and End methods, RegisterAsyncTask lets you register a timeout method that's called if an asynchronous operation takes too long to complete. You can set the timeout declaratively by including an AsyncTimeout attribute in the page's @ Page directive. AsyncTimeout="5" sets the timeout to 5 seconds. The second advantage is that you can call RegisterAsyncTask several times in one request to register several async operations. As with MethodAsync, ASP.NET delays rendering the page until all the operations have completed. Third, you can use RegisterAsyncTask's fourth parameter to pass state to your Begin methods. Finally, RegisterAsyncTask flows impersonation, culture, and HttpContext.Current to the End and Timeout methods. As mentioned earlier in this discussion, the same is not true of an End method registered with AddOnPreRenderCompleteAsync.
In other respects, an asynchronous page that relies on RegisterAsyncTask is similar to one that relies on AddOnPreRenderCompleteAsync. It still requires an Async="true" attribute in the @ Page directive (or the programmatic equivalent, which is to set the page's AsyncMode property to true), and it still executes as normal through the PreRender event, at which time the Begin methods registered using RegisterAsyncTask are called and further request processing is put on hold until the last operation completes.To demonstrate, the codebehind class in Figure 7 is functionally equivalent to the one in Figure 1, but it uses RegisterTaskAsync instead of AddOnPreRenderCompleteAsync. Note the timeout handler named TimeoutAsyncOperation, which is called if HttpWebRequest.BeginGetRequest takes too long to complete. The corresponding .aspx file includes an AsyncTimeout attribute that sets the timeout interval to 5 seconds. Also note the null passed in RegisterAsyncTask's fourth parameter, which could have been used to pass data to the Begin method.
Figure 7 AsyncPageTask.aspx.cs
Copy Code
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

public partial class AsyncPageTask : System.Web.UI.Page
{
private WebRequest _request;

protected void Page_Load(object sender, EventArgs e)
{
PageAsyncTask task = new PageAsyncTask(
new BeginEventHandler(BeginAsyncOperation),
new EndEventHandler(EndAsyncOperation),
new EndEventHandler(TimeoutAsyncOperation),
null
);
RegisterAsyncTask(task);
}

IAsyncResult BeginAsyncOperation(object sender, EventArgs e,
AsyncCallback cb, object state)
{
_request = WebRequest.Create("http://msdn.microsoft.com");
return _request.BeginGetResponse(cb, state);
}

void EndAsyncOperation(IAsyncResult ar)
{
string text;
using (WebResponse response = _request.EndGetResponse(ar))
{
using (StreamReader reader =
new StreamReader(response.GetResponseStream()))
{
text = reader.ReadToEnd();
}
}

Regex regex = new Regex("href\\s*=\\s*\"([^\"]*)\"",
RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(text);

StringBuilder builder = new StringBuilder(1024);
foreach (Match match in matches)
{
builder.Append(match.Groups[1]);
builder.Append("
");
}

Output.Text = builder.ToString();
}

void TimeoutAsyncOperation(IAsyncResult ar)
{
Output.Text = "Data temporarily unavailable";
}
}

The primary advantage of RegisterAsyncTask is that it allows asynchronous pages to fire off multiple asynchronous calls and delay rendering until all the calls have completed. It works perfectly well for one asynchronous call, too, and it offers a timeout option that AddOnPreRenderCompleteAsync doesn't. If you build an asynchronous page that makes just one async call, you can use AddOnPreRenderCompleteAsync or RegisterAsyncTask. But for asynchronous pages that place two or more async calls, RegisterAsyncTask simplifies your life considerably.
Since the timeout value is a per-page rather than per-call setting, you may be wondering whether it's possible to vary the timeout value for individual calls. The short answer is no. You can vary the timeout from one request to the next by programmatically modifying the page's AsyncTimeout property, but you can't assign different timeouts to different calls initiated from the same request.


Wrapping It Up
So there you have it—the skinny on asynchronous pages in ASP.NET 2.0. They're significantly easier to implement in this upcoming version of ASP.NET, and the architecture is such that you can batch multiple async I/O operations in one request and delay the rendering of the page until all the operations have completed. Combined with async ADO.NET and other new asynchronous features in the .NET Framework, async ASP.NET pages offer a powerful and convenient solution to the problem of I/O-bound requests that inhibit scalability by saturating the thread pool.
A final point to keep in mind as you build asynchronous pages is that you should not launch asynchronous operations that borrow from the same thread pool that ASP.NET uses. For example, calling ThreadPool.QueueUserWorkItem at a page's asynchronous point is counterproductive because that method draws from the thread pool, resulting in a net gain of zero threads for processing requests. By contrast, calling asynchronous methods built into the Framework, methods such as HttpWebRequest.BeginGetResponse and SqlCommand.BeginExecuteReader, is generally considered to be safe because those methods tend to use completion ports to implement asynchronous behavior.