Sunday, October 19, 2008

Tags in web.config Part-2

Custom Error tag

So you have developed your web application and now all of a sudden somewhere in the application some error is thrown and you get the white and yellow error page of ASP.NET giving all sorts of technical information which may not be of any use to the normal users of our application but of great use to hackers. So how to avoid this?

One way to handle this kind errors is by writing a code in global.asax ' "Application_Error" event and then redirecting the request to the custom error page. The other elegant way of handling error is by using the "customErrors" tag in web.config file. A sample customErrors tag looks like the one shown below.

<customErrors mode="On" defaultRedirect="CustomError.aspx">
            <error statusCode="404" redirect="FileNotFound.htm"/>
            <error statusCode="500" redirect="IntrnServerError.aspx"/>
</customErrors>

What customErrors tag does is if there is any unhandled errors in any of the web pages in the web application/website the asp.net runtime automatically redirects to the custom error page mentioned in the defaultRedirect attribute of the customErrors tag. One point to note here is that any error inside a try catch blog will not be redirected to the custom error page since it is handled in the catch block.

The attributes of the customeErrors tag is explained below.

Tag Explanation
mode The mode attribute tells the system whether the custom errors are disabled or enabled. The allowed values for the attribute are On, Off and RemoteOnly. The default value is RemoteOnly.
On: Once the custom errors are enabled and if there is no url specified in the defaultRedirect attribute then all the errors in the application will be shown in the (ugly) yellow and white page of the asp.net. If url is specified in the defaultRedirect attribute then any error in any page of the application will be redirected to the url whether the application is accessed remotely or locally.
RemoteOnly: If you want to display the full details of the error in the ugly page of asp.net to the persons accessing the application locally and redirect remote users to the custom page mentioned in the defaultRedirect attribute then you can make use of RemoteOnly. This can be usefull to the developers who want to see the actual exception rather than the nicely designed error page. How it works is that when a user accessess the page locally i.e. from the machine where it is hosted the yellow and white error page of asp.net will show up with the full error details whereas a normal browser who accesses the application from the convenience of his home will see the nicely designed error page, if any error occurs.
Off: The custom errors will be switched off when Off is used i.e. the detailed error page of asp.net will be shown for all the errors in the application for both the remote user (normal user) of the application as well as for the local user.

defaultRedirect

The url where the browser will be redirected on any error in the application. If the attribute is not used or left blank then the error will be displayed in the asp.net error page with full error details. This an optional parameter.

Now you have set the custom error pages and as you are aware for any error in any of the aspx page it will be redirected to the custom error page. Now  you want to log the last error that occurred somewhere in some aspx from the custom error page. You have to retrieve the error and for this one can make use of the Server class to get the last error as shown below

Exception ex = Server.GetLastError();

GetLastError() will get the last error raised. Now using the ex variable you log the required info to your log file or database where ever you want. Using this approach you can a central place from where you can log any unhandled error. Isn't it a neat approach?

Using the <error........./> tag you can specify for a specific http status code which custom error page to be displayed instead of the system provided error pages like file not found error (404 status code), internal server error (500 status code) pages. The error tag has two attributes namely statusCode and redirect. In statusCode attribute you can mention the Http status codes like 400 (bad request), 401 (access denied), 403 (forbidden), 404 (not found) etc and in redirect attribute you can give the url of the page to which you want to redirect for the particular status code.

<customErrors mode="On" defaultRedirect="CustomError.aspx">
    <error statusCode="400" redirect="badrequest.htm"/>
    <error statusCode="401" redirect="accessdenied.htm"/>
    <error statusCode="403" redirect="forbidden.htm"/>
    <error statusCode="404" redirect="notfound.htm"/>
</customErrors>

So whenever there is a file not found error or access denied or forbidden access etc the user will be redirected to the custom error page mentioned in the redirect attribute against the statusCode attribute of the error tag.

Some of the status code and their meaning is given below. These can be configured using the error tag of customErrors tag of web.config

Status Code Meaning
500 Internal server error
501 Header values specify a configuration that is not implemented.
502 Web server received an invalid response while acting as a gateway or proxy.
503 Service unavailable.
504 Gateway timeout.
400 Bad request.
401 Access denied.
403 Forbidden.
404 Not found.
405 HTTP verb used to access this page is not allowed (method not allowed.)
406 Client browser does not accept the MIME type of the requested page.
407 Proxy authentication required.
412 Precondition failed.
413 Request entity too large.
414 Request-URI too long.
415 Unsupported media type.
417 Execution failed.

Most of the errors mentioned in the above table will work along with error tag. I have not tested all of them except for the few mentioned in the e.g. If someone finds the status codes not working please let me know.

To be continued....

Know more.

Sandeep

Wednesday, September 10, 2008

Tags in web.config (Part-1)

Tags in web.config
This blog covers some of the commonly used tags in web.config. In simple term web.configs are ASP.NET configurations maintained in XML format. All the configuration are maintained in the form of XML tags. The first tag which I would like to explain is the one related to the different authentication which can be enabled using web.config. There are many types of authentication which can be used in a web application. They are Anonymous, Windows, Forms, Passport, basic, Certificate, Kerberos and digest. The ones which we are going to enable using web.config are anonymous, windows and forms.

Authentication Tags
Anonymous authentication: Anonymous authentication can be enabled using the following tag

 <authentication mode="none" >

With anonymous authentication enabled anyone can access the website. Most of the websites have anonymous enabled for the pages which can be browsed by all without restriction. Recently I heard a comment from a techie saying that anonymous authentication cannot be enabled through web.config it can be enabled only through IIS. This is not true. With the above tag one can very well enable anonymous authentication.

Now you have given anonymous authentication, what about giving access to people having their login details in your domain network or your company' network. Then you can make use of windows authentication. The tag for the same is as follows

 <authentication mode="Windows" />
Further if you want to restrict some users from accessing you can do the same by extending the authentication tag like the one shown below.
 
 <authentication mode="Windows" />
<authorization>     <allow user=* />
     <deny user="sand" />
</authorization>
 
From the above tag what I mean is all the users except sand should be given unrestricted access. Now say if you want to impersonate the user who has logged in i.e. suppose you have a user named "sandeep" registered in your domain and you want the threads accessing resources in your ASP.NET application take the identity of sandeep and freely access resources then you can use the below tag in conjunction with windows authentication.
 
 <authentication type="Windows" />
<identity impersonate="true"/>
Normally the threads running in Asp.Net have the least privileges and they take the identity of the default Asp.Net account and because of this they may be restricted from accessing the resources on the server. By impersonating the logged in users identity the thread will have more access privileges.

How about giving access to your customers who don't fall in your domain or customers created dynamically?

The answer is making use of forms authentication. By making use of forms authentication you can redirect all unauthenticated requests to your website or to some resources in your website to a page say "login.aspx" and get the user id and password and authenticate user against a database of your choice and give authenticated access to the resources in your website. Forms authentication is a cookie based based authentication system. The tag for the same is given below.

<authentication mode="Forms">
<forms name="FormCookie" loginUrl="Login.aspx" protection="None" timeout="20" requireSSL="false" slidingExpiration="true" defaultUrl="home.aspx">
</forms>
</authentication >
The mode attribute tells that the authentication is forms. Once you specify the mode of authentication is forms then you should provide further details in the "form" tag as shown above. The various attributes used in the form tag are explained below.
 
Attributes Explanation
name Attribute in the form tag tells the system the name of the authentication cookie in which the authentication details will be stored. The default value is ".ASPXAUTH"
loginUrl Is the name of the login/authentication page with path. The default value taken by the system is "login.aspx"
protection Specifies the type of encryption used for storing the authentication cookie details. Default value is All. The allowed values are Encryption, None and Validation.
requireSSL Specifies whether the cookie needs ssl connection to be transmitted. If the property is set to true then the cookies are not returned unless the connection being used is ssl enabled. By default the value is set to false.
timeout Is the time specified in minutes after which the cookie expires. Please refer sliding expiration also.
slidingExpiration The default value is true which means the cookie needs to be refreshed on each and every request and also the cookie expiration time is also reset. All this happens for a single session. Confused? Lets understand with an e.g. If sliding expiration attribute is set to true then the cookie timeout is calculated after the last request i.e. for e.g. suppose a user "A" logs in and he is authenticated at around 8:20 am and the timeout attribute is set to 20 minutes then his cookie will expire by 8:40 am thereby his session. If the user accesses some resource/page in the website say at about 8:30 am then his cookie timeout is reset to 8:50 am. This goes on for further request till his session is closed or timed out or the user logs out. If the slidingExpiration attribute is set to false then the logged in user' session will expire by 8:40 even if he access any number resources/pages in the site. So if slidingExpiration is set to true then the session will be increased by the number of minutes specified in the timeout property after each and every request. The default timeout is 30 minutes.
defaultUrl The url of the page to which the user needs to be redirected after he is successfully authenticated.
 
Above mentioned attribute are some of the commonly used attributes of forms tag.

A small C# sample code showing authentication procedure.
 
 bool authenticated = Authenticate(userName.Text.Trim(),
password.Text.Trim());//Method which will connect to the
database and return true if the user exists.

if (authenticated)
{
    //Getting the authentication section of the web.config file.
    AuthenticationSection authenticationSection =
     (AuthenticationSection)WebConfigurationManager.
    GetSection("system.web/authentication"); 

    /*Retrieving the minutes from the timeout attribute of forms tag of web.config. */
    int timeOut = authenticationSection.Forms.Timeout.Minutes;

    //Creating the authentication ticket.
    FormsAuthenticationTicket authenticationTicket = new
      FormsAuthenticationTicket(1, userName, DateTime.Now,
      DateTime.Now.AddMinutes(timeOut), false, roles);

    //Encrypting the content.
     string encryptedTicket = FormsAuthentication.Encrypt
       (authenticationTicket); 

     /*Creating the cookie with the name retrieved from the web.config name attribute. */ 
     HttpCookie authenticationCookie = new HttpCookie
      (FormsAuthentication.FormsCookieName, encryptedTicket);

     /* Adding the cookie to the response and authenticating the user. */
     Response.Cookies.Add(authenticationCookie);
}
 
Note: The web.config authentication works in conjunction with the authentication set in the IIS and it works on the least privilege concept i.e. the authentication which has the least privilege will take into effect. E.g. the least privileged authentication is the anonymous authentication and if you set anonymous in IIS and windows in web.config the thread will take anonymous as the identity. The below matrix table shows the combination. The table is taken from msdn, the original link can be found here.

Table 1. IIS anonymous authentication

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

-
MACHINE\IUSR_MACHINE
-

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

-
MACHINE\ASPNET
-

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\IUSR_MACHINE
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Table 2. IIS basic authentication

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
Domain\UserName
Domain\UserName

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
MACHINE\ASPNET
Domain\UserName

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
Domain\UserName
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Table 3. IIS digest authentication

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
Domain\UserName
Domain\UserName

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
MACHINE\ASPNET
Domain\UserName

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
Domain\UserName
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Table 4: IIS integrated Windows

Web.config Settings

Variable Location

Resultant Identity

<identity impersonate="true"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
Domain\UserName
Domain\UserName

<identity impersonate="false"/>
<authentication mode="Windows" />

HttpContext
WindowsIdentity
Thread

Domain\UserName
MACHINE\ASPNET
Domain\UserName

<identity impersonate="true"/>
<authentication mode="Forms" />

HttpContext
WindowsIdentity
Thread

Name provided by user
Domain\UserName
Name provided by user

<identity impersonate="false"/>
<authentication mode="Forms" />

HttpContext. WindowsIdentity
Thread

Name provided by user
MACHINE\ASPNET
Name provided by user

Location Tag
You have enabled forms authentication, now you want some files or folders to have free access or some restriction based on user or their roles, in such a scenario you can make use of the location tag. The syntax is as given below.

<location path="graph">
     <system.web>
          <authorization>
               <allow users="user1, user2"/>
               <deny users="user5"/>
               <allow roles="admin"/>
               <deny roles="normaluser"/>
          </authorization>
     </system.web>
</location>
Using the above tag one can restrict or allow access to pages/resources in a folder. The above e.g. gives access rights to a folder specified in the path attribute of the location tag, similar to this you can give restriction to a file also. Just substitute the path attribute with the file name, suppose you have a file named "restrict.aspx" inside "secret" folder then in the path attribute you can substitute this "secret/restrict.aspx". You can restrict any kind of file and it need not be a aspx page. From the above tag we can infer that we have given some restriction to "graph" folder. We are giving access to users with user ids "user1" and "user2" at the same time if a user with identity "user5" is trying to access some resource in "graph" folder then deny access. You can use * which means all and ? which means unauthenticated users or anonymous users. Also you can restrict users based on their roles also. The roles can be mentioned in the role tags. When one is using * in allow tag care should be taken to put the deny tag before the allow tag else the denial will not work as you want. E.g.
 <location path="graph">
     <system.web>
          <authorization>
               <allow users="*"/>
               <deny users="user5"/>
          </authorization>
     </system.web>
</location>
The above statement will allow user with identity "user5" to access the resources within graph folder. The reason which I think why this is happening is once ASP.NET comes across * symbol it is by default allowing everyone whether the user is in the denied list. If the above restriction has to work correctly then one has to put the deny tag before the allow tag as shown below.
 <location path="graph">
     <system.web>
          <authorization>
               <deny users="user5"/>
               <allow users="*"/>
          </authorization>
     </system.web>
</location>
Restricting access based on roles
Sometimes you would like to allow access to resources based on user’s roles. To allow access based on an user’s roles put the following tag in web.config.
 

<location path="AdminFolder">
     <system.web>
          <authorization>               
               <allow roles="admin, superadmin"/>
          </authorization>
     </system.web>
</location>

The above tag will allow access to the “AdminFolder” to users who belong to either the “admin” or “superadmin” role. To add roles to a logged in user, place the following code in authentication routine of your system.
 

//After validating the user create an authentication ticket. 
FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1, "[USERNAME]", DateTime.Now, DateTime.Now.AddMinutes(15), false, "[ROLE]"); 
FormsIdentity fi = new FormsIdentity(fat); 
/*get the roles from the database and assign the string values to the GenericPrincipal.The second argument of GenericPrincipal takes a string array of roles.  */
System.Security.Principal.GenericPrincipal gp = new System.Security.Principal.GenericPrincipal(fi, new  string [] {"Manager", "admin"}); 
HttpContext.Current.User = gp;

In the above code once the user is successfully validated against a database we are creating a FormsIdentity object using the FormsAuthentication ticket object. Once that is done we are creating a GenericPrincipal object and passing the FormsIdentity and the roles of the user as a string array. One can retrieve the roles from the database and populate the same in a string array and can pass the same as argument.
To be Continued.....

Know more.

Sandeep

Sunday, June 8, 2008

ASP.NET View State

What is a view state?
View state in simple terms can be defined as a way to maintain the state of an aspx page during postbacks. And this is the no 1 one liner answer I get from candidates during interviews. Viewstate is a technique which helps in retaining the values of the controls placed in a page during postback/roundtrip. With this blog, again, my aim is the same, to spread more light on what is view state all about.
What do you mean by state of an aspx page?
The state of an aspx page means the values of the controls in an aspx page. By default the view state is maintained for all the controls which are placed in an aspx page. The state of a control can be the text entered in a text box, the checked status of a radio button or check box, the content and selected item in a drop down control etc.

Where is view state stored?
View state is stored in the client in the form of a hidden control called “__VIEWSTATE”. Here by client I mean the rendered aspx pages in the browser. If view state property is set to true then ASP.NET automatically adds a hidden field/control by the name “__VIEWSTATE” and stores the information related to the state of the page in an encrypted format.

What is the encoding used in view state?
View state is stored in base64 format. The base64 format can generate huge amount of data on conversion and this is the reason we are adviced to use view state judiciously.

Which class handles view state?
StateBag class handles the view state and it implements a Dictionary to keep track of the changes in a form. The developer can add or remove items from this dictionary as you would from any dictionary object. You can access this class through the Control.ViewState property.

Can view state be stored in multiple hidden fields?
Yes, view state can be stored in multiple hidden fields. This can be achieved by setting the page’ “MaxPageStateFieldLength” property. If the property is set to a positive value then the view state is broken and sent to the client in multiple hidden field and each field’ size will be less than the value spedified in “MaxPageStateFieldLength”.

How to disable view state?
View state can be disabled in the following ways.
1. In machine.config – you can disable view state for all the application hosted in the server by modifying the following tag in machine.config as shown below.

<pages enableviewstatemac="true" enableviewstate="false">

2. Application/website level - if you want to disable view state for all the pages in your application then you can do that in web.config file as shown below.

<system.web>

<pages enableviewstate="false">

</system.web>

3. Page level – you can use this option to switch off the view state for all the controls in a web page by setting the “EnableViewState” page attribute to false as shown below.

<%@ Page EnableViewState="false" ... %>

4. Control level - you can switch off a control’ view state by setting the EnableViewState property of the control to false from property window or as shown below.

<asp:label id="”Label1”" enableviewstate="false" runat="”server">

Hope the above details give a clearer picture on what view state is. There is more to view state than what is written here.

Sunday, May 11, 2008

Implementing Two interface having the same method signature in the same class

There can be scenario when we would have two interface with the same method name and same type of arguments, same number of arguments and even the return type can be same and we need to implement both the interface in the same class. How to implement the interface in our class? Most of you will be thinking whats so tough in this, just implement the interface and the method and move on. If the signature of the methods in the interface were different then there would have been no problem but here the signature of the methods in two different interface are same and both the interfaces are gonna be implemented in the same class. The two interface are as below.
public interface IA
{
string PrintName();
}
public interface IB
{
string PrintName();
}

From the above code we can infer that we have two interface with names IA and IB and both have a single method named “PrintName”. The signature of both the methods are same and we need to implement the interfaces in our class say “A”. One way of impelementing the interface is as shown below i.e. just having a “public” implementation of the interface method only once.
public class A : IA, IB
{
public A()
{
}
public string PrintName()
{
return this.GetType().Name;
}
}

The above implementation has got a limitation i.e the method “PrintName” is considered to be a common method for all i.e commong method for the class, and for the interfaces IA and IB. If you are writing a code shown below
A a = new A();
IA ia = new A();
IB ib = new A();
Console.WriteLine(a.PrintName());
Console.WriteLine(ia.PrintName());
Console.WriteLine(ib.PrintName());

all the calls to method “PrintName” will give you the same result, the name of the class i.e. “A”. This is because all call to the method goes to the same definition. Now if you want to give different implementation to the methods in interface IA and IB, what will you do? Its also simple, just have two impelementation of the same method and prefix the method names with the interface name as shown below.
public class A : IA, IB
{
public A()
{
}
string IA.PrintName()
{
return “IA PrintName Method”;
}
string IB.PrintName()
{
return “IB PrintName Method”;
}
}

Now the below code will give you different output.
IA ia = new A();
IB ib = new A();
Console.WriteLine(ia.PrintName());
// Will print "IA PrintName Method"
Console.WriteLine(ib.PrintName());// Will print "IB PrintName Method"
So this is how two interfaces having the same method signature can be given different implementation in the same class.

Sunday, March 9, 2008

Methods in Global.asax

This blog is intended to spread some light on the various methods which are available in global.asax file in ASP.NET. It’s very important to understand the methods in global.asax so that we as programmers can handle some application level events very efficiently. I said application level events and reason for using application word is that global.asax is an application level file and methods in it are used to handle application level events and these methods are not at all specific to any aspx page. Some of the common methods in the order in which they are executed are listed below

  • Application_Start
  • Application_BeginRequest
  • Application_AuthenticateRequest
  • Session_Start
  • Application_EndRequest
  • Session_End
  • Application_End
  • Application_Error

Now let’s see what is the major difference between these methods or events. Oh I forgot to say, these are actually events not methods which get raised when a particular event gets triggered. Before we see the various methods in Global.asax I would like to tell you that Global.asax is actually derived from a class called “HttpApplication”. The above listed methods are only a few methods which I am gonna talk about. The listing of other methods can be found at the end of the blog. Now lets see the above mentioned events one by one.


Application_Start
Application_Start event gets triggered only once during the life cycle of the application. This once happens when the first request for any resource in the application comes. Resource can be a page or an image in the application. When the very first request for a resource, say a web page, is made by a user “Application_Start” is triggered after which this event is not at all executed. If by any chance the server where the application is hosted is restarted then this event is fired once again i.e. when the very first request for any resource in the application is made after the server is reset.


Application_BeginRequest
“Application_BeginRequest” is the second event which gets fired after “Application_Start”. Unlike the “Application_Start”, “Application_BeginRequest” is triggered for each and every request which comes to the application. Since this method is fired for any request made to the application you can use this method to keep track of what and all resources are accessed through this method.


Application_AuthenticateRequest
“Application_AuthenticateRequest” is the next event in line which is triggered after “Application_BeginRequest” is triggered. “Application_AuthenticateRequest” is also fired for each and every request. This event can be used to write code in scenarios where you want to do something when the user is getting authenticated.


Session_Start
The next event in line which gets triggered after “Application_AuthenticateRequest” is “Session_Start”. Session start event is fired only when a new session for a user starts. Once “Session_Start” for a user is fired then if the user makes subsequent request to any resource within the application this event is not at all triggered. The event is triggered only when the user’s session expires and then the user tries to access any resource in the application again.
This event can be used when you want to do something when the user visits you site/application for the first time or when his session starts. This event doesn’t get triggered if you are not using sessions which can be disabled in the web.config.


Application_EndRequest
The next event in line which gets fired once the request for the user is processed is “Applicatin_EndRequest”. This event is the closing event of “Applicatin_BeginRequest”. This event is also fired for each and every request which comes for the application.


Session_End
The closing event of “Session_Start” event. Whenever a user’s session in the application expires this event gets fired. So anything you want to do when the user’s session expires you can write codes here. The session expiration time can be set in web.config file. By default session time out is set to 20 mins.


Application_End
The same as “Application_Start”, “Application_End” is executed only once, when the application is unloaded. This event is the end event of “Application_Start”. This event is normally fired when the application is taken offline or when the server is stopped.


Application_Error
Now we come to the last event mentioned in this blog and that is “Application_Error”. This event gets fired when any unhandled exception/error occurs anywhere in the application. Any unhandled here means exception which are not caught using try catch block. Also if you have custom errors enabled in your application i.e. in web.config file then the configuration in web.config takes precedence and all errors will be directed to the file mentioned in the tag.

Lets see with an e.g. how these events get fired.
Suppose “A”, “B” and “C” are users who are going to access a site named “My Site”. “A” is the very first user to visit “My Site” and he/she is accessing “productlist.aspx” page. At this time the flow of the request is as follows. The “Application_Start” event is triggered, since “A” is the very first user to visit the application, after this “Application_BeginRequest”, then “Application_AuthenticateRequest”, then “Session_Start”, “productlist.aspx” page level events are processed and then “Application_EndRequest” event is triggered. After accessing “productlist.aspx” if “A” access some other page then for those page request the flow will be first “Application_BeginRequest”, “Application_AuthenticateRequest” then the page processing (page level events) and then “Application_EndRequest”. For every subsequent request this pattern is followed.


When “B” accesses some resource in the site, say “default.aspx”, then first “Applicatin_BeginRequest”, second “Application_AuthenticateRequest”, third “Session_Start” then “default.aspx” page level events are executed and after that “Application_EndRequest” is executed. After accessing “default.aspx” “B” access “productlist.aspx” then first “Application_BeginRequest”, second “Application_AuthenticateRequest” then “productlist.aspx” and then “Application_EndRequest” event is triggered. He refreshes the page the same events are executed in the same order.

The above same process is repeated for “C” also.

Suppose you have an unhandled exception and you don’t have custom errors enabled in web.config then when a user accesses a resource the flow will be first “Application_BeginRequest”, “Application_AuthenticateRequest”, page level event and an error occurs in the page then it goes to “Application_Error” after that “Application_EndRequest”.
The order mentioned above is how the events are triggered. So with this I hope you would have got a clear idea on how these events are triggered.

Some other events which are part of the HttpApplication class are as follows

  • PostAuthenticateRequest
  • AuthorizeRequest
  • PostAuthorizeRequest
  • ResolveRequestCache
  • PostResolveRequestCache
  • PostMapRequestHandler
  • AcquireRequestState
  • PostAcquireRequestState
  • PreRequestHandlerExecute
  • PostRequestHandlerExecute
  • ReleaseRequestState
  • PostReleaseRequestState
  • UpdateRequestCache
  • PostUpdateRequestCache
  • LogRequest. (Supported in IIS 7.0 only.)
  • PostLogRequest (Supported in IIS 7.0 only.)

Sunday, February 10, 2008

Static Constructors in .NET

What is a static constructor?

As part of my job I conduct technical interviews for my company. Till date I have conducted more 500 interviews and one of the stock question in my interview is can constructors be declared static? Most of the time I get a blunt, no, as the answer. Even some argue that one cannot use the static word along with constructors. A very few who say yes are asked further questions on static constructors like what is the difference between a static constructors and normal constructors? For this also I have got lots of answers like static constructors can be called without creating an object, only static variables can be use etc. Some say static constructors are called only once and when I ask when is that once, People don’t have an answer. So I thought I will try to clear some confusion related to static constructors. To know more read on…

Can constructors be declared Static?

Yes.

What is the difference between a static constructor and normal constructors?

As we know Normal constructors are used to initialize class variables whereas static constructors are used to initialize class level static variables. Static constructors cannot access any other objects other than static as similar to static methods. Similar to static method, static constructors are class level and not instance level. Static constructors do not take any access modifiers, like public, private, protected etc. They also don’t take any arguments. Static constructors are called only once.

Static constructors are called only once, when is that once?

Static constructors are called only once throughout the life time of the program, i.e. when the first instance of the class having static constructors is created or when a static member is accessed/used whichever happens first.

Let me explain further, suppose you have a class called StaticConstructor with a static constructor as shown below.

using System;
namespace StaticConstructorDemo
{
class StaticConstructor
{
private static string someText;
private static int counter;
static StaticConstructor()
{
someText = "Static constructor executed. No of times: ";
counter++;
}
public static void PrintSomeText()
{
Console.WriteLine(someText + counter.ToString());
}
}

class MainClass
{
static void Main(string[] args)
{
StaticConstructor sc1 = new StaticConstructor();
StaticConstructor sc2 = new StaticConstructor();
StaticConstructor sc3 = new StaticConstructor();
StaticConstructor.PrintSomeText();
}
}
}

The above code will print “Static constructor executed. No of times: 1”. The reason is static constructor is called only once when the first instance for the class is created i.e. when sc1 is created.

If the above code inside the main method is rewritten like this

class MainClass
{
static void Main(string[] args)
{
StaticConstructor.PrintSomeText();
StaticConstructor sc1 = new StaticConstructor();
StaticConstructor sc2 = new StaticConstructor();
StaticConstructor sc3 = new StaticConstructor();
}
}


The above code will have the same output as the previous code i.e. “Static constructor executed. No of times: 1”. Static constructor is called before the code inside the static method, PrintSomeText(), is executed. As we know static methods can use static members and if a static constructor is not executed then there is every possibility of the system throwing “object reference not set to an instance” error. So static constructors are called before the first instance of the class is created or any static members are accessed/used.

Hope from the above e.g. gives a clear idea. If for any doubt please do post comments.