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.

Friday, February 8, 2008

HttpHandler in ASP.NET

Sometimes as ASP.NET developers we might have come across situations where we had to implement some custom security to files, of type doc, pdf, excel, jpg etc. I also had the same prob, in my case it was restricting access to jpg files. The reason for this was that the jpg files were graphs and these graphs contained sensitive business data which were not to be shared freely. The files had to be restricted not only based on the user’s role but also based on their login id. So how can I achieve this in asp.net? My problem had an easy solution, by making use of the location tag in web.config file I could give restricted access to the folder which contained graph images based on the user’s role or id. The sample tag is shown below.

But this solution wont work in my case, the reason being the charts are generated on the fly by the system based on dynamic data retrieved from the database and the security is also dynamic and can change often. The users of the system are allowed to apply security based on thier preference. Some images can have role based and some can have id based security. It will be disastrous to ask the customer to modify the web.config file manually and that also for each and every graph image generated. Any syntax error can take the whole site down. So what was the other solution?

The logic to check what kind of access a user has was successfully completed. But our problem was to restrict user’ from directly accessing the jpg images. As we all know if the user saves the jpg image url and pastes the same in the browser’ address bar he can very well view the image. We had to prevent the user from accessing images by directly pasting the url in the address bar of the browser. Even if he pastes the link he should be directed to the login page and should go through the normal authentication process and if he has rights to view the image then he should be able to view the image. So, how to achieve this? Any request to any jpg images in a particular folder should be processed by asp.net. Then after much research we found the solution, this can be achieved using HttpHandler.

What is HttpHandler?

Each and every extensions like aspx, asmx etc are processed by different HttpHandlers in asp.net. All aspx page requests are handled by the ASP.NET Page Handler (PageHandlerFactory) class, all asmx i.e. web services are handled by Web Service Handler(WebServiceHandlerFactory) class. HttpHander is a build in process which takes care of processing requests based on their extension (type) and produce output. In the case of .aspx files the ASP.NET Page Handler processes the request and converts the whole page into html tags and sends back to the browser. I think the story upto this is enough and everyone will be waiting for the main implementation. To implement HttpHandler you should do three things.

1. Extend the IHttpHandler interface and implement the same in your project.
2. Register the file extension using iis filters.
3. Create a web.config file having httpHandler tag and place the file in the directory where you want the images to be handled.

1. Extend the IHttpHandler interface and implement the same in your project.

The first step is to extend the IHttpHandler interface which will process the jpg extensions. IHttpHandler interface has one method and one property namely "ProcessRequest" and “IsReusable" respectively. The ProcessRequest method is the one where you have to implement your image processing logic. The code below shows a sample implementation.

using System;
using System.Data;
using System.Configuration;
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;

public class ImageHandler : IHttpHandler
{
    public ImageHandler()
    {
    }
    /* The overridden method to handle requests for jpg images.*/
    public void ProcessRequest(HttpContext     theContext)
    {
        ProcessGraphRequest(theContext);
    }
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

As you can see from the above code we are invoking another user defined function called “ProcessGraphRequest” where we have the logic for checking image access based on the user’s privileges. Inside the function if the logic evaluates and says the user has got rights to view the graph we will implement the following code. The logic evaluates and stores the result in a boolean variable called “hasGraphAccess”.

private void ProcessImageRequest(HttpContext theContext)
{
  /*Logic to ascertain whether the user has access to graph files or not goes here*/
    if (hasGraphAccess)//Boolean variable to check image access.
    {
        theContext.Response.WriteFile            (theContext.Request.PhysicalPath);
    }
    else
    {
        theContext.Response.Write("Sorry you don’t have access to view the image.");
    }
}

2. Register the file extension using iis filters.

Once the HTTPHandler class is implemented the next step is to register the file extension. Open IIS (type inetmgr in run/command window) and navigate to the virtual directory where you want to implement your custom HttpHandler class. Right click and open the properties window. Click on the “configuration” button in the “Virtual Directory” tab as shown in the figure below.

In the “Mappings” tab of the “Application configuration” window click the “Add” button.

In the “Add/Edit Application Extension Mapping” pop up window enter the extension, in this case “jpg”, in the “Extension” textbox. In the “Executable” text box paste the path for the aspnet_isappi.dll which processes the request for aspx, asmx etc. Check “All Verbs” radio button which means you are asking the aspnet_isappi.dll to process all the request irrespective of the method of their post back i.e. get, post etc. The screenshot with all the details filled is shown below.

3. web.config having the extension mapping.

In this step there is not much to do, one has to create a web.config file using any text editor and put the following lines of xml statement in the web.config and save it in the folder where you want to provide the security.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.web>
        <httpHandlers>
            <add verb="*" path="*.jpg" type="HttpHandlerWebsite.ImageHandler, App_Code"/>
        </httpHandlers>
    </system.web>
</configuration>

The explanation for the various httpHandler attributes is as follows

Attribute
Explanation
E.g.
verb What type of request you want to process i.e. POST, GET, PUT etc. You can enter a comma separated value (verb=”GET,POST”) or simply type “*” which means process all types of request. verb="GET,POST” OR verb="*”
Path The path attribute can contain a single url (will directly point to a file) or some wildcard string. path="*.jpg”
type The class name with full namespace specification and the assembly where to look for the HTTPHandler class. The value of the type attribute will be a comma separated one having the class name with namespace and the assembly name separated by a comma. type=”HttpHandlerWebsite.ImageHandler, App_Code

In case of .net 1.1 the above web.config will change to the following

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.web>
        <httpHandlers>
            <add verb="*" path="*.jpg" type="HttpHandlerWebsite.ImageHandler, HttpHandlerWebsite"/>
        </httpHandlers>
    </system.web>
</configuration>

The reason for this is that in .NET 2.0 and above versions all ASP.NET related files are compiled and put into appcode.dll file where as in .NET 1.1 it is clubbed into a dll having the same name as that of the ASP.NET solution/website.

Know more

Sandeep