ASP.NET Ajax Under-the-hood Secrets


ASP.net Ajax under the hood secrets

Introduction

Microsoft ASP.NET Ajax is a very powerful Ajax framework. However, when you build a real Ajax site like those out there in the Web 2.0 world, you face many problems that you will hardly find documented anywhere. In this article, I will show some advance-level ideas that I learned while building Pageflakes. We will look at the advantages and disadvantages of Batch calls, Ajax call timeouts, browser call jam problems, ASP.NET 2.0’s bug in web service response caching, and so on.

Why Use ASP.NET Ajax

When others see Pageflakes, the first question they ask me is, “Why did you not use Protopage or Dojo library? Why Atlas?” Microsoft Atlas (renamed to ASP.NET Ajax) is a very promising Ajax framework. They are putting a lot of effort into it, making lots of reusable components that can really save you a lot of time and give your web application a complete face lift at reasonably low effort or change. It integrates with ASP.NET very well and is compatible with the ASP.NET Membership and Profile provider. The Ajax Control Toolkit project contains 28 extenders that you can drag & drop onto your page, tweak some properties and add pretty cool effects on the page. Check out the examples to see how powerful the ASP.NET Ajax framework has really become.

When we first started developing Pageflakes, Atlas was in infancy. We were only able to use the page method and Web Service method call features of Atlas. We had to make our own drag & drop, component architecture, pop-ups, collapse/expand features, etc. Now, however, you can have all these from Atlas and thus save a lot of development time. The web service proxy feature of Atlas is a marvel. You can point a <script> tag to an *.asmx file and get a JavaScript class generated right out of the web service definition.

The JavaScript class contains the exact methods that you have on the web service class. This makes it really easy to add/remove new web services and add/remove methods in web services that do not require any changes on the client side. It also offers a lot of control over the Ajax calls and provides rich exception trapping features on the JavaScript. Server side exceptions are nicely thrown to the client side JavaScript code, and you can trap them and show nicely formatted error messages to the user. Atlas works really well with ASP.NET 2.0, eliminating the integration problem completely. You need not worry about authentication and authorization on page methods and web service methods. You thus save a lot of code on the client side — of course, the Atlas Runtime is huge for this reason — and you can concentrate more on your own code than on building up all this framework-related code.

The recent version of Atlas works nicely with ASP.NET Membership and Profile services, giving you login/logout features from JavaScript without requiring page post-backs. You can read/write Profile objects directly from JavaScript. This comes in very handy when you heavily use ASP.NET Membership and Profile providers in your web application, which we do at Pageflakes.

On earlier versions of Atlas, there was no way to make HTTP GET calls. All calls were HTTP POST and were thus quite expensive calls. Now you can say which calls should be HTTP GET. Once you have HTTP GET, you can utilize HTTP response caching features, which I will show you soon.

Batch Calls Are Not Always Faster

ASP.NET Ajax had a feature in the CTP release (and previous releases) that allowed batching of multiple requests into one request. It worked transparently, so you wouldn’t notice anything, nor would you need to write any special code. Once you turned on the Batch feature, all web service calls made within a duration got batched into one call. Thus, it saved round-trip time and total response time.

The actual response time might be reduced, but the perceived delay is higher. If three web service calls are batched, the first call does not finish first. If you are doing some UI updates, all three calls finish at the same time, upon completion of each WS call; it does not happen one-by-one. All of the calls complete in one shot and then the UI gets updated in one shot.

As a result, you do not see incremental updates on the UI. Instead, you see a long delay before the UI updates. If any of the calls — say the third call — downloads a lot of data, the user sees nothing happening until all three calls complete. So, the duration of the first call becomes nearly the duration of the sum of all three calls. Although the actual total duration is reduced, the perceived duration is higher. Batch calls are handy when each call is transmitting a small amount of data. Thus, three small calls get executed in one round trip.

Let’s work on a scenario where three calls are made one-by-one. Here’s how the calls actually get executed.

The second call takes a little bit of time to reach the server because the first call is eating up the bandwidth. For the same reason, it takes longer to download. Browsers open two simultaneous connections to the server so, at a time, only two calls are made. Once the second/first call completes, the third call is made. When these three calls are batched into one:

Here the total download time is reduced (if IIS compression is enabled) and there’s only one network latency overhead. All three calls get executed on the server in one shot and the combined response is downloaded in one call. To the user, however, the perceived speed is slower because all the UI updates happen after the entire batch call completes. The total duration the batch call will take to complete will always be higher than that for two calls. Moreover, if you do a lot of UI updates one after another, Internet Explorer freezes for awhile, giving the user a bad impression. Sometimes, expensive updates on the UI make the browser screen go blank and white. Firefox and Opera do not have this problem.

Batch calls have some advantages, too. The total download time is less than that for downloading individual call responses because if you use gzip compression in IIS, the total result is compressed instead of individually compressing each result. So, generally, a batch call is better for small calls. However, if a call is going to send a large amount of data or is going to return, say, 20 KB of response, then it’s better not to use batch. Another problem with batch calls occurs when, say, two calls are very small but the third call is quite big. If these three calls get batched, the smaller calls are going to suffer from the long delay due to the third larger call.

Bad Calls Make Good Calls Time Out

If two HTTP calls somehow get stuck for too long, those two bad calls are going to make some good calls expire too, which in the meantime got queued. Here’s a nice example:

Collapse | Copy Code
function TestTimeout()
{
    debug.trace("--Start--");
    TestService.set_defaultFailedCallback( 
            function(result, userContext, methodName)
    {
        var timedOut = result.get_timedOut();
        if( timedOut )
            debug.trace( "Timedout: " + methodName );
        else
            debug.trace( "Error: " + methodName );
    });
    TestService.set_defaultSucceededCallback( function(result)
    {
        debug.trace( result );
    });
    
    TestService.set_timeout(5000);
    TestService.HelloWorld("Call 1");
    TestService.Timeout("Call 2");
    TestService.Timeout("Call 3");
    TestService.HelloWorld("Call 4");
    TestService.HelloWorld("Call 5");
    TestService.HelloWorld(null); // This one will produce Error

}

On the server side, the web service is very simple:

Collapse | Copy Code
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class TestService : System.Web.Services.WebService {

    public TestService () {

        //Uncomment the following line if using designed components 

        //InitializeComponent(); 

    }

    [WebMethod][ScriptMethod(UseHttpGet=true)]
    public string HelloWorld(string param) {
        Thread.Sleep(1000);
        return param;
    }
    
    [WebMethod][ScriptMethod(UseHttpGet=true)]
    public string Timeout(string param) {
        Thread.Sleep(10000);
        return param;
    }
}

I am calling a method named Timeout on the server which does nothing but wait for a long time so that the call gets timed out. After that, I am calling a method which does not time out. Guess what the output is:

Only the first call succeeded. So, if at any moment the browser’s two connections get jammed, then you can expect that other waiting calls are going to time out as well. In Pageflakes, we used to get nearly 400 to 600 timeout error reports from users’ browsers. We could never figure out how this could happen. First, we suspected slow internet connections, but that cannot happen for so many users. Then we suspected something was wrong with the hosting provider’s network. We did a lot of network analysis to find out whether there were any problems on the network or not, but we could not detect any.

We used SQL Profiler to see whether there were any long-running queries that timed out the ASP.NET request execution time, but no luck. We finally discovered that it mostly happened due to some bad calls which got stuck and made the good calls expire, too. So, we modified the Atlas Runtime and introduced automatic retry on it, and the problem disappeared completely. However, this auto-retry requires a sophisticated open heart bypass surgery on the ASP.NET Ajax framework JavaScript. The idea is to make each and every call retry once when it times out. In order to do that, we need to intercept all web method calls and implement a hook on the onFailed call-back, which will call the same web method again if the failure reason was a timeout.

Another interesting discovery we made while we were traveling was that whenever we tried to visit Pageflakes from a hotel or an airport wireless internet connection, the first visit always failed and all the web service calls on first attempt always failed. Until we did a refresh, nothing worked. This was another major reason why we implemented immediate auto-retry of web service calls, which fixed the problem.

Here’s how to do it. The Sys$Net$WebServiceProxy$invoke function is responsible for making all Web Service calls. So, we replace this function with a custom implementation that passes a custom onFailure call-back. That custom call-back gets fired whenever there’s an error or timeout. So, when there’s a timeout, it calls the this function again and thus a retry happens.

Collapse | Copy Code
Sys.Net.WebServiceProxy.retryOnFailure = 
    function(result, userContext, methodName, retryParams, onFailure)
{
    if( result.get_timedOut() )
    {
        if( typeof retryParams != "undefined" )
        {
            debug.trace("Retry: " + methodName);
            Sys.Net.WebServiceProxy.original_invoke.apply(this, retryParams );
        }
        else
        {
            if( onFailure ) onFailure(result, userContext, methodName);
        }
    }
    else
    {
        if( onFailure ) onFailure(result, userContext, methodName);
    }
}

Sys.Net.WebServiceProxy.original_invoke = Sys.Net.WebServiceProxy.invoke;
Sys.Net.WebServiceProxy.invoke = 
    function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, 
        params, onSuccess, onFailure, userContext, timeout)
{   
    var retryParams = [ servicePath, methodName, useGet, params, 
        onSuccess, onFailure, userContext, timeout ];
    
    // Call original invoke but with a new onFailure

    // handler which does the auto retry

    var newOnFailure = Function.createDelegate( this, 
        function(result, userContext, methodName) 
        { 
            Sys.Net.WebServiceProxy.retryOnFailure(result, userContext, 
                methodName, retryParams, onFailure); 
        } );
        
    Sys.Net.WebServiceProxy.original_invoke(servicePath, methodName, useGet, 
        params, onSuccess, newOnFailure, userContext, timeout);
}

When run, it will retry each timed-out call once.

Here you see that the first method succeeded and all the others timed out and retried. However, you will see that after a retry, they all succeeded. This happened because server side methods do not time out on retry. So, this proves that our implementation is correct.

Browsers Allow Two Calls at a Time and Don’t Expect any Order

Browsers make two concurrent Ajax calls at a time to a domain. If you make five Ajax calls, the browser is going to make two calls first and then wait for any one of them to complete. Then it makes another call until all four remaining calls are complete. Moreover, you cannot expect calls to execute in the same order as you make the calls. Here’s why:

Here you see that call 3’s response download is quite big, and thus takes longer than call 5. So, call 5 actually gets executed before call 3. The world of HTTP is unpredictable.

Browsers Do Not Respond when More Than Two Calls Are in Queue

Try this: go to any start page in the world that will load a lot of RSS on the first visit (e.g. Pageflakes, Netvibes, Protopage) and, while loading, try to click on a link that will take you to another site or try to visit another site. You will see that the browser is stuck. Until all queued Ajax calls in the browser complete, the browser will not accept any other activity. This is worst in Internet Explorer; Firefox and Opera do not have this much of a problem.

The problem is that when you make a lot of Ajax calls, the browser keeps all calls in a queue and executes two at a time. So, if you click on something or try to navigate to another site, the browser has to wait for running calls to complete before it can take another call. The solution to this problem is to prevent more than two calls from being queued in the browser at a time. We need to maintain a queue ourselves and send calls to the browser’s queue from our queue on-by-one. The solution is quite shocking; brace for impact:

Collapse | Copy Code
var GlobalCallQueue = {
    _callQueue : [],    // Maintains the list of webmethods to call

    _callInProgress : 0,    // Number of calls currently in progress by browser

    _maxConcurrentCall : 2, // Max number of calls to execute at a time

    _delayBetweenCalls : 50, // Delay between execution of calls 

    call : function(servicePath, methodName, useGet, 
        params, onSuccess, onFailure, userContext, timeout)
    {
        var queuedCall = new QueuedCall(servicePath, methodName, useGet, 
            params, onSuccess, onFailure, userContext, timeout);

        Array.add(GlobalCallQueue._callQueue,queuedCall);
        GlobalCallQueue.run();
    },
    run : function()
    {
        /// Execute a call from the call queue

        
        if( 0 == GlobalCallQueue._callQueue.length ) return;
        if( GlobalCallQueue._callInProgress < 
            GlobalCallQueue._maxConcurrentCall )
        {
            GlobalCallQueue._callInProgress ++;
            // Get the first call queued

            var queuedCall = GlobalCallQueue._callQueue[0];
            Array.removeAt( GlobalCallQueue._callQueue, 0 );
            
            // Call the web method

            queuedCall.execute();
        }
        else
        {
            // cannot run another call. Maximum concurrent 

            // webservice method call in progress

        }            
    },
    callComplete : function()
    {
        GlobalCallQueue._callInProgress --;
        GlobalCallQueue.run();
    }
};

QueuedCall = function( servicePath, methodName, useGet, params, 
    onSuccess, onFailure, userContext, timeout )
{
    this._servicePath = servicePath;
    this._methodName = methodName;
    this._useGet = useGet;
    this._params = params;
    
    this._onSuccess = onSuccess;
    this._onFailure = onFailure;
    this._userContext = userContext;
    this._timeout = timeout;
}

QueuedCall.prototype = 
{
    execute : function()
    {
        Sys.Net.WebServiceProxy.original_invoke( 
            this._servicePath, this._methodName, this._useGet, this._params,  
            Function.createDelegate(this, this.onSuccess), // Handle call complete

            Function.createDelegate(this, this.onFailure), // Handle call complete

            this._userContext, this._timeout );
    },
    onSuccess : function(result, userContext, methodName)
    {
        this._onSuccess(result, userContext, methodName);
        GlobalCallQueue.callComplete();            
    },        
    onFailure : function(result, userContext, methodName)
    {
        this._onFailure(result, userContext, methodName);
        GlobalCallQueue.callComplete();            
    }        
};

QueuedCall encapsulates one web method call. It takes all the parameters of the actual web service call and overrides the onSuccess and onFailure call-backs. We want to know when a call completes or fails so that we can issue another call from our queue. GlobalCallQueue maintains the list of all web service calls. Whenever a web method is called, we first queue the call in the GlobalCallQueue and execute calls from the queue one-by-one ourselves. It ensures that the browser does not get more than 2 web service calls at a time and thus the browser does not get stuck. In order to enable the queue-based call, we need to override the ASP.NET Ajax web method invocation again, as we did before.

Collapse | Copy Code
Sys.Net.WebServiceProxy.original_invoke = Sys.Net.WebServiceProxy.invoke;
Sys.Net.WebServiceProxy.invoke = 
    function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, 
        useGet, params, onSuccess, onFailure, userContext, timeout)
{   
    GlobalCallQueue.call(servicePath, methodName, useGet, params, 
        onSuccess, onFailure, userContext, timeout);
}

Caching Web Service Response on the Browser and Saving Bandwidth Significantly

Browsers can cache images, JavaScript and CSS files on a user’s hard drive, and they can also cache XML HTTP calls if the calls are HTTP GET. The cache is based on the URL. If it’s the same URL and it’s cached on the computer, then the response is loaded from the cache and not from the server when it is requested again. Basically, the browser can cache any HTTP GET call and return cached data based on the URL. If you make an XML HTTP call as HTTP GET and the server returns some special header that informs the browser to cache the response, on future calls, the response will be immediately returned from the cache. This saves the delay of network round trip and download time.

At Pageflakes, we cache the user’s state so that when the user visits again the following day, the user gets a cached page that loads instantly from the browser cache, not from the server. Thus, the second-time load becomes very fast. We also cache several small parts of the page that appear on users’ actions. When the user does the same action again, a cached result is loaded immediately from the local cache, which saves on the network round trip time. The user gets a fast-loading site and a very responsive site. The perceived speed increases dramatically.

The idea is to make HTTP GET calls while making Atlas web service calls and return some specific HTTP Response headers that tell the browser to cache the response for some specific duration. If you return the Expires header during the response, the browser will cache the XML HTTP response. There are two headers that you need to return with the response, which will instruct the browser to cache the response:

Collapse | Copy Code
HTTP/1.1 200 OK 
Expires: Fri, 1 Jan 2030 
Cache-Control: public

This will instruct the browser to cache the response until January, 2030. As long as you make the same XML HTTP call with the same parameters, you will get a cached response from the computer and no call will go to the server. There are more advanced ways to get further control over response caching. For example, here is a header that will instruct the browser to cache for 60 seconds, but not contact the server and get a fresh response after 60 seconds. It will also prevent proxies from returning cached responses when the browser local cache expires after 60 seconds.

Collapse | Copy Code
HTTP/1.1 200 OK 
Cache-Control: private, must-revalidate, proxy-revalidate, max-age=60

Let’s try to produce such response headers from an ASP.NET web service call:

Collapse | Copy Code
[WebMethod][ScriptMethod(UseHttpGet=true)]
public string CachedGet()
{
    TimeSpan cacheDuration = TimeSpan.FromMinutes(1);
    Context.Response.Cache.SetCacheability(HttpCacheability.Public);
    Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
    Context.Response.Cache.SetMaxAge(cacheDuration);
    Context.Response.Cache.AppendCacheExtension(
           "must-revalidate, proxy-revalidate");

    return DateTime.Now.ToString();
}

This will result in the following response headers:

The Expires header is set properly, but the problem is with the Cache control. It is showing that max-age is set to zero, which will prevent the browser from doing any kind of caching. If you seriously want to prevent caching, you should emit such a cache-control header. It looks like exactly the opposite thing happened. The output is, as usual, incorrect and not cached:

There’s a bug in ASP.NET 2.0 where you cannot change the max-age header. As max-age is set to zero, ASP.NET 2.0 sets the Cache control to private because max-age = 0 means that no cache is needed. There’s no way you can make ASP.NET 2.0 return proper headers that cache the response. Time for a hack. After decompiling the code of the HttpCachePolicy class (the Context.Response.Cache object’s class), I found the following code:

Somehow, this._maxAge is getting set to zero and the check “if (!this._isMaxAgeSet || (delta < this._maxAge))” is preventing it from getting set to a bigger value. Due to this problem, we need to bypass the SetMaxAge function and set the value of the _maxAge field directly, using Reflection.

Collapse | Copy Code
[WebMethod][ScriptMethod(UseHttpGet=true)]
public string CachedGet2()
{
    TimeSpan cacheDuration = TimeSpan.FromMinutes(1);

    FieldInfo maxAge = Context.Response.Cache.GetType().GetField("_maxAge", 
        BindingFlags.Instance|BindingFlags.NonPublic);
    maxAge.SetValue(Context.Response.Cache, cacheDuration);

    Context.Response.Cache.SetCacheability(HttpCacheability.Public);
    Context.Response.Cache.SetExpires(DateTime.Now.Add(cacheDuration));
    Context.Response.Cache.AppendCacheExtension(
            "must-revalidate, proxy-revalidate");

    return DateTime.Now.ToString();
}

This will return the following headers:

Now max-age is set to 60 and thus the browser will cache the response for 60 seconds. If you make the same call again within 60 seconds, it will return the same response. Here’s a test output that shows the date time returned from the server:

After 1 minute, the cache expires and the browser makes a call to the server again. The client-side code is like this:

Collapse | Copy Code
function testCache()
{
    TestService.CachedGet(function(result)
    {
        debug.trace(result);
    });
}

There’s another problem to solve. In web.config, you will see ASP.NET Ajax adding:

Collapse | Copy Code
        <system.web>
        <trust level="Medium"/>

This prevents us from setting the _maxAge field of the Response object, because it requires Reflection. So, you will have to remove this trust level or put Full.

Collapse | Copy Code
    <system.web> 
    <trust level="Full"/>

When “this” is Not Really “this”

Atlas call-backs are not executed on the same context where they are called. For example, if you are making a Web method call from a JavaScript class like this:

Collapse | Copy Code
function SampleClass()
{
    this.id = 1;
    this.call = function()
    {
        TestService.DoSomething( "Hi", function(result)
        {
            debug.dump( this.id );
        } );
    }
}

What happens when you call the call method? Do you get 1 on the debug console? No, you get null on the debug console because this is no longer the instance of the class. This is a common mistake that everyone makes. As this is not yet documented in Atlas documentations, I have seen many developers spend time finding out what’s wrong. Here’s the reason: we know that whenever JavaScript events are raised, this refers to the HTML element that produced the event. So, if you do this:

Collapse | Copy Code
function SampleClass()
{
    this.id = 1;
    this.call = function()
    {
        TestService.DoSomething( "Hi", function(result)
        {
            debug.dump( this.id );
        } );
    }
}

<input type="button" id="ButtonID" onclick="o.onclick" />

If you click the button, you see ButtonID instead of 1. The reason is that the button is making the call. So, the call is made within the button object’s context and thus this maps to the button object. Similarly, when XML HTTP raises the event onreadystatechanged, which Atlas traps before firing the call-back, the code execution is still on the XML HTTP’s context. It’s the XML HTTP object that raises the event. As a result, this refers to the XML HTTP object, not your own class where the call-back is declared. In order to make the call-back fire on the context of the instance of the class so that this refers to the instance of the class, you need to make the following change:

Collapse | Copy Code
function SampleClass()
{
    this.id = 1;
    this.call = function()
    {
        TestService.DoSomething( "Hi", 
            Function.createDelegate( this, function(result)
        {
            debug.dump( this.id );
        } ) );
    }
}

Here, Function.createDelegate is used to create a delegate that calls the given function under the this context. Function.createDelegate is defined in AtlasRuntime:

Collapse | Copy Code
Function.createDelegate = function(instance, method) {
    return function() {
        return method.apply(instance, arguments);
    }
}

HTTP POST Is Slower than HTTP GET, but It Is Default in ASP.NET Ajax

ASP.NET Ajax, by default, makes HTTP POST for all web service calls. HTTP POST is more expensive than HTTP GET. It transmits more bytes over the wire, thus taking precious network time, and it also makes ASP.NET do extra processing on the server end. So, you should use HTTP GET as much as possible. However, HTTP GET does not allow you to pass objects as parameters. You can pass numerics, strings and dates only. When you make an HTTP GET call, Atlas builds an encoded URL and makes a hit to that URL. So, you must not pass too much content that makes the URL become larger than 2048 characters. As far as I know, that’s the max length of any URL. In order to enable HTTP GET on a web service method, you need to decorate the method with the [ScriptMethod(UseHttpGet=true)] attribute:

Collapse | Copy Code
[WebMethod] [ScriptMethod(UseHttpGet=true)] 
public string HelloWorld()
{
}

Another problem of POST vs. GET is that POST makes two network round trips. When you first make a POST, the web server sends an “HTTP 100 Continue” message, which means that the web server is ready to accept the content. After that, the browser sends the actual data. So, initiation of a POST request takes more time than GET. Network latency (round trip time between your computer and the server) is the biggest concern in Ajax applications because Ajax makes many small calls that need to be done within milliseconds. Otherwise, the application does not feel smooth and inspires user annoyance. Ethereal is a nice tool to see what happens under the hood on POST and GET:

From the above picture, you see that POST requires a confirmation from the web server, “HTTP/1.1 100 Continue,” before sending the actual data. After that, it transmits the data. On the other hand, GET transmits the data without waiting for any confirmation. So, you should use HTTP GET while downloading data from a server like parts of pages, contents in a grid, a block of text, etc. However, you should not use HTTP GET to send data to a server like submission of web forms.

AJAX based CRUD tables using ASP.NET MVC 3 and jTable jQuery plug-in


jTable overview
A full-featured jTable instance. Try a live demo here.

Contents

  • Introduction to the problem
  • What is jTable?
  • Live demo
  • A sample page with ASP.NET MVC 3 and jTable
    • Using the page
    • Model
    • Controller
      • Getting the list
      • Creating
      • Updating
      • Deleting
      • Getting options
    • View
  • Paging
  • Sorting
  • Selecting
  • Master/child tables
  • ASP.NET Web Forms support
  • Details
    • Methods
    • Actions
    • Field options
    • Other options
    • Events
    • Localization
    • Styling
  • Combining with validation
  • Future works
  • More
  • History
  • References

Introduction to the problem

When we are developing a ‘data manipulation page‘, we almost always do the same thing: A ‘table/grid’ that is used to ‘show records‘ of a table in a database, a ‘create new record‘ page/dialog to add a new record to the database, an ‘edit record‘ page/dialog to edit a record, and finally a way of ‘deleting a record‘ in the database.

Also, using AJAX, we can create more fast and interactive pages. Especially, jQuery and jQueryUI are invaluable libraries to perform manipulation in an HTML page and perform AJAX requests to the server.

Users no longer need to leave the ‘list of records’ page to create/edit or delete a record. Also, the page never refreshes itself to reflect a change in records. When the user deletes a record in the table, we can delete the corresponding row from the table without refreshing the whole page. When the user edits a record and saves it, we can change the corresponding values in the table, and so on… Also, we can do some animations while deleting, creating, or updating records.

All of the subjects I mentioned above are known techniques and we have all implemented them. But the problem is that, we are developing/coding almost the same page for every type of record. Surely, we can copy/paste/modify it! But is it a solution or another mess? All we know is, copy/paste is not desirable for all kinds of programming, it is an evil!

What is jTable

jTable [1] is a jQuery plug-in that addresses the problem mentioned above. It takes a list and properties of fields of a record and does all the job! It has several features:

  • Automatically creates an HTML table and loads records from the server using AJAX.
  • Automatically creates a ‘create new record‘ jQueryUI dialog form. When the user creates a record, it sends data to the server using AJAX and adds the same record to the table in the page.
  • Automatically creates an ‘edit record‘ jQueryUI dialog form. When the user edits a record, it updates the server using AJAX and updates all the cells on the table in the page.
  • Allow the user to ‘delete a record‘ by jQueryUI dialog based confirmation. When the user deletes a record, it deletes the record from the server using AJAX and deletes the record from the table in the page.
  • Supports server side AJAX based paging and sorting.
  • Allows user to select rows from table.
  • Supports unlimited level of master/child tables.
  • Shows animations for create/delete/edit operations on the table.
  • Exposes some events to enable validation with forms.
  • It can be localized easily.
  • Table, forms and other elements are styled in a well defined and commented CSS file.
  • It comes with four pre-defined color themes: blue, red, green and purple, for now.
  • It is browser/platform independent and works on all common browsers.
  • It is not dependent on any server-side technology such as ASP.NET MVC, and can be used with others.
  • It has direct support for ASP.NET Web Forms Page Methods.

Live demo

You can try out a demonstration here: http://www.jtable.org.

A sample page with ASP.NET MVC 3 and jTable

Here I will show how to develop a data manipulation page with ASP.NET MVC 3 and jTable. This sample project is included in the download file.

Assume that we are manipulating a Person list that has a lot of information: name, city, email, password, gender, birth date, an ‘about’ text, and education.

Using the page

First, I will show the capabilities of jTable. Here is the list of people:

The Person List

This table is automatically created by jTable. (Don’t worry about the style of the table. The HTML code of the table is not styled and is a clean HTML table. You can edit the CSS files easily.) Also, it shows only the desired fields. Edit/Delete images (buttons) are completely optional, and they are also automatically added to each row. Title is also optional and the add new record link is changeable by the user with another element in the page. While the records are being loaded, a ‘loading…’ animation is shown.

When the user clicks the add new record link, a jQueryUI dialog based form is opened:

Creating new record

This form is also completely automatically created based on the fields of the record! When you fill the form and save, jTable serializes the form and performs an AJAX call to the server. If the server responds ‘OK‘, it adds the record to the table with an animation:

Added new record animation

In the animation above, the row is highlighted with green. It turns back to normal color after a few seconds. This animation is just a CSS class transition and can be changed in the CSS file easily. So you can change the animation to whatever you want. If the server returns error while adding the record, jTable automatically shows an error dialog message and does not add the record to the table.

If you click the edit image (button) in a row, jTable automatically creates an editing jQuery dialog form:

Editing a record

jTable automatically creates and fills the form with the selected record’s values. When the user saves the form, just like creating a new record, the record is saved to the server. If the AJAX call is a success, the record values are updated in the table and an ‘edited’ animation is shown:

Editing Record Animation

As I mentioned above when creating the record, same animation mechanism does exist while updating an edited record in the table. An edited row turns to normal style in a few seconds.

When the user clicks the delete image (button), jTable shows a confirmation dialog:

Delete confirmation dialog

If the user clicks the delete button, the record is deleted from the server using an AJAX call. If the operation succeeds, it is also removed from the table automatically with a deleting animation:

Deleting animation

The deleting row is highlighted for a second and removed from the table.

Now we will see how to implement the page above in ASP.NET MVC 3.

Model

We have two classes here: Person (represents a record in the People database table) and City (represents a record in the Cities database table). A person lives in a city. So the Person class has a CityId that is the ID of a city row in the Cities table.

The Person class is shown below:

Collapse | Copy Code
public class Person
{
    public int PersonId { get; set; }

    // Id of a City in Cities
    [Required]
    public int CityId { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string EmailAddress { get; set; }

    [Required]
    public string Password { get; set; }

    // "M" for mail, "F" for female.
    [Required]
    public string Gender { get; set; }

    [Required]
    public DateTime BirthDate { get; set; }

    public string About { get; set; }

    // 0: Unselected, 1: Primary school,
    // 2: High school 3: University
    [Required]
    public int Education { get; set; }

    //true: Active, false: Passive
    [Required]
    public bool IsActive { get; set; }

    [Required]
    public DateTime RecordDate { get; set; }

    public Person()
    {
        RecordDate = DateTime.Now;
        Password = "123";
        About = "";
    }
}

The [Required] attributes are not related to jTable as you probably know. They are used by ASP.NET MVC and Entity framework for validation.

City is a simple class. It is designed to show the combobox feature of jTable (as you’ve seen above).

Collapse | Copy Code
public class City
{
    public int CityId { get; set; }

    [Required]
    public string CityName { get; set; }
}

Controller

jTable always uses the POST method while making AJAX calls to the server and expects a JSON object. URLs (Controller/Action names in ASP.NET MVC) can be arbitrary and they are set while creating a jTable instance (we will see this soon).

Getting the list

You must supply an action to jTable to get a list of records:

Collapse | Copy Code
[HttpPost]
public JsonResult PersonList()
{
    try
    {
        List<Person> persons = _personRepository.GetAllPersons();
        return Json(new { Result = "OK", Records = persons });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

All methods must return a JSON object. Result property must be “OK” if operation is successful. If an error occurs, Message property will contain an error message to show to the user. If Result is “OK“, the Records property will contain an array of records to show in the table.

You could pass some parameters to the action that can be used to get records based on some filters. Also, you can paginate or sort the table. We will see this later.

Creating

Creating a record is optional (we will see soon). If you allow user to create a record, you must supply an action to jTable to create a new record:

Collapse | Copy Code
[HttpPost]
public JsonResult CreatePerson(Person person)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return Json(new { Result = "ERROR", 
              Message = "Form is not valid! " + 
              "Please correct it and try again." });
        }

        var addedPerson = _personRepository.AddPerson(person);
        return Json(new { Result = "OK", Record = addedPerson });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

CreatePerson method must return the newly created object as the Record property. This is needed since newly inserted record will has a key (PersonId in this sample) and automatically generated values (such as RecordDate here).

Updating

Editing a record is optional (we will see soon). If you allow user to edit a record, you must supply an action to jTable to update a record:

Collapse | Copy Code
[HttpPost]
public JsonResult UpdatePerson(Person person)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return Json(new { Result = "ERROR", 
              Message = "Form is not valid! " + 
                "Please correct it and try again." });
        }

        _personRepository.UpdatePerson(person);
        return Json(new { Result = "OK" });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

Deleting

Deleting a record is optional (we will see soon). If you allow user to delete a record, You must supply an action to jTable to delete a record:

Collapse | Copy Code
[HttpPost]
public JsonResult DeletePerson(int personId)
{
    try
    {
        _personRepository.DeletePerson(personId);
        return Json(new { Result = "OK" });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

Getting options

jTable can automatically download and fill comboboxes from a URL. For instance, the City combobox in the Person create/edit form above uses this feature. In such cases, you must supply an action to get the option list:

Collapse | Copy Code
[HttpPost]
public JsonResult GetCityOptions()
{
    try
    {
        var cities = _personRepository.GetCities().Select(
            c => new { DisplayText = c.CityName, Value = c.CityId });
        return Json(new { Result = "OK", Options = cities });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

The returning JSON object must have the Options property. It is an array of objects and every object has two properties: DisplayText and Value.

View

C# codes above was not directly related to jTable and specific to the ASP.NET MVC implementation. View side is completely about jTable. When you download jTable, you will have a folder structure as shown below:

jTable folder structure

jquery.jtable.js file is the main and only JavaScript file which you must include in your project. Other files (CSS and images files) are used for styling the table and forms. We will come back to styling later.

First, we add the jtable_blue.css file (my favourite style 🙂 to the HEAD section of the HTML document (Razor view in ASP.NET MVC3):

Collapse | Copy Code
<link href="http://www.codeproject.com/Scripts/jtable/themes/standard/blue/jtable_blue.css" 
      rel="stylesheet" type="text/css" />

You can add red or purple style files instead of blue, or you can write your own style file. Then we must add the jquery.jtable.js script file to the page:

Collapse | Copy Code
<script type="text/javascript" src="http://www.codeproject.com/Scripts/jtable/jquery.jtable.js">
</script>

Note that jTable is dependent on jQuery and jQueryUI (included UI effects). So, you must add those scripts to your page before jTable. If you don’t have these libraries, go to http://jqueryui.com/download to download jQueryUI (it includes jQuery).

Finally, we can create the jTable instance like this:

Collapse | Copy Code
<div id="PersonTable" style="width: 580px; margin: auto;"></div>

<script type="text/javascript">

    $(document).ready(function () {

        //Prepare jtable plugin
        $('#PersonTable').jtable({
            title: 'The Person List',
            actions: {
                listAction: '/Home/PersonList',
                deleteAction: '/Home/DeletePerson',
                updateAction: '/Home/UpdatePerson',
                createAction: '/Home/CreatePerson'
            },
            fields: {
                PersonId: {
                    key: true,
                    create: false,
                    edit: false,
                    list: false
                },
                Name: {
                    title: 'Name',
                    width: '15%'
                },
                EmailAddress: {
                    title: 'Emal address',
                    list: false
                },
                Password: {
                    title: 'User Password',
                    type: 'password',
                    list: false
                },
                Gender: {
                    title: 'Gender',
                    width: '12%',
                    options: { 'M': 'Male', 'F': 'Female' }
                },
                CityId: {
                    title: 'Living city',
                    width: '15%',
                    options: '/Home/GetCityOptions'
                },
                BirthDate: {
                    title: 'Birth date',
                    width: '18%',
                    type: 'date',
                    displayFormat: 'yy-mm-dd'
                },
                Education: {
                    title: 'Education',
                    list: false,
                    type: 'radiobutton',
                    options: { '1': 'Primary school', 
                       '2': 'High school', '3': 'University' }
                },
                About: {
                    title: 'About this person',
                    type: 'textarea',
                    list: false
                },
                IsActive: {
                    title: 'Status',
                    width: '10%',
                    type: 'checkbox',
                    values: { 'false': 'Passive', 'true': 'Active' },
                    defaultValue: 'true'
                },
                RecordDate: {
                    title: 'Record date',
                    width: '18%',
                    type: 'date',
                    displayFormat: 'dd.mm.yy',
                    create: false,
                    edit: false
                }
            }
        });

        //Load person list from server
        $('#PersonTable').jtable('load');
    });

</script>

Yes, it’s a long definition but that’s all! jTable does not need anything else to create tables, forms, and animations. I’ll explain all options in the Details section but I want to explain some basics now.

As you can see, jTable just needs a div container as the only HTML tag. It gets options:

  • title: Title of the table.
  • actions: URLs of actions that are used to create/delete/update/list records.
  • fields: All fields of the record. A field entry has properties that define the field.

Finally, the load method of jTable is used to get records from the server (we will see this in detail). You can always call this method to load/refresh table data from the server.

Paging

jTable allows you server side paging with AJAX. See a demo here. It looks like the sample below:

Paging with jTable

To enable paging, paging option must set to true. You can also set pageSize option (default value is 10).

Collapse | Copy Code
$('#PersonTable').jtable({
    //...
    paging: true, //Set paging enabled
    actions: {
        //...
    },
    fields: {
        //...
    }
});

If paging is enabled, jTable sends two query string parameters to the server on listAction AJAX call:

  • jtStartIndex: Start index of records for current page.
  • jtPageSize: Count of maximum expected records.

Also, one additional information is expected from server:

  • TotalRecordCount: Total count of records (not only this page).

An ASP.NET MVC action that is used for paging is shown below:

Collapse | Copy Code
[HttpPost]
public JsonResult PersonList(int jtStartIndex, int jtPageSize)
{
    try
    {
        int personCount = _personRepository.GetPersonCount();
        List<Person> persons = _personRepository.GetPersons(jtStartIndex, jtPageSize);
        return Json(new { Result = "OK", Records = persons, TotalRecordCount = personCount });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

Sorting

jTable allows you server side sorting with AJAX. See a demo here. It looks like the sample below:

jTable sorting

To enable sorting, sorting option must set to true. You can also set defaultSorting option. It can be a field name of a column of the table. For instance, if you want table sorted by Name by default, defaultSorting can be ‘Name ASC‘ or ‘Name DESC‘.

Collapse | Copy Code
$('#PersonTable').jtable({
    //...
 sorting: true, //Enable sorting
 defaultSorting: 'Name ASC', //Sort by Name by default
    actions: {
        //...
    },
    fields: {
        //...
    }
});

If sorting is enabled, jTable sends a query string parameter to the server on listAction AJAX call:

  • jtSorting: A string represents requested sorting. It is built from sorting field name plus sorting direction. For instance, It can be ‘Name ASC‘, ‘BirtDate DESC‘, ‘Age ASC‘… etc.

An ASP.NET MVC action that is used for sorting is shown below:

Collapse | Copy Code
[HttpPost]
public JsonResult PersonList(int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
{
    try
    {
        int personCount = _personRepository.GetPersonCount();
        List<person> persons = _personRepository.GetPersons(jtStartIndex, jtPageSize, jtSorting);
        return Json(new { Result = "OK", Records = persons, TotalRecordCount = personCount });
    }
    catch (Exception ex)
    {
        return Json(new { Result = "ERROR", Message = ex.Message });
    }
}

Note that while sorting can be used with paging (as in this sample), it is completely independed from paging.

Selecting

jTable allows you client side selecting rows. See a demo here. It looks like the sample below:

jTable selecting

To enable selecting, selecting option must set to true. You can set multiselect option to true to allow user to select multiple rows at once. You can set selectingCheckboxes option to true to show checkboxes as the sample above. Finally, you can set selectOnRowClick to false to prevent row selecting on clicking anywhere on the row (it’s true as default).

To get list of selected rows, you can call selectedRows method of jTable anytime (see sample usage). Also, you can get notified when selection changed by selectionChanged event.

Collapse | Copy Code
//Prepare jtable plugin
$('#PersonTable').jtable({
    //...
 selecting: true, //Enable selecting
 multiselect: true, //Allow multiple selecting
 selectingCheckboxes: true, //Show checkboxes on first column
 //selectOnRowClick: false, //Enable this to only select using checkboxes
    actions: {
        //...
    },
    fields: {
        //...
    },
    //Register to selectionChanged event
    selectionChanged: function () {
        //Get all selected rows
        var $selectedRows = $('#PersonTable').jtable('selectedRows');

        $('#SelectedRowList').empty();
        if ($selectedRows.length > 0) {
            //Show selected rows
            $selectedRows.each(function () {
                var record = $(this).data('record');
                $('#SelectedRowList').append(
                    'PersonId: ' + record.PersonId +
                    'Name:' + record.Name
                    );
            });
        } else {
            //No rows selected
            $('#SelectedRowList').append('No row selected! Select rows to see here...');
        }
    }
});

In the sample above, we are registering to selectionChanged event. In the event handler, we are getting selected rows by selectedRows method. It returns a jQuery selection, so we can call any jQuery method on it. We can get the record by record data property. Then we can get fields of record as record.Name, record.PersonId… etc.

Master/Child tables

jTable supports unlimited level of child tables for a table. Child tables can also have their children and so on… A child table is releated in a row in master table. Look at the screen below:

Master Child table on jTable

Click here to see a live demo. When you click phone icon at left of a row, a new table slides down below the clicked row and you can manipulate phones of the selected person. You can do everything just as a regular jTable. When you click close button, child table slides up and closed.

To implement a child table, first we must understand custom (computed) column support of jTable. Green phone icon on the figure above is created in a custom column. To create a custom column, we use display option of jtable field definition as like below:

Collapse | Copy Code
//...
Phones: {
    title: '',
    width: '3%',
    sorting: false,
    edit: false,
    create: false,
    display: function (personData) {
        var $img = $('<img src="http://www.codeproject.com/Content/images/Misc/phone.png" title="Edit phone numbers" />');
        return $img;
    }
}
//...

Phones is a field definition as Name or Gender columns. But Person record has not a field named Phones. So, we define a function that will create value of this field to show on the table. display function is used for that. It is called by jTable for each row. It must return a text, HTML code or jQuery object. In the sample above, I created an image (green phone icon) as a jQuery object and returned it. Then jTable showed this image in the row. personData argument (you can change name of the argument of course) has record property that can be used to get record values for current row. So, if you want to use Name of the person, you can get it using personData.record.Name.

So far so good. But, how to open child table when user clicks this image. jTable defines two methods: openChildTable and closeChildTable to control child tables. So, web can open a child table when user clicks the phone icon (in the display method above):

Collapse | Copy Code
$img.click(function() {
    $('#PersonTable').jtable('openChildTable',
        $img.closest('tr'),
        {
            title: personData.record.Name + ' - Phone numbers',
            actions: {
                listAction: '/PagingPerson/PhoneList?PersonId=' +
                            personData.record.PersonId,
                deleteAction: '/PagingPerson/DeletePhone',
                updateAction: '/PagingPerson/UpdatePhone',
                createAction: '/PagingPerson/CreatePhone'
            },
            fields: {
                StudentId: {
                    type: 'hidden',
                    defaultValue: studentData.record.StudentId
                },
                PhoneId: {
                    key: true,
                    create: false,
                    edit: false,
                    list: false
                },
                PhoneType: {
                    title: 'Phone type',
                    width: '30%',
                    options: { '1': 'Home phone', 
                               '2': 'Office phone', 
                               '3': 'Cell phone'}
                },
                Number: {
                    title: 'Phone Number',
                    width: '30%'
                },
                RecordDate: {
                    title: 'Record date',
                    width: '20%',
                    type: 'date',
                    displayFormat: 'dd.mm.yy',
                    create: false,
                    edit: false
                }
            }
        }, function(data) { //opened handler
            data.childTable.jtable('load');
        });
});

openChildTable has three parameters. First one is used to indicate the row which is used as master row of child table. Here, I got container tr element of the image, so it gives the current row. Second parameter is a regular jTable initialization options. You can pass any option that can be passed to any jTable instance. So, you can define a custom column and open a second level child. Third and the last parameter is a callback method that is called by jTable after child table successfully created and opened. Here, I loaded records after child table is opened.

Look at the listAction. It’s something like that: ‘/PagingPerson/PhoneList?PersonId=’ + personData.record.PersonId. Thus, we are getting phone numbers those are related to current person (personData comes from display method, see codes above). Also, we need PersonId in the server side while creating a new phone number for a person. It’s done with a hidden field (See StudentId definition). Given default value is used for new records.

When you create a child table, jTable automatically closes it when user clicks close icon of the table. You can change/override these functionalities. See details to learn in deep.

ASP.NET Web Forms support

jTable has direct support for ASP.NET Web Forms Page Methods since jTable v1.4.1. While jTable is already platform independed, I have built an extension to jTable to support Page Methods in most proper way. For instance, see the code below. This page method is used to get student list as paged and sorted. It’s pretty much similar to it’s MVC version.

Collapse | Copy Code
[WebMethod(EnableSession = true)]
public static object StudentList(int jtStartIndex, int jtPageSize, string jtSorting)
{
    try
    {
        //Get data from database
        int studentCount = Repository.StudentRepository.GetStudentCount();
        List<student> students = Repository.StudentRepository.GetStudents(jtStartIndex, jtPageSize, jtSorting);
 
        //Return result to jTable
        return new { Result = "OK", Records = students, TotalRecordCount = studentCount };
    }
    catch (Exception ex)
    {
        return new { Result = "ERROR", Message = ex.Message };
    }
}

For more information on ASP.NET Web Forms support, see the tutorial in jTable.org. Also, the download file in this article includes samples in ASP.NET Web Forms.

Details

Now I will explain detailed usage of jTable.

Methods

jTable defines fallowing methods:

load(postData, completeCallback)

Loads records from the server. All parameters are optional. If you want to pass some parameters to the server, you can pass them in the postData argument while calling the load method, like this:

Collapse | Copy Code
$('#PersonTable').jtable('load', { CityId: 2, Name: 'Halil' });

You can get people who are living in city 2 and whose name is Halil like shown above. Surely, you must handle these parameters in the server side. Also, you can pass a callback method as completeCallback, that is called when loading of data is successfully completed.

reload(completeCallback)

Re-loads records from server with last postData. This method can be used to refresh table data from server since it does not change current page, sorting and uses last postData (passed on last load call). Also, you can pass a callback method as completeCallback, that is called when loading of data is successfully completed.

selectedRows()

Gets all selected rows as jQuery selection. See the sample above.

deleteRows(rows)

Deletes given rows from server and table. rows parameter must be a jQuery selection. This method can be combined with selectedRows method. Thus, you can get selected rows and pass to deleteRows method to delete them.

openChildTable(row, tableOptions, opened)

This method is used to create and open a child table for a data row (See Master/Child section above). rowargument is a data row on the table, tableOptions are standard jTable options that is used to initialize child table. opened is a callback that is called by jTable when the child table is shown (After opening animation is finished).

closeChildTable(row, closed)

This method is used to close an open child table for a table row. row is a jQuery row object (tr element) on the table. closed is a callback function that is called when child table is closed.

openChildRow(row)

This method is used to open child row for a table row. Child rows generally used to show child tables. If you want to show child tables, you don’t need to use this method, use openChildTable method instead. If you want to open a custom child row, use this method. It returns the opened child row. Thus, you can fill it with a custom content. A child row is related to a specific data row in the table (which is passed as row agrument). If the data row is removed from table, it’s child is also automatically removed.

closeChildRow(row)

This method is used to close an open child row for a table row. See openChildRow method. (This method is internally used by jTable to close child tables.)

getChildRow(row)

This method is used to get child row (tr element) for a table row. Thus, you can add content to the child row. See openChildRow method.

isChildRowOpen(row)

This method returns true if child row is open for specified row. See openChildRow method.

addRecord(options), removeRecord(options), updateRecord(options)

These methods are used to manipulate table data programmatically. Since they have a bit detailed usage, please see reference documentation for these methods.

Actions

There are four main actions that are used by jTable to perform AJAX requests to the server:

  • listAction: A URL address to get the list of records.
  • createAction: A URL address to submit a create new record form.
  • updateAction: A URL address to submit an edit record form.
  • deleteAction: A URL address to delete a record.

If you don’t want to use an action, just don’t define it. For instance, if you don’t want to allow user to delete a row, don’t supply a deleteAction URL. Thus, jTable will not put a delete button for the records.

Field options

Fields are the core of jTable. They define the shape and behavior of your page. A field can have these properties:

    • title: A string as header in the table and forms for this field.
    • width: Width of the column for this field in the table. Can be any CSS unit (15%, 120px.., so on).
    • key: A boolean value that indicates whether this field is the key field of the record. Every record must has one and only one key field that is used as key on update and delete operations.
    • list: A boolean value that indicates whether this field is shown in the table.
    • create: A boolean value that indicates whether this field is shown in the create record form.
    • edit: A boolean value that indicates whether this field is shown in the edit record form.
    • options: If this field’s value will be selected in an option list (combobox as default, can be radio button list), you must supply a source. An option source can be one of these values:
      • URL string: A URL to download the option list for this field (as we’ve seen above).
      • object: Property names are values, property values are display texts (see sample jTable instance in the View section above).
      • array: An array of values. If values of options are same as display texts, you can use this type.
    • type: Type of the field. If field is a string or number, no need to set the type. Other types are:
      • password: Show a password textbox for this field on edit/create forms.
      • textarea: Shows a textarea for this field on edit/create forms.
      • date: A date (not including time). You can also set the displayFormat option.
      • radiobutton: If field is a value from option, it can be a combobox (default) or radio button list. If it is a radio button list, set type as radiobutton. You must supply options as mentioned above.
      • checkbox: To show a checkbox while editing this field. You must supply values option for checked/unchecked states (see the sample page in the View section). By default, a checkbox’s text changes when user changes the state of the checkbox. If you want to fix the text, you can set the formText option for this field. By default, when the user clicks the checkbox’s text, the state of the checkbox changes. If you do not want that, you can set setOnTextClick to false.
      • hidden: A hidden field can be used hidden fields in edit and create forms. It is not shown on the table. You may want to use defaultValue option with hidden types, thus given default value is automatically set to the hidden field on creating form. See master/child demo for sample usage.
    • displayFormat: If the type is date, you can set its format. See jQueryUI datepicker formats [2].
    • defaultValue: You can set a default value for a field. It must be a valid value. For instance, if the field is an option list, it must be one of these options.
    • listClass: A string value that can be set as the class of a cell (td tag) of this field in the table. This way you can style the fields in the table.
    • inputClass: A string value that can be set as the class of an input item for this field in create/edit forms. So you can style input elements in the forms for this field. This can be useful when working with validation plug-ins (we will see soon).
    • sorting: Indicates that whether this column will be used to sort the table (If table is sortable).
    • display: This option is a function that allows you to define a fully custom column for table. jTable directly shows return value of this function on the table. See the sample below:
      Collapse | Copy Code
      TestColumn: {
          title: 'Test',
          display: function (data) {
              return 'test';
          }
      }

      This sample Test column returns a bold ‘test’ string for all rows. You can return any text, html code or jQuery object that will be shown on the table. This method is called for each row. You can get record of the row using data.record. So, if your record has Name property, you can use data.record.Name property to get the Name.
      display function can be used for many purposes such as creating calculated columns, opening child tables for a row… etc. See demos for detailed usage.

    • input: This option is a function that allows you to define a fully custom input element for create and edit forms. jTable directly shows return value of this function on the form.
      Collapse | Copy Code
      Name: {
          title: 'Name',
          width: '20%',
          input: function (data) {
              if (data.record) {
                  return '<input type="text" style="width:200px" value="' + data.record.Name + '" />';
              } else {
                  return '<input type="text" style="width:200px" value="enter your name here" />';
              }
          }
      }
    • Here, we return a simple text input for Name field of the record. If this input is being created for edit form, you can get editing record using data.record property. If this input is being created for create form, it is undefined. You can also use data.value to get current value of the field. This is default value (if defined) of field for create form, current value of field for edit form.

 

    While jTable automatically created appropriate input element for each field, you can use input option to create custom input elements.

Other options

jTable defines some other options that determine the general shape and behavior of the table and forms:

  • title: A string that is shown on top of the table. This is optional, if you don’t supply the title option, no title is displayed.
  • addRecordButton: A jQuery object that can be used instead of the ‘add new record’ link. Thus you can set any element on the page to open the ‘add new record’ dialog. If you set this option, the bottom panel of jTable is not shown (since it will be empty).
  • deleteConfirmation: This option can be a boolean value or a function. If it is a boolean value, that indicates whether a confirmation dialog is shown when user clicks delete button/icon for a record (default value is true). If this option is a function, It can fully control the delete confirmation process. It must be a function like that: deleteConfirmation: function(data) { … }
    data argument has some properties to control confirmation process:

    • row: A jQuery selection for deleting row element.
    • record: Actual deleting record. For example, you can get Name property of record asdata.record.Name.
    • cancel: You can set data.cancel to true to cancel delete process (default value is false).
    • cancelMessage: If you cancelled delete process, you can show a message to user that explains cancellation reason. If you don’t want to show any message, just don’t set it.
    • deleteConfirm: A boolean value indicates whether to show a delete confirmation message or not (default value is true).
    • deleteConfirmMessage: If confirmation enabled, you can set a custom confirmation message.

    For example, if you want to show some additional information to user on delete confirmation, you can write a function like that:

    Collapse | Copy Code
    deleteConfirmation: function(data) {
        data.deleteConfirmMessage = 'Are you sure to delete person ' + data.record.Name + '?';
    }
  • defaultDateFormat: Default format of a date field. See jQueryUI datepicker formats [2]. Default: ‘yy-mm-dd’.
  • dialogShowEffect: jQueryUI effect to be used while opening a jQueryUI dialog. Some options are ‘blind’, ‘bounce’, ‘clip’, ‘drop’, ‘explode’, ‘fold’, ‘highlight’, ‘puff’, ‘pulsate’, ‘scale’, ‘shake’, ‘size’, ‘slide’… etc. See jQueryUI documentation for all options. Default value is ‘fade’.
  • dialogHideEffect: jQueryUI effect to be used while opening a jQueryUI dialog. Some options are ‘blind’, ‘bounce’, ‘clip’, ‘drop’, ‘explode’, ‘fold’, ‘highlight’, ‘puff’, ‘pulsate’, ‘scale’, ‘shake’, ‘size’, ‘slide’… etc. See jQueryUI documentation for all options. Default value is ‘fade’.
  • messages: All messages that are shown by jTable. You can localize these messages (see the Localization section).
  • paging: Indicates that whether jTable uses paging or not.
  • pageSize: If paging enabled, this value indicates number of rows in a page.
  • sorting: Indicates that whether jTable will sort the table or not.
  • defaultSorting: Default sorting of table. It can be a field name of a column of the table. For instance, if you want table sorted by Name by default, defaultSorting can be ‘Name ASC‘ or ‘Name DESC‘.
  • selecting: Indicates that whether jTable allows user to select rows on the table.
  • multiselect: Indicates that whether jTable allows user to select multiple rows at once.
  • selectingCheckboxes: Indicates that whether jTable shows checkbox column for selecting.
  • selectOnRowClick: Indicates that whether jTable allows user to select a row by clicking anywhere on the row. This can be set as false to allow user selecting a row only by clicking to the checkbox (see selectingCheckboxes option).
  • showCloseButton: Indicates that whether jTable will show a close button/icon for the table. When user clicks the close button, closeRequested event is raised. This option is used internally by jTable to close child tables. Default value is false.
  • openChildAsAccordion: If this options is set to true, jTable automatically closes other open child tables when a child table is opened (accordion style). Default value is false.
  • animationsEnabled: Indicates that whether jTable shows animations when user creates, updates or deletes a row.

Events

jTable defines some events when certain conditions occur.

  • formCreated(event, data): This event is raised when an edit or create form is created for a record. You can reach the form using the data.form argument. You can get the type of the form using the data.formType argument. It can be ‘edit’ or ‘create’. If formType is edit, you can reach the editing record using the data.record argument (for example, you can get the name of the editing person as data.record.Name).
  • formSubmitting(event, data): This event is raised when save/submit button is clicked for a form. You can reach the form using the data.form argument. You can get the type of the form using the data.formType argument. It can be ‘edit’ or ‘create’. You can validate the form on this event. If you return false from this event callback, the submit operation is cancelled.
  • formClosed(event, data): This event is raised when an edit/create form dialog is closed. You can reach the form using the data.form argument. You can get the type of the form using the data.formType argument. It can be ‘edit’ or ‘create’.
  • loadingRecords(event, data): This event is raised just before AJAX request to load records from server. It has no arguments.
  • recordAdded(event, data): This event is raised when user successfully creates and saves a new record. You can get the added record using data.record arguement. You can get the response JSON object returned from server as data.serverResponse. If jTable is not running on paging mode, you can also get the added table row by data.row argument.
  • recordDeleted(event, data): This event is raised when user successfully deletes a record. You can get the deleted record using data.record argument. You can get the deleted table row by data.row argument. You can get the response JSON object returned from server as data.serverResponse.
  • recordsLoaded(event, data): This event is raised when jTable loads records from server and refreshes the table (If paging enabled, this event is also raised when user changes the current page). You can get all records loaded from server by data.records argument. You can get the response JSON object returned from server as data.serverResponse.
  • recordUpdated(event, data): This event is raised when user successfully updates a record. You can get the updated record using data.record arguement. You can get the updated table row by data.row argument. You can get the response JSON object returned from server as data.serverResponse.
  • rowsRemoved(event, data): This event is raised when either user deletes row/rows (actual record deletion from server) or during re-loading records from server (all rows cleared but not deleted from server). You can get all removed rows by data.rows as jQuery selection. You can get remove reason by data.reason (can be ‘deleted’ or ‘reloading’).
  • selectionChanged(event, data): This event is raised when selected rows on the table changes in anyway. It may change when user selects/deselects a row, a selected row is deleted, page changed while some rows are selected… etc. You can get selected rows by selectedRows method.
  • closeRequested(event, data): This event is raised when user clicks close button/icon of the table. Close button is shown if showCloseButton is set to true. This event has no argument.
  • rowInserted(event, data): This event is raised when a row is inserted to the shown table. A new row can be inserted either when user added a new record or records loaded from server. When records loaded from server, rowInserted event is called for each row. So, you can modify row or do whatever you need. You can get the row using data.row, you can get related record with data.record. Finally, if this is a new record (that’s added by user) data.isNewRow is set to true by jTable.
  • rowUpdated(event, data): This event is raised when a row updated. A row is updated when user updates a record. You can get the updated row using data.row, you can get related record with data.record. This event is raised after recordUpdated.

NOTE: formCreated, formSubmitting, and formClosed events are suitable to inject validation logic. See the ‘Combining with validation’ section in this article.

Localization

jTable can be easily localized. You can use the messages option to localize a jTable instance on initialization.

Default value of the messages option is shown below:

Collapse | Copy Code
messages: {
    serverCommunicationError: 'An error occured while communicating to the server.',
    loadingMessage: 'Loading records...',
    noDataAvailable: 'No data available!',
    addNewRecord: '+ Add new record',
    editRecord: 'Edit Record',
    areYouSure: 'Are you sure?',
    deleteConfirmation: 'This record will be deleted. Are you sure?',
    save: 'Save',
    saving: 'Saving',
    cancel: 'Cancel',
    deleteText: 'Delete',
    deleting: 'Deleting',
    error: 'Error',
    close: 'Close',
    cannotLoadOptionsFor: 'Can not load options for field {0}',
    pagingInfo: 'Showing {0} to {1} of {2} records',
    canNotDeletedRecords: 'Can not deleted {0} of {1} records!',
    deleteProggress: 'Deleted {0} of {1} records, processing...'
}

Here, a sample localization for Turkish language:

Collapse | Copy Code
<div id="PersonTable" style="width: 580px; margin: auto;">
</div>
<script type="text/javascript">

    $(document).ready(function () {

        //Localization messages for Turkish
        var turkishMessages = {
            serverCommunicationError: 
              'Sunucu ile iletişim kurulurken bir hata oluştu.',
            loadingMessage: 'Kayıtlar yükleniyor...',
            noDataAvailable: 'Hiç kayıt bulunmamaktadır!',
            addNewRecord: '+ Yeni kayıt ekle',
            editRecord: 'Kayıt düzenle',
            areYouSure: 'Emin misiniz?',
            deleteConfirmation: 'Bu kayıt silinecektir. Emin misiniz?',
            save: 'Kaydet',
            saving: 'Kaydediyor',
            cancel: 'İptal',
            deleteText: 'Sil',
            deleting: 'Siliyor',
            error: 'Hata',
            close: 'Kapat',
            cannotLoadOptionsFor: '{0} alanı için seçenekler yüklenemedi!',
            pagingInfo: '{2} Kayıttan {0} ile {1} arası gösteriliyor',
            canNotDeletedRecords: '{1} kayıttan {0} adedi silinemedi!',
            deleteProggress: '{1} kayıttan {0} adedi silindi, devam ediliyor...'
        };

        //Prepare jtable plugin
        $('#PersonTable').jtable({
            messages: turkishMessages, //Set messages as Turkish
            title: '...',
            actions: {
                ...
            },
            fields: {
                ...
            }
        });

        //Load person list from server
        $('#PersonTable').jtable('load');
    });

</script>

Result of the localization:

Turkish Localization

Styling

All styles of jTable are defined in the related CSS files. There are three pre-defined styles other than blue:

jTable Styles

You can set any style by including its CSS file in your HTML document:

Collapse | Copy Code
<!-- BLUE style -->
<link href="http://www.codeproject.com/Scripts/jtable/themes/standard/blue/jtable_blue.css" 
           rel="stylesheet" type="text/css" />

<!-- RED style -->
<link href="http://www.codeproject.com/Scripts/jtable/themes/standard/red/jtable_red.css" 
           rel="stylesheet" type="text/css" />

<!-- GREEN style -->
<link href="http://www.codeproject.com/Scripts/jtable/themes/standard/green/jtable_green.css" 
           rel="stylesheet" type="text/css" />

<!-- PURPLE style -->
<link href="http://www.codeproject.com/Scripts/jtable/themes/standard/purple/jtable_purple.css" 
           rel="stylesheet" type="text/css" />

If you want to use your own styles, you can start with the jtable_empty.css file. It defines all CSS selectors for jTable as empty. You can fill in the CSS selectors.

If you did like the jTable standard theme (defined in jtable_standard_base.css) but not happy with the colors, you can copy jtable_blue.css and change the colors.

Combining with validation

Validation is a common task while working with forms. jTable exposes some events (described above, in the Events section) to inject validation logic to jTable auto-created forms. You can use your own validation logic or a jQuery validation plug-in.

Validation engine [3] is a powerful validation plug-in for jQuery. I definitely recommend it. Here I will show how to inject validation engine to a jTable instance. First, see the validation engine in action:

Validatin Engine Integration

As you can see, when I try to save the form, the validation engine shows some error messages and prevent the submission of the form.

To be able to use the validation engine, first we must add style and JavaScript files to our HTML page:

Collapse | Copy Code
<!-- Validation engine style file -->
<link href="@Url.Content("~/Scripts/validationEngine/validationEngine.jquery.css")" 
      rel="stylesheet" type="text/css" />

<!-- Validation engine script file and english localization -->
<script type="text/javascript" 
  src="@Url.Content("~/Scripts/validationEngine/jquery.validationEngine.js")">
</script>
<script type="text/javascript" 
  src="@Url.Content("~/Scripts/validationEngine/jquery.validationEngine-en.js")">
</script>

Then we register to the events of jTable to inject validation engine to jTable forms:

Collapse | Copy Code
<script type="text/javascript">

    $(document).ready(function () {

        //Prepare jtable plugin
        $('#PersonTable').jtable({
            title: '...',
            actions: {
                ...
            },
            fields: {
                ...
            },
            formCreated: function (event, data) {
 data.form.find('input[name="Name"]').addClass(
 'validate[required]');
 data.form.find('input[name="EmailAddress"]').addClass(
 'validate[required,custom[email]]');
 data.form.find('input[name="Password"]').addClass(
 'validate[required]');
 data.form.find('input[name="BirthDate"]').addClass(
 'validate[required,custom[date]]');
 data.form.find('input[name="Education"]').addClass(
 'validate[required]');
 data.form.validationEngine();
            },
            formSubmitting: function (event, data) {
 return data.form.validationEngine('validate');
            },
            formClosed: function (event, data) {
 data.form.validationEngine('hide');
 data.form.validationEngine('detach');
            }
        });

        //Load person list from server
        $('#PersonTable').jtable('load');
    });

</script>

The validation engine works with CSS classes for validation. validate[required] indicates that this input element can not be empty. Take a look at the validation engine’s web site [3] for details.

In the formCreated event, I add the required classes to input elements and call the validationEngine() plug-in method on the form. In the formSubmitting event, I call the Validate method of the validation engine. It returns false if the form is not valid. So I use the same value as the return value of the formSubmitting event. jTable does not submit the form if this event returns false. Finally, in the formClosed event, I detach the validation engine from the form.

This was the first method for validation. Since jTable allows you to inject classes to your input fields using the inputClass property in field definitions, we could define a field with the validate[required] class as default:

Collapse | Copy Code
//...
Name: {
    title: 'Name',
    width: '15%',
 inputClass: 'validate[required]'
},
//...

Thus, jTable automatically adds the validate[required] class to the input element of this field. So we don’t need to add classes to inputs in the formCreated event.

See the “Using with ‘validation engine’ plugin – 2” demo page in the download file or the demo web site

Introduction to Object Oriented Programming Concepts (OOP) and More


  • 1. Introduction
  • 2. Background
  • 3. Prerequisites
  • 4. The Main Content
    • 4.1. What is Software Architecture?
    • 4.2. Why Architecture is important?
    • 4.3. What is OOP?
    • 4.4. What is an Object?
    • 4.5. What is a Class?
    • 4.6. How to identify and design a Class?
    • 4.7. What is Encapsulation (or information hiding)?
    • 4.8. What is Association?
    • 4.9. What is the difference between Association, Aggregation and Composition?
    • 4.10. What is Abstraction and Generalization?
    • 4.11. What is an Abstract class?
    • 4.12. What is an Interface?
    • 4.13. What is the difference between a Class and an Interface?
    • 4.14. What is the difference between an Interface and an Abstract class?
    • 4.15. What is Implicit and Explicit Interface Implementations?
    • 4.16. What is Inheritance?
    • 4.17. What is Polymorphism?
    • 4.18. What is Method Overloading?
    • 4.19. What is Operator overloading?
    • 4.20. What is Method Overriding?
    • 4.21. What is a Use case?
    • 4.22. What is a Class Diagram?
    • 4.23. What is a Package Diagram?
    • 4.24. What is a Sequence Diagram?
    • 4.25. What is two-tier architecture?
    • 4.26. What is three-tier architecture?
    • 4.27. What is MVC architecture?
    • 4.28. What is SOA?
    • 4.29. What is the Data Access Layer?
    • 4.30. What is the Business Logic Layer?
    • 4.31. What is Gang of Four (GoF) Design Patterns?
    • 4.32. What is the difference between Abstract Factory and Builder design patterns?
  • 5. What is the Conclusion?
  • 6. What I Referred?
  • 7. History

1. Introduction

I have noticed an increase in the number of articles published in the Architect category in code-project during the last few months. The number of readers for most of these articles is also high, though the ratings for the articles are not. This indicates that readers are interested in reading articles on Architecture, but the quality does not match their expectations. This article is a constructive attempt to group/ define/ explain all introductory concepts of software architecture for well seasoned developers who are looking to take their next step as system architects.

One day I read an article that said that the richest 2 percent own half the world’s wealth. It also said that the richest 1 percent of adults owned 40 percent of global assets in the year 2000. And further, that the richest 10 percent of adults accounted for 85 percent of the world’s total wealth. So there is an unbalanced distribution of wealth in the physical world. Have you ever thought of an unbalanced distribution of knowledge in the software world? According to my view point, the massive expansion of the software industry is forcing developers to use already implemented libraries, services and frameworks to develop software within ever shorter periods of time. The new developers are trained to use (I would say more often) already developed software components, to complete the development quicker. They just plug in an existing library and some how manage to achieve the requirements. But the sad part of the story is, that they never get a training to define, design the architecture for, and implement such components. As the number of years pass by, these developers become leads and also software architects. Their titles change, but the old legacy of not understanding, of not having any architectural experience continues, creating a vacuum of good architects. The bottom line is that only a small percentage of developers know how to design a truly object oriented system. The solution to this problem is getting harder every day as the aggressive nature of the software industry does not support an easy adjustment to existing processes, and also the related online teaching materials are either complex or less practical or sometimes even wrong. The most of them use impractical, irrelevant examples of shapes, animals and many other physical world entities to teach concepts of software architecture. There are only very few good business-oriented design references. Unfortunately, I myself am no exception and am a result of this very same system. I got the same education that all of you did, and also referred to the same resource set you all read.

Coming back to the initial point, I noticed that there is a knowledge gap, increasing every day, between the architects who know how to architect a system properly and the others who do not know. The ones, who know, know it right. But the ones, who do not know, know nothing. Just like the world’s wealth distribution, it is an unbalanced distribution of knowledge.

2. Background

This article began after reading and hearing the questions new developers have, on basics of software architecture. There are some good articles out there, but still developers struggle to understand the basic concepts, and more importantly, the way to apply them correctly.

As I see it, newcomers will always struggle to understand a precise definition of a new concept, because it is always a new and hence unfamiliar idea. The one, who has experience, understands the meaning, but the one who doesn’t, struggles to understand the very same definition. It is like that. Employers want experienced employees. So they say, you need to have experience to get a job. But how the hell is one supposed to have that experience if no one is willing to give him a job? As in the general case, the start with software architecture is no exception. It will be difficult. When you start to design your very first system, you will try to apply everything you know or learned from everywhere. You will feel that an interface needs to be defined for every class, like I did once. You will find it harder to understand when and when not to do something. Just prepare to go through a painful process. Others will criticize you, may laugh at you and say that the way you have designed it is wrong. Listen to them, and learn continuously. In this process you will also have to read and think a lot. I hope that this article will give you the right start for that long journey.

The knowledge of the actions of great men, acquired by long experience in contemporary affairs, and a continual study of antiquity” – I read this phrase when I was reading the book named “The Art of War”, seems applicable here, isn’t it?

3. Prerequisites

This article is an effort to provide an accurate information pool for new developers on the basics of software architecture, focusing on Object Oriented Programming (OOP). If you are a developer, who has a minimum of three or more years of continuous development experience and has that hunger to learn more, to step-in to the next level to become a software architect, this article is for you.

4. The Main Content

4.1. What is Software Architecture?

Software Architecture is defined to be the rules, heuristics and patterns governing:

  • Partitioning the problem and the system to be built into discrete pieces
  • Techniques used to create interfaces between these pieces
  • Techniques used to manage overall structure and flow
  • Techniques used to interface the system to its environment
  • Appropriate use of development and delivery approaches, techniques and tools.

4.2. Why Architecture is important?

OOP.jpg

The primary goal of software architecture is to define the non-functional requirements of a system and define the environment. The detailed design is followed by a definition of how to deliver the functional behavior within the architectural rules. Architecture is important because it:

  • Controls complexity
  • Enforces best practices
  • Gives consistency and uniformity
  • Increases predictability
  • Enables re-use.

4.3. What is OOP?

OOP is a design philosophy. It stands for Object Oriented Programming. Object-Oriented Programming (OOP) uses a different set of programming languages than old procedural programming languages (C, Pascal, etc.). Everything in OOP is grouped as self sustainable “objects“. Hence, you gain re-usability by means of four main object-oriented programming concepts.

In order to clearly understand the object orientation, let’s take your “hand” as an example. The “hand” is a class. Your body has two objects of type hand, named left hand and right hand. Their main functions are controlled/ managed by a set of electrical signals sent through your shoulders (through an interface). So the shoulder is an interface which your body uses to interact with your hands. The hand is a well architected class. The hand is being re-used to create the left hand and the right hand by slightly changing the properties of it.

4.4. What is an Object?

An object can be considered a “thing” that can perform a set of related activities. The set of activities that the object performs defines the object’s behavior. For example, the hand can grip something or a Student (object) can give the name or address.

In pure OOP terms an object is an instance of a class.

4.5. What is a Class?

class.gif

A class is simply a representation of a type of object. It is the blueprint/ plan/ template that describe the details of an object. A class is the blueprint from which the individual objects are created. Class is composed of three things: a name, attributes, and operations.

Collapse | Copy Code
public class Student
{
}

According to the sample given below we can say that the student object, named objectStudent, has created out of the Student class.

Collapse | Copy Code
Student objectStudent = new Student();

In real world, you’ll often find many individual objects all of the same kind. As an example, there may be thousands of other bicycles in existence, all of the same make and model. Each bicycle has built from the same blueprint. In object-oriented terms, we say that the bicycle is an instance of the class of objects known as bicycles.

In the software world, though you may not have realized it, you have already used classes. For example, the TextBox control, you always used, is made out of the TextBox class, which defines its appearance and capabilities. Each time you drag a TextBox control, you are actually creating a new instance of the TextBox class.

4.6. How to identify and design a Class?

This is an art; each designer uses different techniques to identify classes. However according to Object Oriented Design Principles, there are five principles that you must follow when design a class,

  • SRP – The Single Responsibility Principle –
    A class should have one, and only one, reason to change.
  • OCP – The Open Closed Principle –
    You should be able to extend a classes behavior, without modifying it.
  • LSP – The Liskov Substitution Principle-
    Derived classes must be substitutable for their base classes.
  • DIP – The Dependency Inversion Principle-
    Depend on abstractions, not on concretions.
  • ISP – The Interface Segregation Principle-
    Make fine grained interfaces that are client specific.

For more information on design principles, please refer to Object Mentor.

Additionally to identify a class correctly, you need to identify the full list of leaf level functions/ operations of the system (granular level use cases of the system). Then you can proceed to group each function to form classes (classes will group same types of functions/ operations). However a well defined class must be a meaningful grouping of a set of functions and should support the re-usability while increasing expandability/ maintainability of the overall system.

In software world the concept of dividing and conquering is always recommended, if you start analyzing a full system at the start, you will find it harder to manage. So the better approach is to identify the module of the system first and then dig deep in to each module separately to seek out classes.

A software system may consist of many classes. But in any case, when you have many, it needs to be managed. Think of a big organization, with its work force exceeding several thousand employees (let’s take one employee as a one class). In order to manage such a work force, you need to have proper management policies in place. Same technique can be applies to manage classes of your software system as well. In order to manage the classes of a software system, and to reduce the complexity, the system designers use several techniques, which can be grouped under four main concepts named Encapsulation, Abstraction, Inheritance, and Polymorphism. These concepts are the four main gods of OOP world and in software term, they are called four main Object Oriented Programming (OOP) Concepts.

4.7. What is Encapsulation (or information hiding)?

The encapsulation is the inclusion within a program object of all the resources need for the object to function – basically, the methods and the data. In OOP the encapsulation is mainly achieved by creating classes, the classes expose public methods and properties. The class is kind of a container or capsule or a cell, which encapsulate the set of methods, attribute and properties to provide its indented functionalities to other classes. In that sense, encapsulation also allows a class to change its internal implementation without hurting the overall functioning of the system. That idea of encapsulation is to hide how a class does it but to allow requesting what to do.

class.gif

In order to modularize/ define the functionality of a one class, that class can uses functions/ properties exposed by another class in many different ways. According to Object Oriented Programming there are several techniques, classes can use to link with each other and they are named association, aggregation, and composition.

There are several other ways that an encapsulation can be used, as an example we can take the usage of an interface. The interface can be used to hide the information of an implemented class.

Collapse | Copy Code
IStudent myStudent = new LocalStudent();
IStudent myStudent = new ForeignStudent();

According to the sample above (let’s assume that LocalStudent and ForeignStudent are implemented by the IStudent interface) we can see how LocalStudent and ForeignStudent are hiding their, localize implementing information through the IStudent interface.

4.8. What is Association?

Association is a (*a*) relationship between two classes. It allows one object instance to cause another to perform an action on its behalf. Association is the more general term that define the relationship between two classes, where as the aggregation and composition are relatively special.

Collapse | Copy Code
public class StudentRegistrar
{
    public StudentRegistrar ();
    {
        new RecordManager().Initialize();
    }
}

In this case we can say that there is an association between StudentRegistrar and RecordManager or there is a directional association from StudentRegistrar to RecordManager or StudentRegistrar use a (*Use*) RecordManager. Since a direction is explicitly specified, in this case the controller class is the StudentRegistrar.

Association.gif

To some beginners, association is a confusing concept. The troubles created not only by the association alone, but with two other OOP concepts, that is association, aggregation and composition. Every one understands association, before aggregation and composition are described. The aggregation or composition cannot be separately understood. If you understand the aggregation alone it will crack the definition given for association, and if you try to understand the composition alone it will always threaten the definition given for aggregation, all three concepts are closely related, hence must study together, by comparing one definition to another. Let’s explore all three and see whether we can understand the differences between these useful concepts.

4.9. What is the difference between Association, Aggregation and Composition?

Association is a (*a*) relationship between two classes, where one class use another. But aggregation describes a special type of an association. Aggregation is the (*the*) relationship between two classes. When object of one class has an (*has*) object of another, if second is a part of first (containment relationship) then we called that there is an aggregation between two classes. Unlike association, aggregation always insists a direction.

Collapse | Copy Code
public class University
{
    private Chancellor  universityChancellor = new Chancellor();
}

aggregation.gif

In this case I can say that University aggregate Chancellor or University has an (*has-a*) Chancellor. But even without a Chancellor a University can exists. But the Faculties cannot exist without the University, the life time of a Faculty (or Faculties) attached with the life time of the University . If University is disposed the Faculties will not exist. In that case we called that University is composed of Faculties. So that composition can be recognized as a special type of an aggregation.

Composite.gif

Same way, as another example, you can say that, there is a composite relationship in-between a KeyValuePairCollection and a KeyValuePair. The two mutually depend on each other.

.Net and Java uses the Composite relation to define their Collections. I have seen Composition is being used in many other ways too. However the more important factor, that most people forget is the life time factor. The life time of the two classes that has bond with a composite relation mutually depend on each other. If you take the .net Collection to understand this, there you have the Collection Element define inside (it is an inner part, hence called it is composed of) the Collection, farcing the Element to get disposed with the Collection. If not, as an example, if you define the Collection and it’s Element to be independent, then the relationship would be more of a type Aggregation, than a Composition. So the point is, if you want to bind two classes with Composite relation, more accurate way is to have a one define inside the other class (making it a protected or private class). This way you are allowing the outer class to fulfill its purpose, while tying the lifetime of the inner class with the outer class.

So in summary, we can say that aggregation is a special kind of an association and composition is a special kind of an aggregation. (Association->Aggregation->Composition)

association_aggre_com.gif

4.10. What is Abstraction and Generalization?

Abstraction is an emphasis on the idea, qualities and properties rather than the particulars (a suppression of detail). The importance of abstraction is derived from its ability to hide irrelevant details and from the use of names to reference objects. Abstraction is essential in the construction of programs. It places the emphasis on what an object is or does rather than how it is represented or how it works. Thus, it is the primary means of managing complexity in large programs.

While abstraction reduces complexity by hiding irrelevant detail, generalization reduces complexity by replacing multiple entities which perform similar functions with a single construct. Generalization is the broadening of application to encompass a larger domain of objects of the same or different type. Programming languages provide generalization through variables, parameterization, generics and polymorphism. It places the emphasis on the similarities between objects. Thus, it helps to manage complexity by collecting individuals into groups and providing a representative which can be used to specify any individual of the group.

Abstraction and generalization are often used together. Abstracts are generalized through parameterization to provide greater utility. In parameterization, one or more parts of an entity are replaced with a name which is new to the entity. The name is used as a parameter. When the parameterized abstract is invoked, it is invoked with a binding of the parameter to an argument.

4.11. What is an Abstract class?

Abstract classes, which declared with the abstract keyword, cannot be instantiated. It can only be used as a super-class for other classes that extend the abstract class. Abstract class is the concept and implementation gets completed when it is being realized by a subclass. In addition to this a class can inherit only from one abstract class (but a class may implement many interfaces) and must override all its abstract methods/ properties and may override virtual methods/ properties.

Abstract classes are ideal when implementing frameworks. As an example, let’s study the abstract class named LoggerBase below. Please carefully read the comments as it will help you to understand the reasoning behind this code.

Collapse | Copy Code
public abstract class LoggerBase
{
    /// <summary>
    /// field is private, so it intend to use inside the class only
    /// </summary>
    private log4net.ILog logger = null; 

    /// <summary>
    /// protected, so it only visible for inherited class
    /// </summary>
    protected LoggerBase()
    {
        // The private object is created inside the constructor
        logger = log4net.LogManager.GetLogger(this.LogPrefix);
        // The additional initialization is done immediately after
        log4net.Config.DOMConfigurator.Configure();
    }

    /// <summary>
    /// When you define the property as abstract,
    /// it forces the inherited class to override the LogPrefix
    /// So, with the help of this technique the log can be made,
    /// inside the abstract class itself, irrespective of it origin.
    /// If you study carefully you will find a reason for not to have “set” method here.
    /// </summary>
    protected abstract System.Type LogPrefix
    {
        get;
    }

    /// <summary>
    /// Simple log method,
    /// which is only visible for inherited classes
    /// </summary>
    /// <param name="message"></param>
    protected void LogError(string message)
    {
        if (this.logger.IsErrorEnabled)
        {
            this.logger.Error(message);
        }
    }

    /// <summary>
    /// Public properties which exposes to inherited class
    /// and all other classes that have access to inherited class
    /// </summary>
    public bool IsThisLogError
    {
        get
        {
            return this.logger.IsErrorEnabled;
        }
    }
}

The idea of having this class as an abstract is to define a framework for exception logging. This class will allow all subclass to gain access to a common exception logging module and will facilitate to easily replace the logging library. By the time you define the LoggerBase, you wouldn’t have an idea about other modules of the system. But you do have a concept in mind and that is, if a class is going to log an exception, they have to inherit the LoggerBase. In other word the LoggerBase provide a framework for exception logging.

Let’s try to understand each line of the above code.

Like any other class, an abstract class can contain fields, hence I used a private field named logger declare the ILog interface of the famous log4net library. This will allow the Loggerbase class to control, what to use, for logging, hence, will allow changing the source logger library easily.

The access modifier of the constructor of the LoggerBase is protected. The public constructor has no use when the class is of type abstract. The abstract classes are not allowed to instantiate the class. So I went for the protected constructor.

The abstract property named LogPrefix is an important one. It enforces and guarantees to have a value for LogPrefix (LogPrefix uses to obtain the detail of the source class, which the exception has occurred) for every subclass, before they invoke a method to log an error.

The method named LogError is protected, hence exposed to all subclasses. You are not allowed or rather you cannot make it public, as any class, without inheriting the LoggerBase cannot use it meaningfully.

Let’s find out why the property named IsThisLogError is public. It may be important/ useful for other associated classes of an inherited class to know whether the associated member logs its errors or not.

Apart from these you can also have virtual methods defined in an abstract class. The virtual method may have its default implementation, where a subclass can override it when required.

All and all, the important factor here is that all OOP concepts should be used carefully with reasons, you should be able to logically explain, why you make a property a public or a field a private or a class an abstract. Additionally, when architecting frameworks, the OOP concepts can be used to forcefully guide the system to be developed in the way framework architect’s wanted it to be architected initially.

4.12. What is an Interface?

In summary the Interface separates the implementation and defines the structure, and this concept is very useful in cases where you need the implementation to be interchangeable. Apart from that an interface is very useful when the implementation changes frequently. Some say you should define all classes in terms of interfaces, but I think recommendation seems a bit extreme.

Interface can be used to define a generic template and then one or more abstract classes to define partial implementations of the interface. Interfaces just specify the method declaration (implicitly public and abstract) and can contain properties (which are also implicitly public and abstract). Interface definition begins with the keyword interface. An interface like that of an abstract class cannot be instantiated.

If a class that implements an interface does not define all the methods of the interface, then it must be declared abstract and the method definitions must be provided by the subclass that extends the abstract class. In addition to this an interfaces can inherit other interfaces.

The sample below will provide an interface for our LoggerBase abstract class.

Collapse | Copy Code
public interface ILogger
{
    bool IsThisLogError { get; }
}

4.13. What is the difference between a Class and an Interface?

In .Net/ C# a class can be defined to implement an interface and also it supports multiple implementations. When a class implements an interface, an object of such class can be encapsulated inside an interface.

If MyLogger is a class, which implements ILogger, there we can write

Collapse | Copy Code
ILogger log = new MyLogger();

A class and an interface are two different types (conceptually). Theoretically a class emphasis the idea of encapsulation, while an interface emphasis the idea of abstraction (by suppressing the details of the implementation). The two poses a clear separation from one to another. Therefore it is very difficult or rather impossible to have an effective meaningful comparison between the two, but it is very useful and also meaningful to have a comparison between an interface and an abstract class.

4.14. What is the difference between an Interface and an Abstract class?

There are quite a big difference between an interface and an abstract class, even though both look similar.

    • Interface definition begins with a keyword interface so it is of type interface
    • Abstract classes are declared with the abstract keyword so it is of type class
    • Interface has no implementation, but they have to be implemented.
    • Abstract class’s methods can have implementations and they have to be extended.
    • Interfaces can only have method declaration (implicitly public and abstract) and fields (implicitly public static)
    • Abstract class’s methods can’t have implementation only when declared abstract.
    • Interface can inherit more than one interfaces
    • Abstract class can implement more than one interfaces, but can inherit only one class
    • Abstract class must override all abstract method and may override virtual methods
    • Interface can be used when the implementation is changing
    • Abstract class can be used to provide some default behavior for a base class.
    • Interface makes implementation interchangeable
    • Interface increase security by hiding the implementation
    • Abstract class can be used when implementing framework
    • Abstract classes are an excellent way to create planned inheritance hierarchies and also to use as non-leaf classes in class hierarchies.

Abstract classes let you define some behaviors; they force your subclasses to provide others. For example, if you have an application framework, an abstract class can be used to provide the default implementation of the services and all mandatory modules such as event logging and message handling etc. This approach allows the developers to develop the application within the guided help provided by the framework.

However, in practice when you come across with some application-specific functionality that only your application can perform, such as startup and shutdown tasks etc. The abstract base class can declare virtual shutdown and startup methods. The base class knows that it needs those methods, but an abstract class lets your class admit that it doesn’t know how to perform those actions; it only knows that it must initiate the actions. When it is time to start up, the abstract class can call the startup method. When the base class calls this method, it can execute the method defined by the child class.

4.15. What is Implicit and Explicit Interface Implementations?

As mentioned before .Net support multiple implementations, the concept of implicit and explicit implementation provide safe way to implement methods of multiple interfaces by hiding, exposing or preserving identities of each of interface methods, even when the method signatures are the same.

Let’s consider the interfaces defined below.

Collapse | Copy Code
interface IDisposable
{
    void Dispose();
}

Here you can see that the class Student has implicitly and explicitly implemented the method named Dispose() via Dispose and IDisposable.Dispose.

Collapse | Copy Code
class Student : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("Student.Dispose");
    }

    void IDisposable.Dispose()
    {
        Console.WriteLine("IDisposable.Dispose");
    }
}

4.16. What is Inheritance?

Ability of a new class to be created, from an existing class by extending it, is called inheritance.

Inheritance.gif

Collapse | Copy Code
public class Exception
{
}

public class IOException : Exception
{
}

According to the above example the new class (IOException), which is called the derived class or subclass, inherits the members of an existing class (Exception), which is called the base class or super-class. The class IOException can extend the functionality of the class Exception by adding new types and methods and by overriding existing ones.

Just like abstraction is closely related with generalization, the inheritance is closely related with specialization. It is important to discuss those two concepts together with generalization to better understand and to reduce the complexity.

One of the most important relationships among objects in the real world is specialization, which can be described as the “is-a” relationship. When we say that a dog is a mammal, we mean that the dog is a specialized kind of mammal. It has all the characteristics of any mammal (it bears live young, nurses with milk, has hair), but it specializes these characteristics to the familiar characteristics of canis domesticus. A cat is also a mammal. As such, we expect it to share certain characteristics with the dog that are generalized in Mammal, but to differ in those characteristics that are specialized in cats.

The specialization and generalization relationships are both reciprocal and hierarchical. Specialization is just the other side of the generalization coin: Mammal generalizes what is common between dogs and cats, and dogs and cats specialize mammals to their own specific subtypes.

Similarly, as an example you can say that both IOException and SecurityException are of type Exception. They have all characteristics and behaviors of an Exception, That mean the IOException is a specialized kind of Exception. A SecurityException is also an Exception. As such, we expect it to share certain characteristic with IOException that are generalized in Exception, but to differ in those characteristics that are specialized in SecurityExceptions. In other words, Exception generalizes the shared characteristics of both IOException and SecurityException, while IOException and SecurityException specialize with their characteristics and behaviors.

In OOP, the specialization relationship is implemented using the principle called inheritance. This is the most common and most natural and widely accepted way of implement this relationship.

4.17. What is Polymorphisms?

Polymorphisms is a generic term that means ‘many shapes’. More precisely Polymorphisms means the ability to request that the same operations be performed by a wide range of different types of things.

At times, I used to think that understanding Object Oriented Programming concepts have made it difficult since they have grouped under four main concepts, while each concept is closely related with one another. Hence one has to be extremely careful to correctly understand each concept separately, while understanding the way each related with other concepts.

In OOP the polymorphisms is achieved by using many different techniques named method overloading, operator overloading and method overriding,

4.18. What is Method Overloading?

The method overloading is the ability to define several methods all with the same name.

Collapse | Copy Code
public class MyLogger
{
    public void LogError(Exception e)
    {
        // Implementation goes here
    }

    public bool LogError(Exception e, string message)
    {
        // Implementation goes here
    }
}

4.19. What is Operator Overloading?

The operator overloading (less commonly known as ad-hoc polymorphisms) is a specific case of polymorphisms in which some or all of operators like +, – or == are treated as polymorphic functions and as such have different behaviors depending on the types of its arguments.

Collapse | Copy Code
public class Complex
{
    private int real;
    public int Real
    { get { return real; } }

    private int imaginary;
    public int Imaginary
    { get { return imaginary; } }

    public Complex(int real, int imaginary)
    {
        this.real = real;
        this.imaginary = imaginary;
    }

    public static Complex operator +(Complex c1, Complex c2)
    {
        return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
    }
}

I above example I have overloaded the plus operator for adding two complex numbers. There the two properties named Real and Imaginary has been declared exposing only the required “get” method, while the object’s constructor is demanding for mandatory real and imaginary values with the user defined constructor of the class.

4.20. What is Method Overriding?

Method overriding is a language feature that allows a subclass to override a specific implementation of a method that is already provided by one of its super-classes.

A subclass can give its own definition of methods but need to have the same signature as the method in its super-class. This means that when overriding a method the subclass’s method has to have the same name and parameter list as the super-class’s overridden method.

Collapse | Copy Code
using System;
public class Complex
{
    private int real;
    public int Real
    { get { return real; } }

    private int imaginary;
    public int Imaginary
    { get { return imaginary; } }

    public Complex(int real, int imaginary)
    {
        this.real = real;
        this.imaginary = imaginary;
    }

    public static Complex operator +(Complex c1, Complex c2)
    {
        return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
    }

    public override string ToString()
    {
        return (String.Format("{0} + {1}i", real, imaginary));
    }
}

In above example I have extended the implementation of the sample Complex class given under operator overloading section. This class has one overridden method named “ToString”, which override the default implementation of the standard “ToString” method to support the correct string conversion of a complex number.

Collapse | Copy Code
Complex num1 = new Complex(5, 7);
Complex num2 = new Complex(3, 8);

// Add two Complex numbers using the
// overloaded plus operator
Complex sum = num1 + num2;

// Print the numbers and the sum
// using the overriden ToString method
Console.WriteLine("({0}) + ({1}) = {2}", num1, num2, sum);
Console.ReadLine();

4.21. What is a Use case?

A use case is a thing an actor perceives from the system. A use case maps actors with functions. Importantly, the actors need not be people. As an example a system can perform the role of an actor, when it communicate with another system.

usercase1.gif

In another angle a use case encodes a typical user interaction with the system. In particular, it:

  • Captures some user-visible function.
  • Achieves some concrete goal for the user.

A complete set of use cases largely defines the requirements for your system: everything the user can see, and would like to do. The below diagram contains a set of use cases that describes a simple login module of a gaming website.

usecaseLogin.gif

4.22. What is a Class Diagram?

A class diagrams are widely used to describe the types of objects in a system and their relationships. Class diagrams model class structure and contents using design elements such as classes, packages and objects. Class diagrams describe three different perspectives when designing a system, conceptual, specification, and implementation. These perspectives become evident as the diagram is created and help solidify the design.

The Class diagrams, physical data models, along with the system overview diagram are in my opinion the most important diagrams that suite the current day rapid application development requirements.

UML Notations:

notation.jpg

4.23. What is a Package Diagram?

Package diagrams are used to reflect the organization of packages and their elements. When used to represent class elements, package diagrams provide a visualization of the name-spaces. In my designs, I use the package diagrams to organize classes in to different modules of the system.

4.24. What is a Sequence Diagram?

A sequence diagrams model the flow of logic within a system in a visual manner, it enable both to document and validate your logic, and are used for both analysis and design purposes. Sequence diagrams are the most popular UML artifact for dynamic modeling, which focuses on identifying the behavior within your system.

4.25. What is two-tier architecture?

The two-tier architecture is refers to client/ server architectures as well, the term client/ server was first used in the 1980s in reference to personal computers (PCs) on a network. The actual client/ server model started gaining acceptance in the late 1980s, and later it was adapted to World Wide Web programming.

According to the modern days use of two-tier architecture the user interfaces (or with ASP.NET, all web pages) runs on the client and the database is stored on the server. The actual application logic can run on either the client or the server. So in this case the user interfaces are directly access the database. Those can also be non-interface processing engines, which provide solutions to other remote/ local systems. In either case, today the two-tier model is not as reputed as the three-tier model. The advantage of the two-tier design is its simplicity, but the simplicity comes with the cost of scalability. The newer three-tier architecture, which is more famous, introduces a middle tier for the application logic.

2-Tier.jpg

4.26. What is three-tier architecture?

The three tier software architecture (also known as three layer architectures) emerged in the 1990s to overcome the limitations of the two tier architecture. This architecture has aggressively customized and adopted by modern day system designer to web systems.

Three-tier is a client-server architecture in which the user interface, functional process logic, data storage and data access are developed and maintained as independent modules, some time on separate platforms. The term “three-tier” or “three-layer“, as well as the concept of multi-tier architectures (often refers to as three-tier architecture), seems to have originated within Rational Software.

3-Tier.jpg

The 3-Tier architecture has the following three tiers.

  1. Presentation Tier or Web Server: User Interface, displaying/ accepting data/ input to/ from the user
  2. Application Logic/ Business Logic/ Transaction Tier or Application Server: Data validation, acceptability check before being added to the database and all other business/ application specific operations
  3. Data Tier or Database server: Simple reading and writing method to database or any other storage, connection, command, stored procedures etc

4.27. What is MVC architecture?

The Model-View-Controller (MVC) architecture separates the modeling of the domain, the presentation, and the actions based on user input into three separate classes.

Unfortunately, the popularity of this pattern has resulted in a number of faulty usages; each technology (Java, ASP.NET etc) has defined it in their own way making it difficult to understand. In particular, the term “controller” has been used to mean different things in different contexts. The definitions given bellow are the closes possible ones I found for ASP.NET version of MVC.

mvc.jpg

  1. Model: DataSet and typed DataSet (some times business object, object collection, XML etc) are the most common use of the model.
  2. View: The ASPX and ASCX files generally handle the responsibilities of the view.
  3. Controllers: The handling of events or the controlling is usually done in the code-behind class.

In a complex n-tier distributed system the MVC architecture place the vital role of organizing the presentation tier of the system.

4.28. What is SOA?

A service-oriented architecture is essentially a collection of services. These services communicate with each other. The communication can involve either simple data passing or it could involve two or more services coordinating some activity. Some means of connecting services to each other is needed.

The .Net technology introduces the SOA by mean of web services.

SOA.gif

The SOA can be used as the concept to connect multiple systems to provide services. It has it’s great share in the future of the IT world.

According to the imaginary diagram above, we can see how the Service Oriented Architecture is being used to provide a set of centralized services to the citizens of a country. The citizens are given a unique identifying card, where that card carries all personal information of each citizen. Each service centers such as shopping complex, hospital, station, and factory are equipped with a computer system where that system is connected to a central server, which is responsible of providing service to a city. As an example when a customer enter the shopping complex the regional computer system report it to the central server and obtain information about the customer before providing access to the premises. The system welcomes the customer. The customer finished the shopping and then by the time he leaves the shopping complex, he will be asked to go through a billing process, where the regional computer system will manage the process. The payment will be automatically handled with the input details obtain from the customer identifying card.

The regional system will report to the city (computer system of the city) while the city will report to the country (computer system of the country).

4.29. What is the Data Access Layer?

The data access layer (DAL), which is a key part of every n-tier system, is mainly consist of a simple set of code that does basic interactions with the database or any other storage device. These functionalities are often referred to as CRUD (Create, Retrieve, Update, and Delete).

The data access layer need to be generic, simple, quick and efficient as much as possible. It should not include complex application/ business logics.

I have seen systems with lengthy, complex store procedures (SP), which run through several cases before doing a simple retrieval. They contain not only most part of the business logic, but application logic and user interface logic as well. If SP is getting longer and complicated, then it is a good indication that you are burring your business logic inside the data access layer.

4.30. What is the Business Logic Layer?

I know for a fact that this is a question for most, but from the other hand by reading many articles I have become aware that not everyone agrees to what business logic actually is, and in many cases it’s just the bridge in between the presentation layer and the data access layer with having nothing much, except taking from one and passing to the other. In some other cases, it is not even been well thought out, they just take the leftovers from the presentation layer and the data access layer then put them in another layer which automatically is called the business logic layer. However there are no god said things that cannot be changed in software world. You can change as and when you feel comfortable that the method you apply is flexible enough to support the growth of your system. There are many great ways, but be careful when selecting them, they can over complicating the simple system. It is a balance one needs to find with their experience.

As a general advice when you define business entities, you must decide how to map the data in your tables to correctly defined business entities. The business entities should meaningfully define considering various types of requirements and functioning of your system. It is recommended to identify the business entities to encapsulate the functional/ UI (User Interface) requirements of your application, rather than define a separate business entity for each table of your database. For example, if you want to combine data from couple of table to build a UI (User Interface) control (Web Control), implement that function in the Business Logic Layer with a business object that uses couple of data object to support with your complex business requirement.

4.31. What is Gang of Four (GoF) Design Patterns?

The Gang of Four (GoF) patterns are generally considered the foundation for all other patterns. They are categorized in three groups: Creational, Structural, and Behavioral. Here you will find information on these important patterns.

Creational Patterns

      • Abstract Factory Creates an instance of several families of classes
      • Builder Separates object construction from its representation
      • Factory Method Creates an instance of several derived classes
      • Prototype A fully initialized instance to be copied or cloned
      • Singleton A class of which only a single instance can exist

Structural Patterns

      • Adapter Match interfaces of different classes
      • Bridge Separates an object’s interface from its implementation
      • Composite A tree structure of simple and composite objects
      • Decorator Add responsibilities to objects dynamically
      • Facade A single class that represents an entire subsystem
      • Flyweight A fine-grained instance used for efficient sharing
      • Proxy An object representing another object

Behavioral Patterns

    • Chain of Resp. A way of passing a request between a chain of objects
    • Command Encapsulate a command request as an object
    • Interpreter A way to include language elements in a program
    • Iterator Sequentially access the elements of a collection
    • Mediator Defines simplified communication between classes
    • Memento Capture and restore an object’s internal state
    • Observer A way of notifying change to a number of classes
    • State Alter an object’s behavior when its state changes
    • Strategy Encapsulates an algorithm inside a class
    • Template Method Defer the exact steps of an algorithm to a subclass
    • Visitor Defines a new operation to a class without change

4.32. What is the difference between Abstract Factory and Builder design patterns?

The two design patterns are fundamentally different. However, when you learn them for the first time, you will see a confusing similarity. So that it will make harder for you to understand them. But if you continue to study eventually, you will get afraid of design patterns too. It is like infant phobia, once you get afraid at your early age, it stays with you forever. So the result would be that you never look back at design patterns again. Let me see whether I can solve this brain teaser for you.

In the image below, you have both design pattern listed in. I am trying to compare the two one on one to identify the similarities. If you observe the figure carefully, you will see an easily understandable color pattern (same color is used to mark the classes that are of similar kind).

Factory and Builder

Please follow up with the numbers in the image when reading the listing below.

Mark #1: Both patterns have used a generic class as the entry-class. The only difference is the name of the class. One pattern has named it as “Client”, while the other named it as “Director”.
Mark #2: Here again the difference is the class name. It is “AbstractFactory” for one and “Builder” for the other. Additionally both classes are of type abstract.
Mark #3: Once again both patterns have defined two generic (WindowsFactory & ConcreteBuilder) classes. They both have created by inheriting their respective abstract class.
Mark #4: Finally, both seem to produce some kind of a generic output.

Now, where are we? Aren’t they looking almost identical? So then why are we having two different patterns here?

Let’s compare the two again side by side for one last time, but this time, focusing on the differences.

  • Abstract Factory: Emphasizes a family of product objects (either simple or complex)
  • Builder: Focuses on constructing a complex object step by step
  • Abstract Factory: Focus on *what* is made
  • Builder: Focus on *how* it is made
  • Abstract Factory: Focus on defining many different types of *factories* to build many *products*, and it is not a one builder for just one product
  • Builder: Focus on building a one complex but one single *product*
  • Abstract Factory: Defers the choice of what concrete type of object to make until run time
  • Builder: Hide the logic/ operation of how to compile that complex object
  • Abstract Factory: *Every* method call creates and returns different objects
  • Builder: Only the *last* method call returns the object, while other calls partially build the object

Sometimes creational patterns are complementary: So you can join one or many patterns when you design your system. As an example builder can use one of the other patterns to implement which components get built or in another case Abstract Factory, Builder, and Prototype can use Singleton in their implementations. So the conclusion would be that the two design patterns exist to resolve two type of business problems, so even though they look similar, they are not.

I hope that this shed some light to resolve the puzzle. If you still don’t understand it, then this time it is not you, it has to be me and it is since that I don’t know how to explain it.

5. What is the Conclusion?

I don’t think, that it is realistic trying to make a programming language be everything to everybody. The language becomes bloated, hard to learn, and hard to read if everything plus the kitchen sink is thrown in. In another word every language has their limitations. As system architect and designer we should be able to fully and more importantly correctly (this also mean that you shouldn’t use a ballistic missile to kill a fly or hire FBI to catch the fly) utilize the available tools and features to build usable, sustainable, maintainable and also very importantly expandable software systems, that fully utilize the feature of the language to bring a competitively advance system to their customers. In order to do it, the foundation of a system places a vital role. The design or the architecture of a software system is the foundation. It hold the system together, hence designing a system properly (this never mean an *over* desinging) is the key to the success. When you talk about designing a software system, the correct handling of OOP concept is very important. I have made the above article richer with idea but still kept it short so that one can learn/ remind all of important concept at a glance. Hope you all will enjoy reading it.

Finally, after reading all these, one may argue with me saying that anybody can write all these concept definitions but do I know how/ when to apply them in real world systems. So for them to see these concepts being applied in real world systems, please check the source code of the latest of my open-source project name Rocket Framework.

Note: For newbies Rocket Framework is going to be little too advance but check it, use it and review it if you have any questions/ criticisms around my design don’t hesitate to shoot them here or there..

6. What I Referred?

IIS Documentation


Introduction

When request come from client to the server a lot of operation is performed before sending response to the client. This is all about how IIS Process the request.  Here I am not going to describe the Page Life Cycle and there events, this article is all about the operation of IIS Level.  Before we start with the actual details, let’s start from the beginning so that each and everyone understand it’s details easily.  Please provide your valuable feedback and suggestion to improve this article.

What is Web Server ?

When we run our ASP.NET Web Application from visual studio IDE, VS Integrated ASP.NET Engine is responsible to execute all kind of asp.net requests and responses.  The process name is “WebDev.WebServer.Exe” which actually take care of all request and response of an web application which is running from Visual Studio IDE.

Now, the name “Web Server” come into picture when we want to host the application on a centralized location and wanted to access from many locations. Web server is responsible for handle all the requests that are coming from clients, process them and provide the responses.

What is IIS ?

IIS (Internet Information Server) is one of the most powerful web servers from Microsoft that is used to host your ASP.NET Web application. IIS has it’s own ASP.NET Process Engine  to handle the ASP.NET request. So, when a request comes from client to server, IIS takes that request and  process it and send response back to clients.

Request Processing :

Hope, till now it’s clear to you that what is Web server and IIS is and what is the use of them. Now let’s have a look how they do things internally. Before we move ahead, you have to know about two main concepts

1.    Worker Process
2.    Application Pool
Worker Process:  Worker Process (w3wp.exe) runs the ASP.Net application in IIS. This process is responsible to manage all the request and response that are coming from client system.  All the ASP.Net functionality runs under the scope of worker process.  When a request comes to the server from a client worker process is responsible to generate the request and response. In a single word we can say worker process is the heart of ASP.NET Web Application which runs on IIS.

Application Pool:  Application pool is the container of worker process.  Application pools is used to separate sets of IIS worker processes that share the same configuration.  Application pools enables a better security, reliability, and availability for any web application.  The worker process serves as the process boundary that separates each application pool so that when one worker process or application is having an issue or recycles, other applications or worker processes are not affected. This makes sure that a particular web application doesn’t not impact other web application as they they are configured into different application pools.

Application Pool with multiple worker process is called “Web Garden”.

Now, I have covered all the basic stuff like Web server, Application Pool, Worker process. Now let’s have look how IIS process the request when a new request comes up from client.

If we look into the IIS 6.0 Architecture, we can divided them into Two Layer
1.    Kernel Mode
2.    User Mode

Now, Kernel mode is introduced with IIS 6.0, which contains the HTTP.SYS.  So whenever a request comes from Client to Server, it will hit HTTP.SYS First.

Now, HTTP.SYS is Responsible for pass the request to particular Application pool. Now here is one question, How HTTP.SYS comes to know where to send the request?  This is not a random pickup. Whenever we creates a new Application Pool, the ID of the Application Pool is being generated and it’s registered with the HTTP.SYS. So whenever HTTP.SYS Received the request from any web application, it checks for the Application Pool and based on the application pool it send the request.

So, this was the first steps of IIS Request Processing.

Till now, Client Requested for some information and request came to the Kernel level of IIS means at HTTP.SYS. HTTP.SYS has been identified the name of the application pool where to send. Now, let’s see how this request moves from HTTP.SYS to Application Pool.

In User Level of IIS, we have Web Admin Services (WAS) which takes the request from HTTP.SYS and pass it to the respective application pool.

When Application pool receive the request, it simply pass the request to worker process (w3wp.exe) . The worker process “w3wp.exe” looks up the URL of the request in order to load the correct ISAPI extension. ISAPI extensions are the IIS way to handle requests for different resources. Once ASP.NET is installed, it installs its own ISAPI extension (aspnet_isapi.dll) and adds the mapping into IIS.

Note : Sometimes if we install IIS after installing asp.net, we need to register the extension with IIS using aspnet_regiis command.

When Worker process loads the aspnet_isapi.dll, it start an HTTPRuntime, which is the entry point of an application. HTTPRuntime is a class which calls the ProcessRequest method to start Processing.

When this methods called, a new instance of HTTPContext is been created.  Which is accessible using HTTPContext.Current  Properties. This object still remains alive during life time of object request.  Using HttpContext.Current we can access some other objects like Request, Response, Session etc.

After that HttpRuntime load an HttpApplication object with the help of  HttpApplicationFactory class.. Each and every request should pass through the corresponding HTTPModule to reach to HTTPHandler, this list of module are configured by the HTTPApplication.

Now, the concept comes called “HTTPPipeline”. It is called a pipeline because it contains a set of HttpModules ( For Both Web.config and Machine.config level) that intercept the request on its way to the HttpHandler. HTTPModules are classes that have access to the incoming request. We can also create our own HTTPModule if we need to handle anything during upcoming request and response.

HTTP Handlers are the endpoints in the HTTP pipeline. All request that are passing through the HTTPModule should reached to    HTTPHandler.  Then  HTTP Handler  generates the output for the requested resource. So, when we requesting for any aspx web pages,   it returns the corresponding HTML output.

All the request now passes from  httpModule to  respective HTTPHandler then method and the ASP.NET Page life cycle starts.  This ends the IIS Request processing and start the ASP.NET Page Lifecycle.

Conclusion

When client request for some information from a web server, request first reaches to HTTP.SYS of IIS. HTTP.SYS then send the request to respective  Application Pool. Application Pool then forward the request to worker process to load the ISAPI Extension which will create an HTTPRuntime Object to Process the request via HTTPModule and HTTPHanlder. After that the ASP.NET Page LifeCycle events starts.

This was just overview of IIS Request Processing to let Beginner’s know how the request get processed in backend.  If you want to learn in details please check the link for Reference and further Study section.

Rich Custom Error Handling with ASP.NET


Introduction

The quality of a site should be measured not only by how well it works, but by how gracefully it fails. While developers need detailed error reports while debugging, visitors to the site should be shielded from these. Technical errata only serve to confuse, disappoint, and reveal cracks in the armor.

If an error page is displayed, it should serve both developers and end-users without sacrificing aesthetics. An ideal error page maintains the look and feel of the site, offers the ability to provide detailed errors to internal developers—identified by IP address—and at the same time offers no detail to end users. Instead, it gets them back to what they were seeking—easily and without confusion. The site administrator should be able to review errors encountered either by e-mail or in the server logs, and optionally be able to receive feedback from users who run into trouble. Is this the stuff of dreams? No more.

There are several obstacles standing between the current built-in features of ASP.NET 1.1 and realizing the ideal. For one, the built-in detailed error page is fixed and cannot be customized. Further, a custom error page (as set in web.config) does not have access to the last error thrown, so it is really only useful to make the apology prettier. While thecustomErrors tag in web.config has a property to provide the custom page to external users and the detailed error page only to the local user (mode=RemoteOnly), how many developers debug at the server console?

All these problems can be solved, but first it helps to understand the basics. Peter Bromberg wrote two resources on exception handling that everyone should read as a prerequisite for this article: Documenting Exceptional Developers and Build a Really Useful ASP.NET Exception Engine. In addition, source code is provided with this article (click the link near the top of this page) for a complete rich custom error system. As with my previous MSDN article, the sample is from my favorite fake Swedish journal of finance: Fjorbes Online. All these online resources will introduce you to the basics. Now let’s see how to put it all together to bring error handling from the dark ages to the space age.

Errors Raise Exceptions

When errors happen, an exception is raised or thrown. There are three layers at which you may trap and deal with an exception: in a try…catch…finally block, at the Page level, or at the Application level. The first two happen right inside a page’s code, and code for application events is kept inside global.asax.

The Exception object contains information about the error, and as the event bubbles up through the layers, it is wrapped in further detail. In rough terms, the Application_Errorexception contains the Page_Error exception, which expands on the base Exception, which triggered the bubbling in the first place.

The Exception Class

Not surprisingly, the call to get the last error is Server.GetLastError() and it returns an object of type Exception:

   Dim err As Exception = Server.GetLastError()

You will find an Exception class reference here. Some of the properties and methods of the Exception class are more useful than others. (See Table 1.)

Table 1. Exception class properties and methods rated for usefulness

Property / Method() Return Type Description
Message String The error message. Useful. Available with debugging on or off.
Source String The application or object that caused the error. Not of much use when an .aspx file fails, as .NET generates a random name when it compiles an .aspx into IL (for example, “MyPage.aspx” can become “ecpgatxa”). Reasonably useful for debugging classes and controls.
StackTrace String When execution ends, the stack is unwound. This means that every call from the original page request, down to the line that triggered the error, is popped off the execution stack and noted. Happily, even line numbers are recorded in the base Exception when debugging is turned on. Only the method name is reported when debugging is off. This is highly useful.
TargetSite MethodBase The method that threw the Exception. This also shows up in the StackTrace. It is not as useful on its own.
HelpLink String Can hold a URL that might help the user, but usually doesn’t. Consider implementing it when throwing custom exceptions.
InnerException Exception The next error in the StackTrace. You can use InnerException to drill down through the complete list of exceptions to the originalException.
GetBaseException() Exception The Exception describing the original error. Since the original error might be wrapped up in the depths of InnerException, this method is essential to cut to the chase.
ToString() String Concatenates the above properties into a single string.

To see how the Exception looks as it bubbles up through each layer, consider the following sample Page_Load (with debugging turned on):

Sample Microsoft® Visual Basic® code

Sub Page_Load(ByVal src As Object, ByVal e As EventArgs)
   Throw New ApplicationException("This is an unhandled exception.")
End Sub

Try…Catch…Fail (Exception.Source=” yk1wsaam”)

Message: "This is an unhandled exception."

Stack Trace

at ASP.Default_aspx.Page_Load(Object src, EventArgs e) in C:\dev\CustomErrors\Default.aspx:line 5

Page_Error (Exception.Source=” yk1wsaam”)

Message: "This is an unhandled exception."

Stack Trace

at ASP.Default2_aspx.Page_Load(Object src, EventArgs e) in C:\dev\CustomErrors\Default.aspx:line 5 
at System.Web.UI.Control.OnLoad(EventArgs e) 
at System.Web.UI.Control.LoadRecursive() 
at System.Web.UI.Page.ProcessRequestMain()

Application_Error (Exception.Source=”System.Web”)

Message: "Exception of type System.Web.HttpUnhandledException was thrown."

Stack Trace

at System.Web.UI.Page.HandleError(Exception e) 
at System.Web.UI.Page.ProcessRequestMain() 
at System.Web.UI.Page.ProcessRequest() 
at System.Web.UI.Page.ProcessRequest(HttpContext context) 
at System.Web.CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute() 
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

At the Try…Catch…Fail layer, only the immediate Exception exists and Exception.Source is a random string of characters that ASP.NET uses to identify the IL version of Default.aspx.

At the Page level, the stack has unwound to show that the error happened during Page.ProcessRequestMain.

At the Application layer, something interesting happens. The Source changes to the slightly meaningful, “System.Web.” Everything above Page.ProcessRequestMain from the Page level exception has been rolled into the Page.HandleError(exception e) line. At the Application layer, that detail is still available by either using InnerException or getting straight to the original exception with GetBaseException().

Try…Catch…Finally

The sooner you catch and resolve an error, the better. There is a reason they are called exceptions and not rules. In most cases, you can stop problems before they become exceptions with simple validation. FileIO.File.Exists and String.Empty are your friends. When writing a new class, always provide a way to validate data. For example, this article’s sample code includes an IP address class (IPAddress.vb). While methods IsInRangeToLong, and ToIPAddress can throw exceptions, the Validate and IsEmptyOrZero functions do not. No one should rely on Try…Catch…Fail for validation.

When writing a line or block of code that could fail based on an uncontrollable condition, such as an unavailable object (like a missing database connection or Web service), it should be wrapped with Try…Catch…Finally.

Inside the Catch block, you have the option of throwing the exception higher to a Page and perhaps an Application error handler. While you can still recover gracefully (that is, without an apology) inside a Page_Error handler, you are not likely to write one for every page. No, the main reason to throw the Exception higher than the Catch block is to perform notification or logging in an Application_Error handler.

When throwing an Exception higher, don’t:

Throw New ApplicationException(e)

Do:

Throw

The former is the syntax for a brand new custom Exception. In a Catch you already have one in front of you. The latter is all you need to send the current Exception merrily up the chain of command for further handling. If you must add your own two cents, you can always:

   Catch e As System.Exception
      Throw New System.ApplicationException("My Two Cents", e)

This creates a new Exception that wraps up the original error as its InnerException. Now for a proper demonstration of Try…Catch…Finally.

Visual Basic:

Dim Conn as New _
SqlConnection("Server=sql.mySite.com;uid=myUser;password=myPass")
Dim Cmd As New _
SqlCommand("SELECT Title, URL FROM Article ORDER BY Title", Conn)
Dim IsDbAvailable as Boolean = True
try
   ' The database may not be available
Conn.Open
ArticleGrid.DataSource = Cmd.ExecuteReader
ArticleGrid.DataBind
catch e as Exception
   ' Executed if an error occurs
   IsDbAvailable = False
   Trace.Write ("Database unavailable with Message: ", e.Message)
Trace.Write ("Stack Trace: ", e.StackTrace)

   ' Throw the exception higher for logging and notification
   Throw
finally
   ' If any clean-up is required for either case (unmanaged objects 
   ' left open, etc.), do it here.
Conn.Close()
end try

C#:

New SqlConnection("Server=sql.mySite.com;uid=myUser;password=myPass") Conn;
New SqlCommand("SELECT Title, URL FROM Article ORDER BY Title", Conn) Cmd;

Boolean IsDbAvailable = True;
try {
   // The database may not be available
Conn.Open();
ArticleGrid.DataSource = Cmd.ExecuteReader();
ArticleGrid.DataBind();
}
catch (e as Exception) {
   // Executed if an error occurs
   IsDbAvailable = False;
   Trace.Write ("Database unavailable with Message: ", e.Message);
   Trace.Write ("Stack Trace: ", e.StackTrace);

   // Throw the exception higher for logging and notification
   throw;
}
finally {
   /* If any clean-up is required for either case (unmanaged objects 
      left open, etc.), do it here. */
   Conn.Close ()
}

You can have multiple Catch blocks, each overloaded to catch a different Exception type (ExceptionIndexOutOfRangeExceptionNullReferenceException, and so on). Chris Sully wrote an article, Error Handling in ASP.NET…, which both provides a reference table of exception types and makes terrific further reading.

Before going on, note that there is a school of thought that says you should always throw an exception higher, that “swallowing” the exception is a bad idea. The reasoning is that exceptions should be visible and logged so that they can be guarded against in the future (with improved infrastructure, scalability, and so on), and that any instances that might be swallowed could be avoided with better programming. This happens to be true. Swallowing an exception is fine while debugging, but production code should always throw exceptions higher. Then, whenever preventable exceptions show up in the logs, you can apply some validation to ensure they won’t happen again.

Page_Error

Page_Error and Application_Error are similar. They take the same arguments, and they can even contain the same code. In fact a Page_Error section on a test page is a great way to debug code intended for Application_Error.

Their differences are few. One goes inside the .aspx file (or its code-behind), and the other inside global.asax (or an IHttpHandler class assembly). Differences between their stack traces were noted earlier, but if you always use GetBaseException(), then you will always have the original error, making this difference irrelevant. Another point to note is that in Page_Error you can prevent an exception from bubbling up further on to Application_Error by invoking Context.ClearError(). While useful for debugging (to avoid clogging the error log), this is not good practice in production code.

The following sample code adds the error to the trace information. The page will not finish loading once the exception is raised, so a brief apology is presented. Note that this simply shows the mechanics of Page_Error; actually helping the user out is an exercise left to the reader.

Visual Basic:

Sub Page_Load(ByVal src As Object, ByVal args As EventArgs)
   Throw New ApplicationException("This is an unhandled exception.")
End Sub

Sub Page_Error(ByVal src As Object, ByVal args As EventArgs) Handles MyBase.Error
   Dim e As System.Exception = Server.GetLastError()
   Trace.Write("Message", e.Message)
   Trace.Write("Source", e.Source)
   Trace.Write("Stack Trace", e.StackTrace)
   Response.Write("Sorry, an error was encountered.")
Context.ClearError()
End Sub

C#:

void Page_Load(Object src, EventArgs args) {
   // raise an intentional exception to get the ball rolling
   throw new ApplicationException("This is an unhandled exception.");
}

void Page_Error(Object sender, EventArgs args) {
   Response.Write("Error:\n");
   Exception e = Server.GetLastError();
   Trace.Write("Message",e.Message);
   Trace.Write("Source",e.Source);
   Trace.Write("Stack Trace",e.StackTrace);
Response.Write("Sorry, an error was encountered.");
   Context.ClearError();
}

Some people believe that putting code into an override of the Page‘s OnError event is equivalent to putting it in the Page_Error event. It isn’t. OnError hands control to a privateHandleError method. This is where ASP.NET checks whether customErrors is turned on and redirects when an exception is raised. It is where ASP.NET checks whether tracing is turned on and adds its own bit about the exception just raised. The main reason to override OnError is to replace this behavior with your own (described later). There is no good reason to put other code there. If someone does decide to turn on the built-in customErrors, code sitting in OnError will get in the way. If someone decides to add code toPage_Error it will not fire, as OnError fires first. To do error-handling at the Page level, use Page_Error.

global.asax: Application_Error

Generating e-mail notification, logging errors to the Event Log, and the structure of global.asax are covered wonderfully in many books and articles. Here are two good references:

The source code provided with the article implements these in global.asax and uses these web.config declarations:

<appSettings>
  <add key="customErrorAutomaticLogging" value = "On/Off" />
  <add key="customErrorAutomaticEmail" value="On/Off"/>
  <add key="customErrorEmailAddress" value="errors@mySite.com" />
</appSettings>

The interesting part is the construction of rich error messages.

Rich Custom Error Pages

There are four pieces to the puzzle:

  1. Configuring behavior in web.config. The choices are either to use the built-in customErrors tag with its mode and defaultRedirect properties, or to build custom settings in the appSettings section.
  2. Capturing, logging, and storing the Exception (in global.asax). The Exception needs to be stored inside an object that will persist until the custom error page. Possibilities are: ApplicationContextCookies, and QueryString. Other notification (e-mail, pager, and so on) can occur here too.
  3. Passing control from global.asax to the custom error page. Methods include using the built-in customErrors method, Server.Transfer(), or Response.Redirect().
  4. Retrieving and displaying the custom error message. Logic to display detailed information only to certain IP addresses may be included here.

Aa479319.customerrors_01(en-us,MSDN.10).gif

 

 

Figure 1. Flow of custom error handler

Unfortunately, you cannot pick and choose among all these options; some can only be implemented certain ways. For example, you cannot store the Exception in Context.Itemsand retrieve it after a Response.Redirect() since the Redirect() creates a brand new Context. The Exception would disappear. Here is a list of which storage baskets work with which control-passing methods:

Storage Basket Control-passing methods that work
Application Response.Redirect()Server.Transfer(), or customErrors:defaultRedirect
Cookies Response.Redirect()Server.Transfer(), or customErrors:defaultRedirect
ContextSession Server.Transfer()
QueryString Response.Redirect() or Server.Transfer()

While Application works with all three, it does not scale without a way to identify which session triggered the error. If two users trigger nearly simultaneous errors, you do not want one to overwrite the other. An advantage of Application is that it can store the complete Exception object.

Cookie storage also works with all three, and the client that triggered the error is guaranteed to see the proper error message. The caveats are that cookies must be enabled on the client, and they place an extra burden on bandwidth, which raises a scalability issue. Since you can only store strings and not complete objects to a cookie, you need to decide which strings to pass. XML serialization of an Exception is prevented by internal security issues, but binary or custom serialization is an option.

Context and Session, while limited to Server.Transfer(), both provide the advantage that the entire Exception object may be stored, without the client identification steps required to store the object to Application.

QueryString is an interesting option first described by Donny Mack in ASP.NET: Tips, Tutorials and Code (Mitchell, Mack, Walther, et al., SAMS Publishing, 2001). While you can’t stuff a complete Exception into QueryString and must choose which strings to pass, it does avoid local storage overhead completely and would seem to scale the best.

The sample code provided with this article implements all of these methods except Session, which would not be an improvement on Context.

Implementation

Now let’s look in more detail at the four steps mentioned above to construct rich custom error pages.

Configuring Behavior

The customErrors setting has three options for the mode property: On, Off, and RemoteOnly. The defaultRedirect property sets the custom error page. You can usecustomErrors in combination with your own appSettings, which you might do to control events in global.asax (like event logging). ASP.NET transfers control from global.asax to the custom page by generating a default OnError method in the Page‘s event cycle. You can replace the generated method with your own. The code goes something like this (if “myErrorPage.aspx” is the defaultRedirect value):

Visual Basic:

Protected Overrides Sub OnError(ByVal args As EventArgs)
    Response.Redirect("myErrorPage.aspx?aspxerrorpath=" & _
        Request.Path, True)
End Sub

C#:

protected override void OnError(EventArgs args) {
    Response.Redirect("myErrorPage.aspx?aspxerrorpath=" + 
        Request.Path, true);
}

The True tells ASP.NET to end the current request and proceed. Omitting it would imply the default false, and require an extra line to explicitly call Response.End.

Unfortunately, there is no easy way to override the Page OnError event for all pages on a site (the ideal way to replace customErrors), short of subclassing Page, which would require a new reference at the top of each page. The source code provided uses a different method, relying instead on custom appSettings inside web.config:

   <appSettings>
      <add key="customErrorAutomaticLogging" value="On/Off" />
      <add key="customErrorAutomaticEmail" value="On/Off" />

      <add key="customErrorMethod" 
value="Application/Context/Cookie/QueryString/Off" />
      <add key="customErrorPage" value="myErrorPage.aspx" />
<add key="customErrorBranchMethod" value="Redirect/Transfer" />
      <add key="customErrorAllowReport" value="On/Off" />
      <add key="customErrorEmailAddress" value="errors@mySite.com" />
</appSettings>

Using appSettings in code is as simple as this:

if (System.Configuration.ConfigurationSettings.AppSettings _
("customErrorAutomaticLogging").ToLower) = "on"

Settings can be added for other functions. For example, you might need to define a connection string for a central error log on a particular server.

Capturing, Logging, and Storing

The top of global.asax imports three namespaces: System.IOSystem.Diagnostics, and Msdn.ErrorIO. The Msdn.ErrorIO class is provided in the download as ErrorIO.vb.

This line of Application_Error captures the Exception and converts it to a string for logging or notification:

   Dim objError As Exception = Server.GetLastError.GetBaseException

In C# this is written over two lines:

   Exception objError = Server.GetLastError();
objError = objError.GetBaseException();

It was shown that the Page and Application layers stuff the original Exception in their own Exception wrappers as the call stack unwinds. While Server.GetLastError returns this whole wrapped package, GetBaseException pulls out the original Exception that interrupted execution.

The error is next logged and e-mailed to an administrator depending on web.config settings (see the section, global.asax: Application_Error). Functions WriteErrorToLog() andEmailError() are included in global.asax. Note that their catch blocks are empty, effectively swallowing any problems with writing to the event log or sending e-mail. This is done to avoid throwing a new Exception inside the handler and either creating an endless loop or having ASP.NET default to its own handler. However, it is never preferred to swallow errors. One solution would be to store a message (for example, HandlerMessage) along with the Exception to describe any problems with the exception handler itself. Such a message could appear with the original error on the custom error page. The WriteErrorToLog and EmailError functions allow for this by returning a true or false based on their success, though this feature is not implemented in the source provided.

Four storage models are implemented in the source code. You will find each represented by a class in ErrorIO.vbErrorApplicationErrorCookieErrorContext, andErrorQueryString. Since all classes use the same methods (StoreRetrieve, and Clear), a single interface (IErrorIOHandler) is provided for all three, plus an ErrorIOFactory class with a Create(model) method that allows the storage model to be selected at runtime. The advantage of using the Factory Pattern here is that you can declare the model to use in web.config and switch between them freely. Switching to a new model does not require changing any source code, only the web.config declaration. Of course you can still explicitly choose a model by creating an instance of, say, ErrorContext and using its StoreRetrieve, and Clear methods directly.

In the source, the storage basket is created like this:

   Dim objErrorIOFactory As New Msdn.RichErrors.ErrorIOFactory
   Dim objErrorBasket As MSDN.RichErrors.IErrorIOHandler
   objErrorBasket = objErrorIOFactory.Create(strErrorMethod)

Yes, it takes three lines to create an ErrorIOFactory, create a storage basket, and to connect the object created by the Factory to the basket. It’s the price of flexibility. As an alternative, you can hardcode the type of basket used, like so:

   Dim objErrorBasket as ErrorContext = New ErrorContext()

Instead of ErrorContext, you could similarly create an instance of ErrorApplicationErrorCookie, or ErrorQueryString. Whichever you choose, this is how the exception is stored:

   Dim strRedirect, strQueryString, strFilePath As String 
   strRedirect = AppSettings("customErrorPage")
   strQueryString = objErrorBasket.Store(objError)
   strFilePath = strRedirect & strQueryString

Hmmm, that probably wasn’t what you expected. You may be asking, “What’s this about building strFilePath? The result of objErrorBasket.Store() is a QueryString?!” Well, back in the section on configuring behavior, you saw the default ASP.NET way of implementing customErrors, and it went like this:

Response.Redirect("myErrorPage.aspx?aspxerrorpath=" & Request.Path, True)

To recreate this behavior, each Store() method in the ErrorIO classes generates the aspxerrorpath parameter. The ErrorQueryString class goes a step further and stores parts of the error (MessageSource, and StackTrace) plus a DateTime stamp in additional parameters. Combining the customErrorPage defined in web.config with the query string generated during the Store() results in a string that can be used with either Response.Redirect(strFilePath) or Server.Transfer(strFilePath).

Refer to the source to see exactly how each of the four storage baskets work; each has unique traits. When naming Application identifiers, ErrorApplication.Store() appends the client IP address so each client is sure to receive his own message. ErrorCookie.Store() uses one multi-part cookie rather than four separate cookies to get the job done.ErrorContext.Store() is the simplest the bunch; nothing tricky about it. QueryString.Store() uses a fast StringBuilder to generate the query string, which it initializes as 512 chars (the default is 16) to cut down on internal resizing steps.

Since some of the storage baskets provided store strings and not objects, the decision was made to store: Exception.MessageException.SourceException.StackTrace, theDate.Now marking the Exception, and the Request.Filepath (the Web page requested). The source can be modified to record other properties of Exception, the server name, client IP, or whatever meets your debugging requirements.

The web.config <appSettings> tag to turn rich custom errors on and set the storage basket is:

<add key="customErrorMethod" 
value="Application/Cookie/Context/QueryString/Off" />

Setting this value to Off prevents the remaining steps from occurring, but will not get in the way of any automatic logging or notification already done.

Passing Control

The final task of Application_Error is to execute the Redirect() or Transfer(). From the discussion of configuring behavior above, you already know that which of these you choose is tied to how the Exception is stored, and that some combinations work while others don’t. The features of the storage methods usually drive the decision.

But occasionally, features of Redirect() and Transfer() drive the decision. Redirect creates a new ContextTransfer does not. Redirect requires a round-trip to the browser,Transfer does not. As a result of this round-trip, Redirect rewrites the URL to reflect the location of the error page, Transfer does not.

If this seems to be an argument in favor of Transfer, it isn’t. The built-in customErrors feature uses Redirect and not Transfer for a reason. The rationale of the ASP.NET development team is that Redirect accurately displays the URL of the custom error page, while Server.Transfer is intended for “switchboard”-style pages (as on content management sites) where the true URL is preferably hidden.

Therefore, while Context is one of the more convenient ways to move the Exception from Application_Error to the rich error page, its dependence on Server.Transfer() makes it less than perfect. While you may not be concerned that this approach breaks a tenet of the design philosophy of ASP.NET, be aware that it does.

The web.config <appSettings> tags to set the control-passing method and identify the custom error pages are:

<add key="customErrorBranchMethod" value="Redirect/Transfer" />
<add key="customErrorPage" value ="myErrorPage.aspx" />

Retrieving and Displaying

Finally, the Exception must be retrieved from its storage basket and displayed in the rich error page. In the sample, this page is called myErrorPage.aspx.

In the sample code, the Exception is retrieved in myErrorPage.aspx, inside the DisplayDetailedError() function.

   Dim objErrorIOFactory As New Msdn.ErrorIO.ErrorIOFactory
   Dim objErrorBasket As Msdn.ErrorIO.IErrorIOHandler
objErrorBasket = objErrorIOFactory.Create( _ 
System.Configuration.ConfigurationSettings.AppSettings("customErrorMethod") )
   objErrorBasket.Retrieve(strMessage, strSource, 
     strStackTrace, strDate, strQueryString)
   objErrorBasket.Clear()

The first three lines are familiar; a similar series was used to create the basket to Store() the Exception.

Retrieve() passes five parameters by reference. These will come back holding the exception data. The actual Retrieve methods (in ErrorIO.vb) are similar to their Store()counterparts. The big difference is the use of Try…Catch…Fail to swallow errors that might occur while retrieving data from the baskets. Again, it is not desirable for an exception handler to throw exceptions of its own. If the Retrieve() fails, the error data returned instead describes the type of retrieve attempted (ApplicationCookieContext, orQueryString). Try…Catch…Fail is not used in QueryString.Retrieve(), it being the only technique that cannot generate exceptions of its own.

Finally objErrorBasket.Clear is called. Two of the storage baskets can or should be destroyed explicitly. Since Application is unique for each client (it uses the IP Address to name each identifier), it must be destroyed once used, and even then there is a chance this technique will leak memory.

So too should cookies be destroyed. Cookies are set to expire in thirty minutes, but a user can trigger any number of errors in this span. Thirty seconds would make more sense, but the expiration is based on the server’s clock, not the client’s. Have you seen how far off some system clocks are? Thirty minutes is a realistic term, most clocks should be within that span of each other. But this is the problem with short-term cookies. Explicit destruction is the best answer.

ErrorContext.Clear() and ErrorQueryString.Clear() have nothing to do, as these baskets ceases to exist once the rich error page is emitted to the client.

The sample rich error page has three display features:

  • Standard Error Message. The standard message, intended for public consumption, explains that an error occurred while loading the requested page and provides a link to try loading the page again. Links are also provided to get the user back to familiar ground—in this case back to the home page. If your site has standard navigation or menu bars, be sure to include them in the error page as well.The last thing you want is for someone to hit a brick wall of no return. Get the user back on track. Some sites parse the page request to seed a search of either the current site or the whole Web with a message like, “We couldn’t service your request but maybe this will help.” Helpful is good.
  • Error Report Panel. A form asking the user what was expected when the error happened is a good way to trace issues. This sample panel says, “If you describe what you were trying to do, perhaps it can be fixed.” Reports are e-mailed to the administrator along with the Exception.ToString data. The code in SendClick(), which sends the actual message, is similar to the EmailError() function in global.asax. This feature is configured with the web.config <appSettings> keys:

    <add key="customErrorAllowReport" value="On"/>
    <add key="customErrorEmailAddress" value="errors@mySite.com"/>
  • Detailed Error Panel. This panel (populated in the DisplayDetailedError() function) reports the exception raised by the error, as retrieved from the storage basket. This information is useful to those debugging the site, but not the general public. While you could add authentication to distinguish the two, not all sites need authentication. The built-in customErrors feature has a switch (mode="remoteOnly") to only display detailed information to the client at 10.0.0.1, but developers rarely have access to the server console (Why are so many errors only reproducible on the live server?). The way to overcome this limitation is to make a custom IP address class with range checking. Table 2 shows the methods for this class.Table 2. IPAddress Class (namespace: Msdn.IPUtils, source: IPAddress.vb)
    Method Description
    Validate() Test for a valid IP address with a regular expression.
    IsInRange() Check an IP address against a specified range.
    ToString() Return a value of type String.
    ToLong() Returns the IP address as a 12-digit Long (for example, “10.0.0.255” becomes 010000000255). Helpful for a variety of comparisons.
    ToIPAddress() Returns a value of type System.Network.IPAddress.

    This panel is displayed if the client’s IP address is within the range declared by web.config <appSettings>:

    <add key=”customErrorIpRangeMin” value=”10.0.0.1″/>

    <add key=”customErrorIpRangeMax” value=”10.0.0.255″/>

The Return of Page_Error

Debugging custom error pages is a pain. In addition to a local Page_Error handler, it helps to turn on tracing and debugging so you can capture and display problems without throwing the Exception all the way up to Application_Error. Once your custom error page works, turn these off again. While you can just forget about Page_Error, you will be glad it’s there during routine maintenance, or whenever you add new errors.

Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components


Introduction

Have you ever worked on an ASP.NET application and designed some useful functionality or feature set that you wanted to be able to easily reuse in another ASP.NET application? ASP.NET offers different tools for componentizing different types of functionality. The two most common tools for reuse in ASP.NET are:

  • User Controls and custom, compiled server controls for user interface elements and functionality.
  • .NET class libraries for business logic and data access code.

Two ASP.NET reuse tools that don’t get much attention are HTTP modules and handlers.

If you’re not familiar with what HTTP handlers and modules are, don’t worry. We’ll talk more about them later on in this article. For now, just understand that HTTP modules are classes that can be configured to run in response to events that fire during the request for an ASP.NET resource. An HTTP handler is a class that is responsible for rendering a particular resource, or a particular type of resource. In fact, each time you add an ASP.NET Web page to your project, you are essentially writing a HTTP handler. This is because when the HTML portion of an ASP.NET Web page gets dynamically compiled at run time, it directly or indirectly inherits from System.Web.UI.Page, which happens to be a HTTP handler implementation. This is true irrespective of whether you take the inline or code-behind strategy.

As you know, an ASP.NET application usually consists of a set of Web pages, which are invoked when they are requested by an end-user’s browser. As ASP.NET developers, most of the code we write is specific to a request for a particular Web page, such as code in a particular page’s code-behind class to display database results based on some search query. There are times, though, that we need to write code that is orthogonal to a single Web page, code that applies to all pages in an application. For example, we might want to track the order with which each user moves around our Web site. To do this, we’d need to have each page log the time of the request and information identifying the user.

One way to provide such logging functionality would be to add code that recorded the germane data in a database in the Page_Load event handler for each Web page on the site. This approach, however, is hardly maintainable or reusable. Each time we add a new ASP.NET page in our site, we’d need to make sure that we included the appropriate logging code. If we wanted to add similar functionality to another site, we’d need to go through each page in that site and add the requisite code. Ideally, the logging functionality would be logically and physically separate from the functionality of each individual page, and adding it to another site would be as simple as dropping an assembly in the site’s/bin directory.

Such reuse and maintainability is quite possible with HTTP modules and handlers. In this article, we are going to examine a set of HTTP modules and handlers that have been designed to make error logging a highly maintainable and reusable exercise. The goal of this article is to demonstrate how HTTP handlers and modules can be used as a very high-level form of componentization, enabling entire sets of functionalities to be developed, packaged, and deployed as a single unit and independent of Web applications. We’ll achieve this goal in large part through an examination of an application that benefits from reuse and componentization through HTTP handlers and modules.

ELMAH: Error Logging Modules And Handlers

The Error Logging Modules And Handlers (ELMAH), which we’ll be examining throughout this article, were written by coauthor Atif Aziz (http://www.raboof.com/) and demonstrate an easy means to add error logging capabilities to an ASP.NET Web application. ELMAH illustrates how HTTP modules and handlers can be used to provide a high degree of componentization for code that is orthogonal to the Web application (such as application-wide logging). ELMAH is a truly pluggable solution, meaning that it can be dynamically added to a running ASP.NET Web application without any need for recompilation or redeployment.

No matter how well written and tested a particular Web application may be, things will still go awry every now and then. It may not be your code at fault, it could be that the e-mail server is not responding, or some corruption of data causes a cryptographic failure. Regardless of the reason, when an exception occurs, especially on a live site, it is important that the details of the exception are recorded in order to assist with diagnosing the problem. ELMAH provides a mechanism for centralized error logging and notification. Whenever an exception occurs in an ASP.NET application that is not caught, ELMAH is notified and handles the exception as spelled out in the Web.config file. This may include recording the details of the exception to a database, sending an e-mail to an administrator, or both.

ELMAH isn’t designed to respond gracefully to unhandled exceptions. It simply records the details of unhandled exceptions. Once ELMAH has been added to an ASP.NET Web application, any unhandled exceptions raised in this application are logged. ELMAH doesn’t affect the end user’s experience when an unhandled exception occurs. They’ll still see the “Server Error” page, or, if you have custom errors configured to handle HTTP 500 errors, they’ll be redirected to a page with a more user-friendly message. But behind the scenes, ELMAH will have detected that an unhandled exception occurred and recorded the details.

ELMAH discovers unhandled exceptions by way of the HttpApplication object’s Error event. The Error event is raised whenever an uncaught exception bubbles up during request processing be that from a .NET class library or an ASP.NET Web page. Bear in mind that a lot of ASP.NET applications incorrectly implement custom error pages and handling by calling the Server.ClearError() method. Clearing the error will prevent the Error event from firing (as well as being reported to the client) and so ELMAH will never get a chance to log the exception. To put it another way, when using ClearError() in a custom error page, your user will see that a problem occurred, but you won’t.

Note   For more information on creating custom error pages, read Eli Robillard’s article Rich Custom Error Handling with ASP.NET.
Note   When an unhandled exception occurs in an ASP.NET Web service, the

Error

event is not bubbled up to HTTP modules and thus ELMAH. Rather, it is intercepted by the ASP.NET runtime and a SOAP fault is returned to the client. To have an error logged in a Web service, you would need to create a SOAP Extension that listened for SOAP faults.

In addition to recording details of unhandled exceptions, ELMAH also comes with a set of HTTP handlers for viewing the error log. There is a Web interface to the log, which can provide a list of all unhandled errors, as well as details about a particular error (see Figures 1 and 2).

Aa479332.elmah_fig01(en-us,MSDN.10).gif

Figure 1. Viewing the Error Log

Aa479332.elmah_fig02(en-us,MSDN.10).gif

Figure 2. Viewing an error

This error log can also be rendered as RSS, thereby allowing an administrator to receive notifications through her favorite RSS aggregator when an error has occurred (see Figure 3).

Aa479332.elmah_fig03(en-us,MSDN.10).gif

Figure 3. RSS feed of errors

Note   RSS, which stands for Really Simple Syndication, is an XML-formatted standard that is commonly used to syndicate news and other types of changing content. To learn more about RSS, including how to syndicate content using RSS, as well as how to create a Web-based RSS reader, consider reading Creating an Online News Aggregator with ASP.NET.

For brevity, this article touches upon only a subset of the features of ELMAH, focusing on the key components. The complete code is available for download with this article and we encourage you to study it thoroughly to get at the implementation details. There is also a GotDotNet Workspace setup for ELMAH at http://workspaces.gotdotnet.com/elmahfor the purpose of discussions, reporting issues, and staying up to date with any changes.

Existing Solutions for Centralized Error Logging

While ASP.NET does not provide built-in error logging and viewing capabilities, Microsoft’s Patterns & Practices Group have created an open-source error logger—the Exception Management Application Block (EMAB). The EMAB was designed to work with both desktop and Web-based .NET applications, but one can’t help feel that the EMAB was primarily designed for desktop applications with Web applications as an afterthought because the EMAB, by default, publishes exception details to the Windows Event Log. While the Event Log is a suitable backing store for concise exception information for a desktop application, most Web applications—especially those being hosted on a shared server at a Web hosting company—steer clear of the Event Log because using the Event Log requires special permissions to be established to allow the ASP.NET application to write to the Event Log. Granted, the EMAB is flexible enough that you can create a custom publisher that records information to a database, but that’s an extra step that you, the developer, are tasked with.

Note   ELMAH ships with a database-logging module for Microsoft SQL Server 2000, which we’ll discuss later. With ELMAH you can also create custom exception loggers, such as a logger that records exception details to an XML file on the Web server’s file system. In fact, you could extend ELMAH to use the Exception Management Application Block, if you already had a custom publisher written for the EMAB that you wanted to use.

How the EMAB is used to record exception information strongly influences the maintainability and reusability of the Web application. For example, a naïve approach to recording exception information would be to place a try ...catch block around each block of code in each ASP.NET Web page, calling the EMAB in the catch section.

private void Page_Load(object sender, EventArgs e)
{
  try {
    // Code that might cause an exception
  }
  catch (Exception ex) {
    // record exception information by calling exception logger library
  }
}

This approach is foolhardy since it tightly couples the exception logging to each and every ASP.NET Web page, making it anything but maintainable or reusable. A better approach would be to utilize the EMAB in the Application_Error event in Global.asax. This approach offers a more loosely coupled, maintainable, and reusable architecture, as the exception publishing code does not touch any ASP.NET Web page and is instead located in one, centralized location. The downside of this approach is that it is not pluggable. To add this error logging functionality to another ASP.NET Web application, you’d need to modify that application’s Global.asax, thereby needed to recompile and redeploy the application.

The point of this article is not to introduce a replacement for the EMAB. Rather, it is to highlight the componentization made possible by HTTP handlers and modules. ELMAH illustrates how one can take a common task, such as centralized error logging, and componentize it to ease maintainability and afford a high degree of reusability. The purpose of ELMAH is to offer guidance for componentizing applicable functionality.

A Brief Overview of HTTP Handlers and Modules

Before we move on to examining the specifics of ELMAH’s architecture and implementation, let’s take a moment to review HTTP handlers and modules. Whenever a request arrives at an IIS Web server, IIS examines the extension of the request to decide how to proceed. For static content like HTML pages, CSS files, images, JavaScript files, and so on, IIS handles the request itself. For dynamic content like ASP pages, ASP.NET Web pages, and ASP.NET Web Services, IIS delegates the request to a specified ISAPI Extension. An ISAPI Extension is a piece of unmanaged code that knows how to render requests of a particular type. For example, the asp.dll ISAPI Extension is responsible for rendering requests for classic ASP Web pages; the aspnet_isapi.dll ISAPI Extension is invoked when a request comes in for an ASP.NET resource.

In addition to ISAPI Extensions, IIS also allows for ISAPI Filters. An ISAPI Filter is a piece of unmanaged code that can run in response to events raised by IIS. During the lifecycle of a request, IIS passes through a number of steps that raise corresponding events. For example, an event is raised when the request first reaches IIS, when the request is about to be authenticated, when the rendered content is about to be sent back to the client, and so forth. ISAPI Filters are commonly used to provide capabilities such as URL rewriting, compression, specialized authentication and authorization, specialized logging, and so on.

When a request for an ASP.NET resource reaches IIS, it is routed to the ASP.NET engine, which renders the content for the requested resource. The ASP.NET engine behaves a lot like IIS in that it raises a number of events as the request passes through the ASP.NET HTTP pipeline. Furthermore, the ASP.NET engine delegates rendering of the requested resource to a particular class. Whereas IIS uses unmanaged ISAPI Extensions and Filters, ASP.NET uses managed classes called HTTP handlers and modules.

An HTTP handler is a class that is responsible for rendering a particular type of resource. For example, the code-behind class for an ASP.NET Web page is an HTTP handler, knowing how to render the markup for the particular Web page. It helps to think about handlers as specialized renderers that know how to create the markup for a particular type of resource.

Note   For a more in-depth discussion on HTTP handlers, along with some practical applications of handlers, be sure to read Serving Dynamic Content with HTTP Handlers.

An HTTP module is a class that can tap into the various events raised as a request passes through stages of its lifecycle on the server. One such ASP.NET application event is theError event, which fires when an unhandled exception occurs, which is the event ELMAH is interested in.

Note   For more information on HTTP modules, including a look at how to use HTTP modules to implement URL rewriting, check out URL Rewriting in ASP.NET.

Figure 4 provides a graphical representation of the ASP.NET HTTP pipeline. Note that the process starts with a request arriving at IIS. Assuming the requested resource is configured to be handled by the ASP.NET ISAPI Extension, IIS dispatches the request to the unmanaged aspnet_isapi.dll ISAPI Extension. This ISAPI Extension passes off the request to the managed ASP.NET engine. During the request lifecycle, one or more HTTP modules may execute, depending on what modules have been registered and what events they have subscribed to. Finally, the ASP.NET engine determines the HTTP handler that is responsible for rendering the content, invoking the handler and returning the generated content back to IIS, which returns it back to the requesting client.

Aa479332.elmah_fig04(en-us,MSDN.10).gif

Figure 4. Data flow through the Error Logger

ELMAH provides centralized error logging through an HTTP module that has an event handler for the Error event. When the event fires, ELMAH logs the exception details. ELMAH also uses HTTP handlers that are primarily responsible for generating HTML and RSS markup to display information from the error log.

Configuring an existing Web application to utilize various handlers or modules is accomplished by copying the module or handler assembly into the Web application’s /bindirectory and adding a few lines of configuration to the Web.config file.

To configure the HTTP modules for a Web application, include an <httpModules> section to the Web.config file that specifies the type of the module to add:

<httpModules>
   <add name="ModuleName" type="ModuleType" />
</httpModules>

The ModuleType is a string that spells out the module’s type, which is the fully qualified class name (Namespace.ClassName) followed by the assembly name. The type attribute can also include versioning and culture information, along with a public key token that is required of strong-named assemblies. The following snippet shows the actual<httpModules> setting you’ll need to use to include ELMAH’s error logging Module in your ASP.NET application:

<httpModules>
  <add name="ErrorLog" type="GotDotNet.Elmah.ErrorLogModule, 
    GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, 
    PublicKeyToken=978d5e1bd64b33e5" />
</httpModules>

An HTTP handler can be used in a Web application by adding an <httpHandlers> section to the Web.config file. Since an HTTP handler renders content for a particular type of resource, in addition to a type attribute the <httpHandlers> element contains a path attribute, which indicates what file paths or extensions should be mapped to this HTTP Handler. There’s also a verb attribute that allows you to limit use of the handler to specific types of HTTP requests, as in a GET or POST request. The following example would create an HTTP Handler that is invoked for all requests to files with a .ashx extension.

<httpHandlers>
   <add verb="*" path="*.ashx" type="HandlerType" />
</ httpHandlers >

The type attribute for the HTTP handler is expressed using the same syntax options as with HTTP modules. These settings in the Web.config can also be placed in themachine.config file, which has the effect of enabling the handlers and modules for all Web applications on the server. The following snippet shows the <httpHandlers> element in the Web.config file in the demo included in this article’s download. Note that it indicates that any incoming requests to /elmah/default.aspx should be rendered by theErrorLogPageFactory class.

<httpHandlers>
    <add 
        verb="POST,GET,HEAD" 
        path="elmah/default.aspx" 
        type="GotDotNet.Elmah.ErrorLogPageFactory, 
          GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, 
          PublicKeyToken=978d5e1bd64b33e5" />
</httpHandlers>

As you can see, adding HTTP modules and handlers to an ASP.NET Web application is very simple, can be done in a matter of seconds, and doesn’t require any recompilation or redeployment of the ASP.NET application. This is why HTTP modules and handlers are a great tool for reuse, and afford a means to componentize your application into loosely-coupled, highly maintainable pieces.

Examining ELMAH’s Architecture

ELMAH’s architecture is comprised of three subsystems:

  • An error logging subsystem
  • An HTTP module subsystem
  • An HTTP handler subsystem

The error logging subsystem is responsible for two tasks: recording errors to the log and retrieving error information from the log. The HTTP module subsystem is responsible for logging an error when an unhandled exception occurs in the ASP.NET application. The HTTP handler subsystem provides a means for the error log to be rendered into markup, constituting a Web-based interface to the error log, as well as an RSS feed.

As Figure 5 shows, the HTTP module and handler subsystems both utilize the error logging subsystem. The HTTP module subsystem sends off exception information to the error logging subsystem, while the HTTP handler subsystem reads and renders the error information.

Aa479332.elmah_fig05(en-us,MSDN.10).gif

Figure 5. Where the Error Logging System fits

To better understand ELMAH’s architecture, let’s examine each of these three subsystems in more detail.

The Error Logging Subsystem

The error logging subsystem is responsible for recording errors in the log, as well as offering capabilities for retrieving details about a particular error, or a subset of the errors. This functionality is made available by a number of classes:

  • ErrorLog: This abstract class provides the contractual methods to both read from and write to the log.
  • Error: This class contains properties that describe the details of a particular error.
  • ErrorLogEntry: This class represents a particular Error instance for a particular ErrorLog. The ErrorLogEntry essentially groups an Error instance with the ErrorLoginstance it originated from.

Let’s take a look at these three classes and how they work with the HTTP modules and HTTP handler subsystems in order to provide a complete, centralized exception-logging utility.

Examining the ErrorLog Class

Depending on a particular project setup or strategy, you might want to employ a different backing store for the error log. For example, on a production server, you might want to log exceptions to Microsoft SQL Server, but on a development server you might be happy just storing the errors in a set of XML files or a Microsoft Access database. To offer the capability of using different backing stores, the error logging subsystem provides an abstract base class, ErrorLog, which defines the base methods that all ELMAH error loggers must implement. These methods are:

  • Log(Error): Logs an error to the backing store. The Error class represents information about an unhandled exception; we’ll discuss this Error class in more detail shortly. In logging the error information, the Log() method must also assign a unique identifier to the error.
  • GetError(id): Returns information about a particular error in the log.
  • GetErrors(…): Returns a subset of errors from the log. This method is used by the HTTP handler subsystem to display the error log in a paged fashion, rather than displaying all errors at once.

ELMAH ships with two ErrorLog implementations:

  • SqlErrorLog: Records errors to a Microsoft SQL Server 2000 database using the System.Data.SqlClient provider. The SqlErrorLog requires SQL Server 2000 because it takes advantage of some of its XML features, but this is an implementation detail that can be changed.
  • MemoryErrorLog: Records errors in the application’s memory (RAM). In other words, it is bound to the AppDomain such that each application receives its own private log. Needless to say, this log does not survive application restarts or lifetime, so it’s mostly good for testing and temporary troubleshooting purposes when other implementations may fail.

You can use either of these exception loggers by simply adding a couple lines of text to your ASP.NET Web application’s Web.config file. If you need to store error details to someplace other than SQL Server or application memory, you can create your own custom logger. To implement an error logger for ELMAH, create a class that extends ErrorLogand supply the implementation for the Log()GetError(), and GetErrors() against your desired store.

Realize that both the HTTP module and handler subsystems in ELMAH interact directly with the specified ErrorLog class, be it SqlErrorLogMemoryErrorLog, or your own custom log class. The HTTP module logs exception information by creating an Error instance and passing this to the ErrorLog method’s Log() method. The HTTP handlers read details about one or more errors through the ErrorLog‘s GetError() and GetErrors() methods, which return either a specific ErrorLogEntry instance, or a set of ErrorLogEntryinstances.

A Look at the Error Class

The Log() method of ErrorLog expects an input parameter of type Error. A custom Error class is used in place of the Exception class provided in the .NET Framework because the Exception class is more suited for communicating exception information across the code stack and during the lifetime of an application. However, Exception objects are not ideal for storing in an exception log because of storage, typing, and portability concerns. Yes, binary serialization could be utilized to store an Exception instance, but this would require that the Exception object be deserializable on a machine with the same set of types and assemblies available. This is an unacceptable limitation (especially from the point of view of administration and operations) because a log and its contents should be portable and not only be viewable on a machine with a particular runtime or configuration. Furthermore, an Exception instance often lacks periphery information specific to a Web application, such as the values of the current Web request’s ServerVariables collection, something that can be invaluable for diagnosis. So, in short, the Error class acts as a surrogate for all exception types, holding over information from an exception raised in a Web application.

The complete list of Error properties are shown in Table 1.

Property Description
Exception The Exception instance represented by this error. This is a run-time property only that is never persisted along with an instance of the class.
ApplicationName The name of application in which this error occurred.
HostName The name of host machine where this error occurred. A good default is Environment.MachineName.
Type The type, class or category of the error. Usually this would be the full type name (sans the assembly qualification) of the exception.
Source The source of the error, usually the same as the Message property of an Exception object.
Message A brief text describing the error, usually the same as the Message property of an Exception object.
Detail Detailed text of the error, such as the complete stack trace.
User The User logged into the application at the time of the error, such as that returned by Thread.CurrentPrincipal.Identity.Name.
Time The date and time at which the error occurred. This is always in local time.
StatusCode The status code being returned in the response header as a result of the error. For example, this is 404 for a FileNotFoundException. Unfortunately, this value cannot always be reliably determined from within ASP.NET. For a few cases this StatusCode value may be reported as zero.
WebHostHtmlMessage The default HTML message that the Web host (ASP.NET) would have generated in absence of custom error pages.
ServerVariables NameValueCollection of Web server variables, such as those contained in HttpRequest.ServerVariables.
QueryString NameValueCollection of HTTP query string variables, such as those contained in HttpRequest.QueryString.
Form NameValueCollection of form variables, such as those contained in HttpRequest.Form.
Cookies NameValueCollection of cookies sent by the client, such as those contained in HttpRequest.Cookies.

The WebHostHtmlMessage property needs some explanation. If your ASP.NET Web application encounters an unhandled exception and you do not have your application configured to use custom error pages, you’ll see a screen similar to the one shown in Figure 6. This is a screen every ASP.NET developer has seen far too many times.

Aa479332.elmah_fig06(en-us,MSDN.10).gif

Figure 6. Standard Error page

When an exception is raised, the actual HTML markup for the corresponding screen is accessed and saved in the WebHostHtmlMessage property of the Error class. When the page that shows detailed information about a particular exception is visited, if the corresponding Error instance has a value in its WebHostHtmlMessage property, the visitor is presented with a link to a page that will show the actual exception information screen (like that shown in Figure 6). The neat thing here is that you not only get the exception logged, but you can also visit the original error page generated by ASP.NET when examining the log later. And all this while you have custom errors enabled!

The Error class also has methods to serialize and deserialize its state to and from an XML format. See FromXml and ToXml in accompanying code for details.

The ErrorLogEntry Class: Associating an Error with an ErrorLog

The final class in the error logging subsystem is the ErrorLogEntry class, which associates an Error instance with an ErrorLog instance. When the HTTP handler subsystem calls the GetError() method to retrieve information about a particular exception, the GetError() method retrieves the information from the specific backing store and populates this information in an ErrorLogEntry instance. The ErrorLogEntry class contains three properties:

  • Id: The unique ID of the exception details.
  • Log: A reference to the ErrorLog instance that represents the backing store.
  • Error: A populated instance of the Error class with the details of the specific error.

While the GetError() method returns a single ErrorLogEntry instance, the GetErrors() returns a list of ErrorLogEntry instances. GetErrors() is especially designed to allow errors to be paged through n records at a time.

Figure 7 shows an updated view of ELMAH’s architecture, showing greater detail in the error logging subsystem.

Aa479332.elmah_fig07(en-us,MSDN.10).gif

Figure 7. Updated architecture

The HTTP Module Subsystem

ELMAH consists of two HTTP modules: ErrorLogModule and ErrorMailModuleErrorLogModule is an HTTP module that creates an event handler for the application’s Errorevent. In the event of an unhandled exception, the HTTP module gets the appropriate error logger as specified in the application’s configuration, and calls the Log() method on it, passing in an Error instance populated with the information of the exception and the HttpContext for the current request. The following source code shows the germane code from the ErrorLogModule class:

public class ErrorLogModule : IHttpModule
{
    public virtual void Init(HttpApplication application)
    {
        application.Error += new EventHandler(OnError);
    }

    protected virtual ErrorLog ErrorLog
    {
        get { return ErrorLog.Default; }
    }

    protected virtual void OnError(object sender, EventArgs args)
    {
        HttpApplication application = (HttpApplication) sender;
        LogException(application.Server.GetLastError(), 
          application.Context);
    }

    protected virtual void LogException(Exception e, 
      HttpContext context)
    {
        try
        {
            this.ErrorLog.Log(new Error(e, context));
        }
        catch (Exception localException)
        {
            Trace.WriteLine(localException);
        }
    }
}

The ErrorLogModule‘s execution begins in the Init() method, where it indicates to the ASP.NET runtime that the OnError() method should be invoked whenever the Error event is raised. The OnError() method references the HttpApplication object and calls the LogException() method, passing in the details of the last exception, as well as theHttpContext instance specific to the particular request. LogException() simply calls the appropriate ErrorLog class’s Log() method, passing in a new Error instance. (TheError instance’s constructor takes in an Exception and HttpContext instance, and populates the properties accordingly; refer to the source code available in the download for more information.)

The ErrorLogModule contains a read-only ErrorLog property, and returns the ErrorLog instance returned by ErrorLog.DefaultDefault is a static property of type ErrorLogin the ErrorLog class. It consults the Web application’s configuration to determine what class to use for exception logging: SqlErrorLogMemoryErrorLog, or a custom exception logging class.

Note   In the section Adding ELMAH to an ASP.NET Web Application we’ll examine how to configure a Web application to use a specific exception logger. It’s as simple as adding a couple of lines to the

Web.config

or

machine.config

files.

The other HTTP module in the HTTP module subsystem is the ErrorMailModule class, which sends an e-mail to an administrator in the event of an exception. We won’t be discussing this piece of ELMAH, although you can examine how to use this module in the code samples available in this article’s download.

The HTTP Handler Subsystem

Recall that the purpose of HTTP handlers is to render the content for a particular type of resource. When a request comes into the ASP.NET HTTP pipeline, the ASP.NET engine examines the requested path and determines what HTTP handler should be used to handle the requested resource. Specifically, an ASP.NET application may be configured to have a particular path handled by either an HTTP handler or an HTTP handler factory. An HTTP handler factory is a class that is not directly responsible for rendering the content, but instead is responsible for selecting and returning an HTTP handler instance. This returned HTTP handler instance is then the one that is tasked with rendering the requested resource.

ELMAH’s HTTP handler subsystem consists of a number of HTTP handler classes designed to produce markup to display the logged errors, along with a single HTTP handler factory class. The HTTP handler factory class, ErrorLogPageFactory, examines the PathInfo portion of the requested URL to determine what HTTP Handler should generate the output.

Note   The

PathInfo

portion of a URL is any extra content following the file name, and is available through the

Request

object’s PathInfo property. For example, in the URL

, somePath is the

PathInfo

portion of the URL. For more information on the terminology used for the various parts of a URL, and the corresponding

Request

object properties, refer to Rick Strahl‘s blog entry Making Sense of ASP.NET Paths.

The following code snippet shows the more interesting code from the ErrorLogPageFactory HTTP handler factory class.

public class ErrorLogPageFactory : IHttpHandlerFactory
{
    public virtual IHttpHandler GetHandler(HttpContext context, 
      string requestType, string url, string pathTranslated)
    {
        string resource = 
          context.Request.PathInfo.Length == 0 ? string.Empty :
            context.Request.PathInfo.Substring(1);

        switch (resource.ToLower(CultureInfo.InvariantCulture))
        {
            case "detail" :
                return new ErrorDetailPage();

            case "html" :
                return new ErrorHtmlPage();

            case "rss" :
                return new ErrorRssHandler();

            default :
                return new ErrorLogPage();
        }
    }
}

As you can see, the ErrorLogPageFactory class’s GetHandler() method returns an HTTP handler instance based upon the PathInfo of the request. If the PathInfo is rss, an instance of the ErrorRssHandler HTTP handler is returned, which renders the log as an RSS feed. If the PathInfo is detail, an ErrorDetailPage HTTP handler instance is returned, which displays information about a particular exception.

In the ASP.NET Web application’s settings, you must specify a path that maps to the ErrorLogPageFactory HTTP handler factory, such as ErrorLog.aspx. To view an RSS feed of the exception log, you could visit: http://www.example.com/ErrorLog.aspx/rss.

ELMAH’s various HTTP handler classes—ErrorDetailPageErrorHtmlPageErrorRssHandlerErrorLogPage, and so on—render different markup. The ErrorRssHandler HTTP handler, for instance, loops through the 15 latest errors and emits the proper XML markup to display this information in an RSS format. The other HTTP handlers are all derived, directly or indirectly, from the System.Web.UI.Page class (which is the class from which all ASP.NET code-behind classes are derived from). These page-related HTTP handlers override the Page class’s Render() and OnLoad() methods to create an HTML interface displaying a pageable list of the logged exceptions. Refer back to Figures 1, 2, and 3 for screenshots of these pages.

Note   While the

Error

class saves the

ServerVariables

,

QueryString

,

Form

, and

Cookie

collections, only the

ServerVariables

collection is displayed in the details for an exception. This is because the

QueryString

parameters and cookies are viewable through the

ServerVariable

‘s

QUERY_STRING

and

HTTP_COOKIE

parameters, respectively. The

Form

collection is omitted because this could include potentially tens of kilobytes of view state information that usually serves little purpose for most diagnosis. Of course, you could easily modify the details of the HTTP handler to include this information, if you so chose.

Now that we have examined ELMAH’s three subsystems, let’s take a look at how to add ELMAH to an existing ASP.NET Web application. Pay particular attention to how easy it is to add ELMAH to any site—a benefit of componentization that the HTTP handlers and modules afford.

Adding ELMAH to an ASP.NET Web Application

Adding ELMAH to an ASP.NET Web application is fairly simple, and is comprised of two steps:

  • Adding the ELMAH assembly to the Web application.
  • Configuring the Web application to use ELMAH’s HTTP modules and HTTP handlers.

ELMAH can be applied to a particular Web application on a Web server by copying the assembly to the Web application’s /bin directory, and configuring ELMAH’s settings through the Web.config file. What’s more, you can configure ELMAH to be applied to all Web applications on a Web server by adding the assembly to the Web server’s Global Assembly Cache (GAC) and adding the same configuration settings in machine.config instead of Web.config.

In the Web.config (or machine.config) file, you’ll need to add the following settings:

  • <sectionGroup> element in the <configSections> element that defines a new section name, <gotdotnet.elmah>, with a section inside called <errorLog>, which has information about how to log exception information.
  • <gotdotnet.elmah> section, with an inner section named <errorLog>, which contains a type reference to the exception logger you want ELMAH to use, along with any settings specific to that exception logger.
  • An entry in the <httpHandlers> section indicating the path that, when visited through a browser, will render various views on the error log.
  • An entry in the <httpModules> section that adds the ErrorLogModule to the ASP.NET HTTP pipeline.

The following snippet from the Web.config file included in this article’s download illustrates how these four settings can be specified:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <!-- Allows for a new section group to the Web.config -->
    <sectionGroup name="gotdotnet.elmah">
      <!-- Indicates that inside the section group there will be an
              errorLog section -->
      <section name="errorLog" 
        type="System.Configuration.SingleTagSectionHandler, 
          System, Version=1.0.5000.0, Culture=neutral, 
          PublicKeyToken=b77a5c561934e089" />
    </sectionGroup>
  </configSections>

  <!-- This section group contains the type of the exception logger
         to use (SqlErrorLog, MemoryErrorLog, or a custom logger).
         It also contain properties pertinent to the exception logger
         (connectionString, for the SqlErrorLog). -->
  <gotdotnet.elmah>
    <errorLog type="GotDotNet.Elmah.SqlErrorLog, 
      GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, 
      PublicKeyToken=978d5e1bd64b33e5" 
      connectionString="...connection string..." />
  </gotdotnet.elmah>

  <system.web>
    <!-- Register that a request to aspnetham/errorlog.aspx should
        be serviced by the ErrorLogPageFactory HTTP Handler factory -->
    <httpHandlers>
      <add verb="POST,GET,HEAD" path="elmah/default.aspx" 
        type="GotDotNet.Elmah.ErrorLogPageFactory, 
        Skybow.Samples.AspNetHam, Version=1.0.5527.0, 
        Culture=neutral, PublicKeyToken=978d5e1bd64b33e5" />
    </httpHandlers>

    <!-- Adds the ErrorLogModule HTTP Module to the HTTP pipeline. -->
    <httpModules>
      <add name="ErrorLog" type="GotDotNet.Elmah.ErrorLogModule, 
         GotDotNet.Elmah, Version=1.0.5527.0, Culture=neutral, 
         PublicKeyToken=978d5e1bd64b33e5" />
    </httpModules>

    ...
  </system.web>
</configuration>

The <sectionGroup> element in the <configSections> element spells out that there will be an additional section group in the configuration file called <gotdotnet.elmah>. Furthermore, it indicates that inside this custom section, there will be an <errorLog> section. Inside the actual <gotdotnet.elmah> element there is an <errorLog> element that specifies which error log implementation should be used. Recall that ELMAH ships with two built-in implementations, namely SqlErrorLog and MemoryErrorLog. You can specify which of these two to use, or you can specify to use a custom exception logger you may have created, in the <errorLog> element. The <errorLog> element also holds the settings specific to an error log implementation. For example, when using the <errorLog> element to indicate that the SqlErrorLog should be used, a connectionStringproperty must be included that tells it how to connect to the database. The SQL script to create the appropriate table and associated stored procedures is included in the download.

Note   If you want an administrator to be e-mailed in the event of an unhandled exception, you would need to add another

<section>

element in

<sectionGroup>

that defines a new element called

<errorMail>

. Furthermore, in the actual

<gotdotnet.elmah>

element, you’d need to add an

<errorMail>

element. Consult the

Web.config

file in the download for a sample of this syntax.

The <httpHandlers> section specifies that the ErrorLogPageFactory (an HTTP Handler factory) should be used to retrieve the HTTP handler that renders the content to view the error log. The value of the path attribute indicates the URL relative to the application’s virtual root for getting at the error log display. You can change this to whatever you like, but make sure that it is a URL with an extension that is handled by the ASP.NET engine. That is, if you change the path to something like errors.log, you’ll need to configure IIS to map requests to errors.log to the ASP.NET ISAPI Extension (aspnet_isapi.dll). If you want to ensure that only administrators can view the log, use ASP.NET’s URL authorization capabilities to restrict access to a specific user or a set of users or roles. On the other hand, if you want to entirely disable Web-based access to the log then you simply don’t configure the <httpHandlers> section.

The <httpModules> section adds the ErrorLogModule HTTP module to the ASP.NET HTTP pipeline. Make sure you include this <httpModules> setting, otherwise ELMAH won’t be listening for the Error event, and therefore won’t be logging any unhandled exceptions.

As you can see, adding ELMAH to an existing ASP.NET Web application is fairly straightforward. The simple deployment and reusability of ELMAH is due to the fact that it is componentized using HTTP modules and handlers.

Conclusion

Hopefully this article has been able to shed some light on how HTTP handlers and modules are great tools for componentizing functionality orthogonal to an ASP.NET Web application. Common tasks such as centralized, application-wide logging, or monitoring requests across the entire application, can be componentized through handlers and modules. By wrapping up this functionality into a set of components, you get reusability, maintainability, and deployment benefits without requiring any migration, integration or re-compilation of existing code and applications.

To demonstrate the componentization possible with HTTP modules and handlers, we examined ELMAH, a centralized error logging and mailing application. ELMAH uses an HTTP module to listen for any application-wide Error events, which is fired as a result of an unhandled exception bubbling up. Upon learning of an unhandled exception, ELMAH logs the exception to a SQL Server database, to memory, or, perhaps, to some other backing store. ELMAH can also e-mail the contents of the exception to one or more recipients like developers and operations staff.

In addition to an HTTP module, ELMAH contains a set of HTTP handlers and an HTTP handler factory to facilitate viewing of the error log through a Web-based medium. This includes not only a traditional Web page, but also an RSS feed. ELMAH maintains a discrete component by having the display functionality wrapped in an HTTP handler, as opposed to requiring that the Web application include an ASP.NET Web page that displays such information. Through the use of HTTP handlers, deploying ELMAH is a simple process, and does not require a recompilation of the Web application, or uploading an ASP.NET Web page to the production server.

ELMAH is only one example of the power of componentization that HTTP handlers and modules afford. Perhaps there are other application-wide processes that you have implemented that can benefit from being componentized with handlers and modules.

Happy Programming!

3 tips if you want to use crystal report. Net 2010:


1. Crystal Reports .NET is no longer included with Visual Studio .NET 2010. it is a separate download. Use this link to download it to your application and install it after you have installed Visual Studio .NET 2010.

http://downloads.businessobjects.com/akdlm/cr4vs2010/CRforVS_13_0_1.exe

2. You will find that the Crystal Reports viewer is strangely missing from the Visual Studio toolbox. To fix this go to Project > Properties > Compile > Advanced Compiler Settings > Target framework(all configurations) > .NET

Framework 4. Set the Target Framework to be .NET Framework 4. After doing so, you application will close and re-open and the viewer will now be in the toolbox.

3. The Crystal Reports DLLs were written with .NET Framework 2 and they are compatible with Framework 4 as wel. But your application needs to have mixed-mode compatibility turned on for it to use the Crystal assemblies. To fix

this go to Solution Explorer > app.config.  You should add this property to the Startup tag in the app.config file.

useLegacyV2RuntimeActivationPolicy=”true”

Detail as follows:
….

<startup useLegacyV2RuntimeActivationPolicy=”true”><supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.0″/></startup></configuration>

Biography of BillGates


William H. Gates
Chairman
Microsoft CorporationWilliam (Bill) H. Gates III

William (Bill) H. Gates is chairman of Microsoft Corporation, the worldwide leader in software, services and solutions that help people and businesses realize their full potential. Microsoft had revenues of US$39.79 billion for the fiscal year ending June 2005, and employs more than 61,000 people in 102 countries and regions.

On June 15, 2006, Microsoft announced that effective July 2008 Gates will transition out of a day-to-day role in the company to spend more time on his global health and education work at the Bill & Melinda Gates Foundation. After July 2008 Gates will continue to serve as Microsoft’s chairman and an advisor on key development projects. The two-year transition process is to ensure that there is a smooth and orderly transfer of Gates’ daily responsibilities. Effective June 2006, Ray Ozzie has assumed Gates’ previous title as chief software architect and is working side by side with Gates on all technical architecture and product oversight responsibilities at Microsoft. Craig Mundie has assumed the new title of chief research and strategy officer at Microsoft and is working closely with Gates to assume his responsibility for the company’s research and incubation efforts.

Born on Oct. 28, 1955, Gates grew up in Seattle with his two sisters. Their father, William H. Gates II, is a Seattle attorney. Their late mother, Mary Gates, was a schoolteacher, University of Washington regent, and chairwoman of United Way International.

Gates attended public elementary school and the private Lakeside School. There, he discovered his interest in software and began programming computers at age 13.

In 1973, Gates entered Harvard University as a freshman, where he lived down the hall from Steve Ballmer, now Microsoft’s chief executive officer. While at Harvard, Gates developed a version of the programming language BASIC for the first microcomputer – the MITS Altair.

In his junior year, Gates left Harvard to devote his energies to Microsoft, a company he had begun in 1975 with his childhood friend Paul Allen. Guided by a belief that the computer would be a valuable tool on every office desktop and in every home, they began developing software for personal computers. Gates’ foresight and his vision for personal computing have been central to the success of Microsoft and the software industry.

Under Gates’ leadership, Microsoft’s mission has been to continually advance and improve software technology, and to make it easier, more cost-effective and more enjoyable for people to use computers. The company is committed to a long-term view, reflected in its investment of approximately $6.2 billion on research and development in the 2005 fiscal year.

In 1999, Gates wrote Business @ the Speed of Thought, a book that shows how computer technology can solve business problems in fundamentally new ways. The book was published in 25 languages and is available in more than 60 countries. Business @ the Speed of Thought has received wide critical acclaim, and was listed on the best-seller lists of the New York TimesUSA Today, the Wall Street Journal and Amazon.com. Gates’ previous book, The Road Ahead, published in 1995, held the No. 1 spot on the New York Times‘ bestseller list for seven weeks.
In addition to his love of computers and software, Gates founded Corbis, which is developing one of the world’s largest resources of visual information – a comprehensive digital archive of art and photography from public and private collections around the globe. He is also a member of the board of directors of Berkshire Hathaway Inc., which invests in companies engaged in diverse business activities.Gates has donated the proceeds of both books to non-profit organizations that support the use of technology in education and skills development.

Philanthropy is also important to Gates. He and his wife, Melinda, have endowed a foundation with more than $28.8 billion (as of January 2005) to support philanthropic initiatives in the areas of global health and learning, with the hope that in the 21st century, advances in these critical areas will be available for all people. The Bill and Melinda Gates Foundation has committed more than $3.6 billion to organizations working in global health; more than $2 billion to improve learning opportunities, including the Gates Library Initiative to bring computers, Internet Access and training to public libraries in low-income communities in the United States and Canada; more than $477 million to community projects in the Pacific Northwest; and more than $488 million to special projects and annual giving campaigns.

Gates was married on Jan. 1, 1994, to Melinda French Gates. They have three children. Gates is an avid reader, and enjoys playing golf and bridge.

Javascript Differences in Mozilla Firefox and Internet Explorer


document.all

Internet Explorer 4 introduced the document.all DOM (document object model) to allow access to the various parts of the web page. Soon after that the standard DOM method getElementById was introduced and is therefore available in all version 5+ browsers. This means that the document.all references are only needed to support IE4.

document.all doesn’t work  mozilla why?

Some proprietary document objects such as document.all and document.layers are not part of the W3C DOM and are not supported in Mozilla. (There is partial undetectable support for document.all, though, in newer versions of Mozilla. However, that functionality only exists for compatibility with sites authored specifically for IE. You should not rely on Mozilla’s document.all support on new pages.) The method document.getElementById()can be used instead.

In the Standards mode Mozilla does not generate implicit top-level JavaScript variable bindings for elements with the id or name attribute. The correct way to access an element by id is to call the document.getElementById()method with the id as a string as the argument.

Also, old client sniffers can shut out new browsers. The point of having a common API (the W3C DOM) is interoperability, and checking for a particular browser defeats that purpose. When working with the DOM, it is better to check for the existence of the methods and objects you are planning on using. For example, the existence ofdocument.getElementById() can be checked as follows:

if(document.getElementById) {
/* code that uses document.getElementById() */
}

1. Window/Body OnLoad

When dealing with a site that uses Master Pages, you lose some control, including the ability to declare a page specific event handler. There are ways around this, and I found that the following code example works pretty well.

<script language=”javascript” type=”text/javascript” for=”window” event=”onload“>
if (document.all)
{
initialize();
}
else
{
window.document.addEventListener(“DOMContentLoaded”, initialize, true);
}
</script>

2. Get Control Inner Text

Retrieving the text of an element is done by using element.innerText in Internet Explorer and element.textContentin Mozilla Firefox.

function getText(control)
{
if (document.all)
{
return control.innerText;
}
else
{
return control.textContent;
}
}

function setText(control, value)
{
if (document.all)
{
control.innerText = value;
}
else
{
control.textContent = value;
}
}

3. Element Height and Width

To retrieve an element’s height and width, use element.currentStyle for Internet Explorer and element.style forMozilla Firefox.

if (document.all)
{
top += parseValue(element.currentStyle.borderTopWidth);

}
else
{
top += parseValue(element.style.borderTopWidth);

}

4. Source Elements

To get a reference to the element that fired an event within an event handler, use event.srcElement for Internet Explorer and event.target for Mozilla Firefox.

function getSourceElement(event)
{
if (document.all)
{
return event.srcElement;
}
else
{
return event.target;
}
}

5. Firing Events

You can call fireEvent on an element in Internet Explorer, but it’s more complicated in Mozilla Firefox, requiring an event to be instantiated, initialized, and dispatched.

function fireClickEvent(control)
{
if (document.all)
{
control.fireEvent(“onclick”);
}
else
{
var clickEvent = window.document.createEvent(“MouseEvent“);
clickEvent.initEvent(“click“, false, true);
control.dispatchEvent(clickEvent);
}
}

6. Window Height and Width

Internet Explorer exposes the visible content area dimensions using document.body.offsetHeight anddocument.body.offsetWidth, whereas Mozilla Firefox uses document.body.offsetWidth and window.innerWidth.

function getWindowHeight()
{
if (document.all)
{
return document.body.offsetHeight;
}
else
{
return window.innerHeight;
}
}

function getWindowWidth()
{
if (document.all)
{
return document.body.offsetWidth;
}
else
{
return window.innerWidth;
}
}

7. Why doesn’t Mozilla display my alt tooltips?

Contrary to a popular belief stemming from the behavior of a couple browsers running on the Windows platform,alt isn’t an abbreviation for ‘tooltip’ but for ‘alternative’. The value of the alt attribute is a textual replacement for the image and is displayed when the image isn’t.

Mozilla doesn’t display the alt attribute as a tooltip, because it has been observed that doing so encourages authors to misuse the attribute.

  • * When the alternative text is shown in a tooltip, some authors write bad alt texts, because they intend the text as auxiliary tooltip text and not as a replacement for the image. (‘Bad’ in the sense that the textual alternative is less useful for people who don’t see the image.)
  • * When the alternative text is shown in a tooltip, other authors don’t want to supply textual alternatives at all, because they don’t want tooltips to appear. (Again, making things harder for people who don’t see the image.)

There is another attribute that Mozilla shows as a tooltip: title. In fact, the HTML 4.01 specification suggests that the title attribute may be displayed as a tooltip. However, this particular display method is not required and some other browsers show the title attribute in the browser status bar, for example.

At this point some people feel compelled to post a “But IE…” rant in the newsgroups or in Bugzilla. Please note that Mac IE 5 behaves in the same way as Mozilla when it comes to the alt and title attributes. Windows IE also shows the title attribute in a tooltip.

8. Does Mozilla support downloadable fonts?

Downloadable fonts are not supported.

Downloadable fonts are usually used on sites using writing systems for which proper support has been missing in browsers in the past. These sites (for example some Indian sites) code the text in Latin gibberish and then use a font that to the browser and operating system seems to be a Latin font but has eg. Devanagari glyphs, so that when the Latin gibberish is rendered with the font it seems to a human reader to be intelligible text in some language.

Obviously, that kind of ad hockery falls apart when Unicode-savvy browsers come along and render Latin gibberish as Latin gibberish (since that’s what is coded in the file from the Unicode point of view). Instead of providing support for downloadable fonts, Mozilla is addressing the real issue: support for various Unicode ranges.

However, there are still bugs related to support for Indic scripts on some platforms. For example, on Mac OS X Mozilla does not use the Devanagari font that comes with the system but can use a third-party font like TITUS Cyberbit.

lot of work has been put into Mozilla’s Unicode support. Supporting downloadable fonts in a cross-platform way would also be a lot of work and would potentially require navigating past a bunch of patents but the rewards would be small. For the purpose of rendering non-ISO-8859-1 characters Mozilla already provides Unicode support that, in the long run, is a lot better approach than using pseudo-Latin downloadable fonts separately on each site.

9. In Mozilla Firefox my style sheet doesn’t work! Why?

Here’s the check list:

  • 1. Does the HTML document validate? Styling misnested markup may cause strange effects.
    • * The <link> and <style> elements should be inside the <head> element.
  • 2. Does the CSS style sheet pass the syntax check? The CSS error handling rules require erroneous parts to be ignored rather than fixed by guessing.
    • * Lengths other than zero should be followed by a proper unit without a space between the number and the unit (eg. 1.2em).
    • * The character to use between the property name and the value is the colon—not the equal sign.
    • * HTML markup, such as <style>, does not belong in .css files.
    • * font-face is not a real CSS property. The property is font-family and @font-face is an at-rule.
    • * If @import is used, it should be the first thing in a CSS file.
    • * In Mozilla 1.8a4 and later (not in Firefox 1.0) CSS parsing errors are reported to the JavaScript console.
  • 3. Is the server sending the proper Content-Type header for CSS style sheets?
  • 4. Class names and ids are case-sensitive.
  • 5. The element selectors are case-sensitive with XML.
  • 6. Style sheet processing instructions are only allowed in the prolog of XML documents. Also, they only work in XML documents—not in documents served as text/html.
  • 7. width and height do not apply to non-replaced inline elements such as (by default) <span>.
  • 8. text-align: center; centers inline content within a block. It does not (and should not) center the block box itself. A block is centered by setting its margin-left and margin-right to auto and its width to a value that makes the block narrower than its containing block.

It is also possible, although not very likely, that you are seeing a bug.

Create an EXE or Setup File in .NET Windows Application


Hi Friends!

Visual Studio 2005 Setup and deployment Projects provides to make an exe or installer file in .NET windows application is easy and rapidly.

Visual Studio provides templates for four types of deployment projects: Merge Module Project, Setup Project, Web Setup Project, and Cab Project. In addition, a Setup wizard is provided to help step you through the process of creating deployment projects. You can see the templates and the wizard in the New Project dialog box under theSetup and Deployment Projects node.

The following are guidelines for choosing the right type of deployment project for your project.

1)Merge Module Project : Packages components that might be shared by multiple applications.

2)Setup Project : Builds an installer for a Windows-based application.

3)Web Setup Project : Builds an installer for a Web application.

4)Cab Project : Creates a cabinet file for downloading to a legacy Web browser.

5)Smart Device Cab Project : Creates a Cab project to deploy device applications.

This topic demonstrates deployment using a Setup and Deployment Project.

Setup Projects

Setup projects allow you to create installers in order to distribute an application. The resulting Windows Installer (.msi) file contains the application, any dependent files, information about the application such as registry entries, and instructions for installation. When the .msi file is distributed and run on another computer, you can be assured that everything necessary for installation is included; if for any reason the installation fails (for example, the target computer does not have the required operating system version), the installation will be rolled back and the computer returned to its pre installation state.

The following steps will gives the elegant guidance to create an executable or installer file.

1, Go to file menu > click Add > new project >now “Add New Project” dialog will appear.

2.Select the “Other Project Types” and click “Setup and Deployment” projects,Choose “Setup Project”give name project name in name text box finally click OK.

3.New project appear in solution explorer,for eg., you have give the name “MyEXE” file will be displays with given name.

4.Right click the MyEXE > go View > click “File System”

5.You can see the “File System on TargetMachine”under  three folders
Application Folder
User’s Desktop
User’s Program Menu

6.Select Application Folder and right click Add>Project Output>select Primary output

7. Select User’s Desktop richt click on the second window>click create new shortcut>select output file from Application folder>change the file name from  primary output name to MyEXE

next >>

same procedure follows the user’s program menu also

8.If you want to change the Manufactures name f,just right click the project go to properties

change the properties as per you requirement

9.Finally Build the new project After successfully Build the project myEXE(Setup) will be appear in Application Debug or Release folder(depend upon the properties settings)

EXE or installer will be available on his physical path…

When you want to install  the EXE on the client machine,you should be installed .NET Framework on that machine because, Applications and controls written for the .NET Framework v2.0 requires the .NET Framework Redistributable Package version 2.0 to be installed on the computer where the application or control runs.

How to insert the data to the Xml file?


protected void InsertRecordToXml_Click(object sender, EventArgs ee)

    {

        XmlDocument docXml = new XmlDocument();

        docXml.Load(Server.MapPath(@"App_Data\TestXmlFile.xml"));

        

        //Create the node to set the data

        XmlElement element = docXml.CreateElement("DotNetFunda");

        XmlElement xmlUser = docXml.CreateElement("UserName");

        XmlElement xmlQuestion = docXml.CreateElement("Question");

        XmlElement xmlSolution = docXml.CreateElement("Solution");


        xmlUser.InnerText = this.txtUser.Text.Trim();

        xmlQuestion.InnerText = this.txtQuestion.Text.Trim();

        xmlSolution.InnerText = this.txtSolution.Text.Trim();



        element.AppendChild(xmlUser);

        element.AppendChild(xmlQuestion);

        element.AppendChild(xmlSolution);


        docXml.DocumentElement.AppendChild(element);


        docXml.Save(Server.MapPath(@"App_Data\TestXmlFile.xml"));


        //call the load method to load the data

        loadUsersXmlData();

    }

 

JavaScript interview questions and answers


  • What’s relationship between JavaScript and ECMAScript? – ECMAScript is yet another name for JavaScript (other names include LiveScript). The current JavaScript that you see supported in browsers is ECMAScript revision 3.
  • What are JavaScript types? – Number, String, Boolean, Function, Object, Null, Undefined.
  • How do you convert numbers between different bases in JavaScript? – Use the parseInt() function, that takes a string as the first parameter, and the base as a second parameter. So to convert hexadecimal 3F to decimal, use parseInt (“3F”, 16);
  • What does isNaN function do? – Return true if the argument is not a number.
  • What is negative infinity? – It’s a number in JavaScript, derived by dividing negative number by zero.
  • What boolean operators does JavaScript support? – &&, || and !
  • What does “1”+2+4 evaluate to? – Since 1 is a string, everything is a string, so the result is 124.
  • How about 2+5+”8″? – Since 2 and 5 are integers, this is number arithmetic, since 8 is a string, it’s concatenation, so 78 is the result.
  • What looping structures are there in JavaScript? – for, while, do-while loops, but no foreach.
  • How do you create a new object in JavaScript? – var obj = new Object(); or var obj = {};
  • How do you assign object properties? – obj[“age”] = 17 or obj.age = 17.
  • What’s a way to append a value to an array? – arr[arr.length] = value;
  • What is this keyword? – It refers to the current object.
  •  

    Dot Net Interview Success Kit


    1. Explain the .NET architecture.
    2. How many languages .NET is supporting now? – When .NET was introduced it came with several languages. VB.NET, C#, COBOL and Perl, etc. The site DotNetLanguages.Net
    3. How is .NET able to support multiple languages? – a language should comply with the Common Language Runtime standard to become a .NET language. In .NET, code is compiled to Microsoft Intermediate Language (MSIL for short). This is called as Managed Code. This Managed code is run in .NET environment. So after compilation to this IL the language is not a barrier. A code can call or use a function written in another language.
    4. How ASP .NET different from ASP? – Scripting is separated from the HTML, Code is compiled as a DLL, these DLLs can be executed on the server.
    5. Resource Files: How to use the resource files, how to know which language to use?
    6. What is smart navigation? – The cursor position is maintained when the page gets refreshed due to the server side validation and the page gets refreshed.
    7. What is view state? – The web is stateless. But in ASP.NET, the state of a page is maintained in the in the page itself automatically. How? The values are encrypted and saved in hidden controls. this is done automatically by the ASP.NET. This can be switched off / on for a single control
    8. Explain the life cycle of an ASP .NET page.
    9. How do you validate the controls in an ASP .NET page? – Using special validation controls that are meant for this. We have Range Validator, Email Validator.
    10. Can the validation be done in the server side? Or this can be done only in the Client side? – Client side is done by default. Server side validation is also possible. We can switch off the client side and server side can be done.
    11. How to manage pagination in a page? – Using pagination option in DataGrid control. We have to set the number of records for a page, then it takes care of pagination by itself.
    12. What is ADO .NET and what is difference between ADO and ADO.NET? – ADO.NET is stateless mechanism. I can treat the ADO.Net as a separate in-memory database where in I can use relationships between the tables and select insert and updates to the database. I can update the actual database as a batch.

    Designers and Editors, Shared Shortcuts


     

    Name Shortcut keys Description
    Activate application menu ALT + SPACEBAR Opens the program menu, allowing the user to manage the state of the application window, for example, move or resize.
    Activate document window menu ALT + HYPHEN Opens the document menu, allowing the user to manage the state of the active document window, for example, move or resize. Available only while in MDI mode from within a document window.
    Activate tool window menu ALT + HYPHEN Opens the tool window menu, allowing the user to move the tool window within the IDE. Available only while within a tool window.
    Close application ALT + F4 Closes the IDE.
    Close document CTRL+F6 Closes the active application document.
    Collapse all tree nodes NUM + – Collapses all nodes in the current tree view.
    Expand all tree nodes NUM + * Expands all nodes in the current tree view.
    Move to menu bar ALT Activates the main IDE menu bar.
    Move to next toolbar CTRL + TAB Moves to the next visible toolbar. Available only while the main menu bar is active.
    Move to previous toolbar CTRL + SHIFT + TAB Moves to the previous visible toolbar. Available only while the main menu bar is active.
    Move to tool window toolbar SHIFT + ALT Activates the tool window toolbar. Available only while in a tool window containing a toolbar.
    Move tree focus down CTRL + DOWN ARROW Moves the focus in tree view down without changing the selection. This shortcut can be used to select multiple items in the tree.
    Move tree focus up CTRL + UP ARROW Moves the focus in tree view up without changing the selection. This shortcut can be used to select multiple items in the tree.
    Shortcut menu SHIFT + F10 Displays the shortcut menu.
    Toggle drop-down list visibility F4 Hides and shows a drop-down list. Available only while within a drop-down list.
    Toggle tree focus selection CTRL + SPACEBAR Toggles a selection for the current focus in tree view.

     

    Converting Docx to PDF


    After long hours of researching on this topic, I came accross Bullzip PDF Creator http://www.bullzip.com/products/pdf/info.php . This product is the best freeware programmable pdf printer that I’ve used so far. The installer of pdf printer includes a .NET assembly (no COM!!) called Bullzip.PdfWriter which gives the possibility to print “silently” to pdf – with no user interaction. (The assembly is visible within the “Add Reference” dialog in Visual Studio in the .NET tab!). When the Print() method of this assembly is invoked on a Word 2007 document, it opens Word automatically, launches the Print command and closes Word within a couple of seconds. The pdf printer can also be configured to iterate through a collection of documents. The best thing about this product is that is very well documented, making it quite easy to set up.

    Here’s a piece of code:

     

    using System;
    using System.IO;
    using System.Linq;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.ComponentModel;
    using System.Configuration;
    using System.ServiceModel;
    using Bullzip.PdfWriter;
    
    namespace DocxGenerator.SL.WCF
    {
      public class PdfMaker
      {    
        internal static byte[] PrintToPdf(string appFolder, string tempDocxFileName)
        {
          try
          {
            string tempFolder = appFolder + @"\temp";
            string tempDocxFilePath = tempFolder + @"\" + tempDocxFileName;
    
            PdfSettings pdfSettings = new PdfSettings();
            pdfSettings.PrinterName = ConfigurationManager.AppSettings["PdfPrinter"];
    
            string settingsFile = pdfSettings.GetSettingsFilePath(PdfSettingsFileType.Settings);
            pdfSettings.LoadSettings(appFolder + @"\App_Data\printerSettings.ini");
            pdfSettings.SetValue("Output", tempFolder + @"\<docname>.pdf");
            pdfSettings.WriteSettings(settingsFile);
    
            PdfUtil.PrintFile(tempDocxFilePath, pdfSettings.PrinterName);
            string tempPdfFilePath = tempFolder + @"\Microsoft Word - " + tempDocxFileName + ".pdf";
    
            bool fileCreated = false;
            while (!fileCreated) 
            {
              fileCreated = PdfUtil.WaitForFile(tempPdfFilePath, 1000);
            }
    
            byte[] pdfBytes = File.ReadAllBytes(tempPdfFilePath);
    
            File.Delete(tempDocxFilePath);
            File.Delete(tempPdfFilePath);
    
            return pdfBytes;        
          }
          catch (Exception ex)
          {
            throw new FaultException("WCF error!\r\n" + ex.Message);
          }
        }
      }
    
    }

     

    How To Play Flash Video Files In ASP.NET using C#.net or VB.net


    Videos are becoming common part of web sites today. Before just a few years, web designers avoided even larger picture on site, because Internet connection of many visitors was slow, and movies usually have much more bytes than pictures. Visitors did not like to wait more than a few seconds to see page loaded. Rare videos was very short, had low resolution and bad quality. But now, circumstances are changed. Now almost everyone have fast connection and time of dial-up connection is past. Now you can display video whenever you want to better describe your product or service.

     

    There is a few different ways to show video on web page. Most popular are Windows Media Player, Quick Time, Adobe Flash or Silverlight. If you want to find out how to show video with Windows Media Player you can read How to build ASP.NET Media Player Control tutorial. This tutorial will focus on using of Flash to show flash video files on ASP.NET web site.

    Flash becomes widely used and today it is most used technology for showing movies on Internet. Flash is used by most popular video sharing web sites like YouTube or Google Video. It is compatible with almost every operating system and web browser and very prevalent on Internet users computers. To see Flash movies, users need to have Flash player installed. On my experiences, at least 95% visitors have Flash player installed which is more than other available technologies. Flash is client side technology, although it can be used with static HTML page, but it is usually manipulated by server side web application.

    You can’t show flash video files directly. Flash is just a programming framework, which uses Action Script programming language. You need a program made in Flash (video player) to show .flv video on page. You can of course learn Action Script and develop your own player, but that is out of scope of this tutorial. I will leave that task to Flash developers. Fortunately, there are already some free and very good Flash video players available. Using of them will short your development cycle and provide you a quality solution. I selected JW FLV Player as the best solution.

    Using of JW FLV Player on web page

    There are a two basic steps when placing Flash application to web page:

    – First, declare and initiate a Flash object

    – Second, set properties of object according to your needs.

    You can do this on two different ways, with static HTML tags <OBJECT > and , or by using a JavaScript. With static HTML your code could look something like this:

    <object width=”640″ height=”480″>
    <param name=”movie” value=”player.swf” />

    </object>

     

    We need both <object > and tags to get browser compatibility. Internet Explorer uses <object> tag, but Firefox and Netscape can’t see it and recognize just . We set parameters by using <param > tags, and inside tag. Code example above have added parameter name “movie” and value “player.swf”. You can add any other parameter on the same way. Complete list of supported parameters for JW FLV Player you can see at their Flash vars page.

    http://cdn5.tribalfusion.com/media/2481846/template_300x250_v8.swf

    There is a problem with static HTML if visitors access with Internet Explorer. Flash application would not start until visitor clicks on it. If you just place a cursor over a movie you’ll see an ugly border. Common way to avoid need to click every time when page load is to initiate Flash player with JavaScript. JavaScript code for starting Flash movie could look like this:

    <p id=’preview’>The player will show in this paragraph</p>

    <script type=’text/javascript’ src=’swfobject.js’></script>
    <script type=’text/javascript’>
    var s1 = new SWFObject(‘player.swf’,’player’,’400′,’300′,’9′);
    s1.addParam(‘allowfullscreen’,’true’);
    s1.addParam(‘allowscriptaccess’,’always’);
    s1.addParam(‘flashvars’,’file=video.flv’);
    s1.write(‘preview’);
    </script>

     

    As you can see, nothing complicated here. Code creates SWFObject dynamically and then set its parameters. In this case visitor is not required to click to start a movie. Of course, JavaScript must be enabled in visitor’s web browser.

    Manipulating Flash Player with ASP.NET

    Basically, playing video files with JW FLV Player is simple, you just create an object and set needed parameters as in two code examples above. But, if you work with large number of video files or you need to enable to your users to add their movies you need to automate things. Writing static HTML code for every video certainly not sounds professional. Fortunately, with a little ASP.NET code we can make this task much easier :).

    Creating a custom ASP.NET Flash Player Control

    Basic idea is this: Custom ASP.NET control will have properties related to JW FLV Player parameters. In run time, control will render appropriate content on client side so JW FLV player will show video correctly, and you can manipulate flash videos with ASP.NET web application. Now, we can create admin ASP.NET pages, load videos from database, enable database search etc., without hard coding.

    I created ASP.NET JW FLV Flash Video Player Control that do this task. Control is free and you can use it to show Flash video files on your web site. Source code of control is also available in C# andVB.NET. Example web project is included in download to see how it works.


    Image 1: ASP.NET Flash player control at run time

    You can download this control compiled for ASP.NET 1.1ASP.NET 2.0 and ASP.NET 3.5. Every download contains example web application with sample video files, so you can immediately see how it works.

    Flash Player Control Code Analysis

    As you can see from C# and VB.NET code listings, control code consists from three parts:

    1. Declaring of properties default values on the beginning. For server control, I used same default values like JW FLV Flash player already uses. I added two additional properties to describe location of JW FLV .swf and .js file, like in code bellow.

    [ C# ]

    #region Properties defaults
    const string DefaultSwfobject_jsLocation = “”; // in the same directory
    const string DefaultFlashPlayerLocation = “”; // in the same directory
    const bool DefaultAllowFullScreen = true;
    const string DefaultFile = “”;
    const bool DefaultAutoStart = false;
    const int DefaultBufferLength = 1;

    #endregion

    [ VB.NET ]

    #Region “Properties defaults”
    Const DefaultSwfobject_jsLocation As String = “” ‘ in the same directory
    Const DefaultFlashPlayerLocation As String = “” ‘ in the same directory
    Const DefaultAllowFullScreen As Boolean = True
    Const DefaultFile As String = “”
    Const DefaultAutoStart As Boolean = False
    Const DefaultBufferLength As Integer = 1

    #End Region

     

    2. Value of every property is saved to ViewState if value is different from default value. For example, code for AllowFullScreen property looks like this:

    [ C# ]

    [Bindable(true), Category(“Settings”)]
    bool AllowFullScreen
    {
    get
    {
    if(ViewState[“AllowFullScreen”] == null)
    return DefaultAllowFullScreen;
    else
    return (bool)ViewState[“AllowFullScreen”];
    }
    set
    {
    if(value != DefaultAllowFullScreen)
    ViewState[“AllowFullScreen”] = value;
    else
    ViewState[“AllowFullScreen”] = null;
    }
    }

    [ VB.NET ]

    <Bindable(True), Category(“Settings”)> _
    Property AllowFullScreen() As Boolean
    Get
    If ViewState(“AllowFullScreen”) Is Nothing Then
    Return DefaultAllowFullScreen
    Else
    Return ViewState(“AllowFullScreen”)
    End If
    End Get
    Set(ByVal value As Boolean)
    If value <> DefaultAllowFullScreen Then
    ViewState(“AllowFullScreen”) = value
    Else
    ViewState(“AllowFullScreen”) = Nothing
    End If
    End Set
    End Property

     

    3. RenderContents function produces output to, depended of values of every property, correctly initialize Flash player on client side by using a JavaScript, like mentioned before.

    Conclusion

    With custom ASP.NET Flash Player control that manipulate client side flash player you can save a lot of time. I tested control in Firefox and Internet Explorer and worked fine. Please let me know if you find some bug or you have a suggestion for improvement.

    Going professional with ASPNetFlashVideo

    Control introduced in this tutorial is useful in some simpler scenarios, but keep in mind that JW FLV Player is free only for noncommercial projects. Fortunately, there is pure ASP.NET control namedASPNetFlashVideo that allows you to effortlessly incorporate beautiful Adobe Flash Video (FLV) media into ASP.NET website. For $49 you can use it on single site or just $99 for use on unlimited number of web sites. Except common interface commands for playing flash video files, ASPNetFlashVideosupports skins, custom user interface, play lists, integration with Visual Studio, search engine optimization and more. Things like no ongoing subscription costs, free future updates or 30 days money back guarantee justify decision to give it a try.