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¬†IsInRange,¬†ToLong, 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 (Exception,¬†IndexOutOfRangeException,¬†NullReferenceException, 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: Application, Context, Cookies, 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
Context, Session 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.IO, System.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.vb: ErrorApplication, ErrorCookie, ErrorContext, andErrorQueryString. Since all classes use the same methods (Store, Retrieve, 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 Store, Retrieve, 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 ErrorApplication, ErrorCookie, 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 (Message, Source, 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.Message, Exception.Source, Exception.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 Context, Transfer 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 (Application,¬†Cookie,¬†Context, 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¬†SqlErrorLog,¬†MemoryErrorLog, 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 A NameValueCollection of Web server variables, such as those contained in HttpRequest.ServerVariables.
QueryString A NameValueCollection of HTTP query string variables, such as those contained in HttpRequest.QueryString.
Form A NameValueCollection of form variables, such as those contained in HttpRequest.Form.
Cookies A 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¬†ErrorMailModule.¬†ErrorLogModule¬†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.Default.¬†Default¬†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:¬†SqlErrorLog,¬†MemoryErrorLog, 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‚ÄĒErrorDetailPage,¬†ErrorHtmlPage,¬†ErrorRssHandler,¬†ErrorLogPage, 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:

  • A¬†<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.
  • A¬†<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>

Download a web page using c#


static void Main(string[] args)

        {

            string yourUrl = "http://www.dotnetfunda.com/";

            string yourOutpuFile = "temp.html";


            using (WebClient client = new WebClient())

            {

                client.DownloadFile(yourUrl, yourOutpuFile);

            }

            Console.WriteLine("Page Downloaded...");

            Console.Read();

        }

 

C# interview questions and answers


  1. What’s the advantage of using System.Text.StringBuilder over System.String? StringBuilder is more efficient in the cases, where a lot of manipulation is done to the text. Strings are immutable, so each time it’s being operated on, a new instance is created.
  2.  

  3. Can you store multiple data types in System.Array? No.
  4. What’s the difference between the System.Array.CopyTo() and System.Array.Clone()? The first one performs a deep copy of the array, the second one is shallow.
  5. How can you sort the elements of the array in descending order? By calling Sort() and then Reverse() methods.
  6. What’s the .NET datatype that allows the retrieval of data by a unique key?HashTable.
  7. What’s class SortedList underneath? A sorted HashTable.
  8. Will finally block get executed if the exception had not occurred? Yes.
  9. What’s the C# equivalent of C++ catch (…), which was a catch-all statement for any possible exception? A catch block that catches the exception of type System.Exception. You can also omit the parameter data type in this case and just write catch {}.
  10. Can multiple catch blocks be executed? No, once the proper catch code fires off, the control is transferred to the finally block (if there are any), and then whatever follows the finally block.
  11. Why is it a bad idea to throw your own exceptions? Well, if at that point you know that an error has occurred, then why not write the proper code to handle that error instead of passing a new Exception object to the catch block? Throwing your own exceptions signifies some design flaws in the project.
  12. What’s a delegate? A delegate object encapsulates a reference to a method. In C++ they were referred to as function pointers.
  13. What’s a multicast delegate? It’s a delegate that points to and eventually fires off several methods.
  14. How’s the DLL Hell problem solved in .NET? Assembly versioning allows the application to specify not only the library it needs to run (which was available under Win32), but also the version of the assembly.
  15. What are the ways to deploy an assembly? An MSI installer, a CAB archive, and XCOPY command.
  16. What’s a satellite assembly? When you write a multilingual or multi-cultural application in .NET, and want to distribute the core application separately from the localized modules, the localized assemblies that modify the core application are called satellite assemblies.
  17. What namespaces are necessary to create a localized application?System.Globalization, System.Resources.
  18. What’s the difference between // comments, /* */ comments and /// comments? Single-line, multi-line and XML documentation comments.
  19. How do you generate documentation from the C# file commented properly with a command-line compiler? Compile it with a /doc switch.
  20. What’s the difference between <c> and <code> XML documentation tag? Single line code example and multiple-line code example.
  21. Is XML case-sensitive? Yes, so <Student> and <student> are different elements.
  22. What debugging tools come with the .NET SDK? CorDBG ‚Äď command-line debugger, and DbgCLR ‚Äď graphic debugger. Visual Studio .NET uses the DbgCLR. To use CorDbg, you must compile the original C# file using the /debug switch.
  23. What does the This window show in the debugger? It points to the object that’s pointed to by this reference. Object’s instance data is shown.
  24. What does assert() do? In debug compilation, assert takes in a Boolean condition as a parameter, and shows the error dialog if the condition is false. The program proceeds without any interruption if the condition is true.
  25. What’s the difference between the Debug class and Trace class? Documentation looks the same. Use Debug class for debug builds, use Trace class for both debug and release builds.
  26. Why are there five tracing levels in System.Diagnostics.TraceSwitcher? The tracing dumps can be quite verbose and for some applications that are constantly running you run the risk of overloading the machine and the hard drive there. Five levels range from None to Verbose, allowing to fine-tune the tracing activities.
  27. Where is the output of TextWriterTraceListener redirected? To the Console or a text file depending on the parameter passed to the constructor.
  28. How do you debug an ASP.NET Web application? Attach the aspnet_wp.exe process to the DbgClr debugger.
  29. What are three test cases you should go through in unit testing? Positive test cases (correct data, correct output), negative test cases (broken or missing data, proper handling), exception test cases (exceptions are thrown and caught properly).
  30. Can you change the value of a variable while debugging a C# application? Yes, if you are debugging via Visual Studio.NET, just go to Immediate window.
  31. Explain the three services model (three-tier application). Presentation (UI), business (logic and underlying code) and data (from storage or other sources).
  32. What are advantages and disadvantages of Microsoft-provided data provider classes in ADO.NET? SQLServer.NET data provider is high-speed and robust, but requires SQL Server license purchased from Microsoft. OLE-DB.NET is universal for accessing other sources, like Oracle, DB2, Microsoft Access and Informix, but it’s a .NET layer on top of OLE layer, so not the fastest thing in the world. ODBC.NET is a deprecated layer provided for backward compatibility to ODBC engines.
  33. What’s the role of the DataReader class in ADO.NET connections? It returns a read-only dataset from the data source when the command is executed.
  34. What is the wildcard character in SQL? Let‚Äôs say you want to query database with LIKE for all employees whose name starts with La. The wildcard character is %, the proper query with LIKE would involve ‚ÄėLa%‚Äô.
  35. Explain ACID rule of thumb for transactions. Transaction must be Atomic (it is one unit of work and does not dependent on previous and following transactions), Consistent (data is either committed or roll back, no ‚Äúin-between‚ÄĚ case where something has been updated and something hasn‚Äôt), Isolated (no transaction sees the intermediate results of the current transaction), Durable (the values persist if the data had been committed even if the system crashes right after).
  36. What connections does Microsoft SQL Server support? Windows Authentication (via Active Directory) and SQL Server authentication (via Microsoft SQL Server username and passwords).
  37. Which one is trusted and which one is untrusted? Windows Authentication is trusted because the username and password are checked with the Active Directory, the SQL Server authentication is untrusted, since SQL Server is the only verifier participating in the transaction.
  38. Why would you use untrusted verificaion? Web Services might use it, as well as non-Windows applications.
  39. What does the parameter Initial Catalog define inside Connection String?The database name to connect to.
  40. What’s the data provider name to connect to Access database? Microsoft.Access.
  41. What does Dispose method do with the connection object? Deletes it from the memory.
  42. What is a pre-requisite for connection pooling? Multiple processes must agree that they will share the same connection, where every parameter is the same, including the security settings.

 

Text To Speech Conversion – convert text to voice


Imports SpeechLib

Public Class Form1
    Dim voice As New SpVoice

    Private Subbtn_Read_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Try
            voice.Speak(Me.TextBox1.Text)
        Catch ex As Exception
         End Try
    End Sub

    Private Sub btn_Read_From_File_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Me.OpenFileDialog1.ShowDialog()
        Try
            Dim fs As New System.IO.FileStream(Me.OpenFileDialog1.FileName, IO.FileMode.Open, IO.FileAccess.Read)
            Dim fr As New System.IO.StreamReader(fs)

            Me.TextBox1.Text = fr.ReadToEnd
        Catch ex As Exception
        End Try
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.TextBox1.Select()
    End Sub
   
    End Class

************============***********
Another Processes 

private void btnListen_Click(object sender, EventArgs e)
{
	// Speech Recognition Object
	SpSharedRecoContext listener;

	// Grammar object
	ISpeechRecoGrammar grammar;

	listener = new SpeechLib.SpSharedRecoContext();
	listener.Recognition += new _ISpeechRecoContextEvents_RecognitionEventHandler (listener_Reco);
	grammar = listener.CreateGrammar(0);
	grammar.Dictationload("", SpeechLoadOption.SLOStatic);
	grammar.DictationSetState(SpeechRuleState.SGDSActive);
}

public void listener_Reco(int StreamNumber, object StreamPosition, SpeechRecognitionType RecognitionType, ISpeechRecoResult Result)
{
	string heard = Result.PhraseInfo.GetText(0, -1, true);
	textBox1.Text += heard;
}


 

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.1, ASP.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.

 

File uploader in C#


This is very basic level small user control, in which we can discuss how to create web user control.

To create user controls follow the steps:

  1. Right click on project
  2. Click on Add
  3. Select New Item
  4. Select Web User Control
  5. Specify some Name

I have given name to this file as “uploader.ascx” and kept this file under “userControl” for simplicity purpose.

On this page I am having following controls:

  1. <INPUT id=”fileUpload” type=”file” Runat=”server” NAME=”fileUpload”>
  2. <asp:label id=”lblMessage” runat=”server” Width=”416px” Font-Size=”10″ Font-Name=”verdana”></asp:label>
  3. <asp:button id=”btnSave” runat=”server” Text=”Upload..”></asp:button>

At the code behind of above file I am having following function

public string uploadFile(string fileName,string folderName)

{

if(fileName==””)

{

return¬†“Invalid filename supplied”;

}

if(fileUpload.PostedFile.ContentLength==0)

{

return¬†“Invalid file content”;

}

fileName = System.IO.Path.GetFileName(fileName);

if(folderName==””)

{

return¬†“Path not found”;

}

try

{

if (fileUpload.PostedFile.ContentLength<=2048000)

{

fileUpload.PostedFile.SaveAs(Server.MapPath(folderName)+”\\”+fileName);

return¬†“File uploaded successfully”;

}

else

{

return¬†“Unable to upload,file exceeds maximum limit”;

}

}

catch(UnauthorizedAccessException ex)

{

return¬†ex.Message + “Permission to upload file denied”;

}

}

 

The above function takes care of following things before uploading file to the folder

  1. Invalid file name supplied.
  2. If file not exists or content length 0.
  3. Folder name exists.

Error Handling

While uploading done with UnauthorizedAccessException and returned with the message

On upload button click I am having following code

 

private void btnSave_Click(object sender, System.EventArgs e)

{

string strFilename, strMessage;

strFilename = fileUpload.PostedFile.FileName.ToString();

strMessage = uploadFile(strFilename,ConfigurationSettings.AppSettings[“folderPath”]);

lblMessage.Text = strMessage;

lblMessage.ForeColor = Color.Red;

}

 

I have made use of Web.config file, in which I have added attribute as follows under:

 

<configuration>
<appSettings>
<add key=”folderPath” value=”Images”></add>
</appSettings>

i.e. I have set up path of folder to upload image

To access control in project, I have added page called as “uploadTester.aspx” to the project in which¬†I have added following line:

<%@ Register TagPrefix=”img” TagName=”Uploader” src=”userControl/uploader.ascx”%>

Which says that this control is register to this page with specified source.

And in HTML code I have added following code inside form tag:

<img:Uploader runat=”server” id=”Uploader1″></img:Uploader>

That’s all about

General:

To upload any of the file in respective folder user need to have permission for writing to the folder so please follow the following steps to prevent from the error.

Set permission to virtual directory by following steps in IIS

  • Right Click on virtual directory which you have created for this project. Under directory Tab you will find
    1)Read
    2)Log Visits
    3)Index this resources
    Are marked as checked (enables) in addition to this make
    4)Write access enabled or checked
  • Click on apply
  • Click on ok

This will set right permission to entire virtual directory, this way we can minimize error from the front end for permission / access denied.

Other way to solve permission denied issue is to go to actual folder “images” by using physical path and follow these steps:

  • Right click folder
  • Sharing Tab
  • Enable share this folder radio button
  • Click Apply
  • Click Ok

If u are using this code on 2000 server you should do following:

  • Right click respective folder
  • Go to security tab
  • Select Everyone user
  • Apply full control
  • click on ok

Kindly go through zip file for entire code.

 

 

How to Create Shortcut of Application programatically using C#


There are some situations in which we need to code to create a short cut of ourapplication especially when user loose the shortcuts created by the application after the setup has been run because some shortcuts also have defines special parameters that are for  executable that runs program.

So here is article i am presenting that will show you how to write code in c# that will create shortcut programmatically.

Step 1:

Create a New Windows Form Project.

Step 2:

Drag drop a button control from Toolbox to Form name it btnShortcut and Set text Property to “Create Shortcut “

Step 3:

For creating shortcut you need to reference Windows Script Host Object so follow the steps as below

Step 4:

Add namespace as below

using IWshRuntimeLibrary;

Step 5:

Now write code in Button’s Click event like below

private void btnShortcut_Click(object sender, EventArgs e)

{

WshShellClass shell = new WshShellClass();

IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(@‚ÄĚD:\shotcut.lnk‚ÄĚ);

shortcut.TargetPath = Application.ExecutablePath;

//shortcut.IconLocation = ‚ÄėLocation of¬† iCon you want to set‚ÄĚ;

// add Description of Short cut

shortcut.Description = “Any Description here “;

// save it / create

shortcut.Save();

}

 

 

 

There are some situations in which we need to code to create a short cut of our application especially when user loose the shortcuts created by the application after the setup has been run because some shortcuts also have defines special parameters that are for  executable that runs program.

So here is article i am presenting that will show you how to write code in c# that will create shortcut programmatically.

Step 1:

Create a New Windows Form Project.

Step 2:

Drag drop a button control from Toolbox to Form name it btnShortcut and Set text Property to “Create Shortcut ”

8-6-2010 6-47-21 PM.gif

Step 3:

For creating shortcut you need to reference Windows Script Host Object so follow the steps as below

Step 3a:

8-6-2010 6-36-00 PM.gif

Step 3b:

 

8-6-2010 6-39-47 PM.gif

Step 4:

Add namespace as below

using IWshRuntimeLibrary;

 

Step 5:

Now write code in Button’s Click event like below

private void btnShortcut_Click(object sender, EventArgs e)

{

 

WshShellClass shell = new WshShellClass();

 

IWshShortcut¬†shortcut = (IWshShortcut)shell.CreateShortcut(@”D:\shotcut.lnk”);

 

shortcut.TargetPath = Application.ExecutablePath;

//shortcut.IconLocation = ‘Location of¬†¬†iCon you want to set”;

 

// add Description of Short cut

shortcut.Description =¬†“Any Description here “;

 

// save it / create

shortcut.Save();

 

}

Step 6: you are done here is your result

 

8-6-2010 6-57-23 PM.gif

Sending Mail in ASP.NET using C#


Sending email from a web page is one of the most common functionality required from a web site.

The System.Web.Mail Namespace in the .NET Framework contains the required support classes and enumerations for email capabilities.

The main classes used are System.Web.Mail.MailMessage and the SmtpMail class.

Listing1 contains the listing for a simple web form to send email. This form assumes that the SMTP service is running on the server.  

Listing 1: Send an email from ASP.Net Page.

<%@¬†Import¬†Namespace=”System.Web.Mail”¬†%>
<script¬†language=”c#”¬†runat=”server”>

private void btnSend_Click(object sender, System.EventArgs e)

{

MailMessage msg = new MailMessage();

msg.To = txtTo.Text;

msg.From = txtFrom.Text;

msg.Subject = txtSubject.Text;

msg.Body = txtContent.Value;
lblStatus.Text =¬†“Sending…”;

SmtpMail.Send(msg);

lblStatus.Text =¬†“Sent email (”¬†+ txtSubject.Text +¬†“) to ”¬†+txtTo.Text;

}

</script>

<html>

<body>

<h3>

Email From ASP.NET</h3>

<form¬†id=”MailForm”¬†method=”post”¬†runat=”server”>

<asp:Label¬†ID=”Label1″¬†Style=”left: 100px; position: absolute; top: 100px”¬†runat=”server”>From:

</asp:Label>

<asp:TextBox¬†ID=”txtFrom”¬†Style=”left: 200px; position: absolute; top: 100px”

runat=”server”></asp:TextBox>

<asp:RequiredFieldValidator¬†ID=”FromValidator1″¬†Style=”left: 100px; position: absolute;

top: 375px”¬†runat=”server”¬†ErrorMessage=”Please Enter the Email From.”¬†Width=”200px”

Height=”23px”¬†ControlToValidate=”txtFrom”></asp:RequiredFieldValidator>

<asp:RegularExpressionValidator¬†ID=”FromValidator2″¬†Style=”left: 100px; position: absolute;

top: 400px”¬†runat=”server”¬†ErrorMessage=”Please Enter a Valid From Email address”

ControlToValidate=”txtFrom”¬†ValidationExpression=”\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)

*”></asp:RegularExpressionValidator>

<asp:Label¬†ID=”Label2″¬†Style=”left: 100px; position: absolute; top: 125px”¬†runat=”server”>To:

</asp:Label>

<asp:TextBox¬†ID=”txtTo”¬†Style=”left: 200px; position: absolute; top: 125px”

runat=”server”></asp:TextBox>

<asp:RequiredFieldValidator¬†ID=”ToValidator1″¬†Style=”left: 100px; position: absolute;

top: 425px”¬†runat=”server”¬†ErrorMessage=”Please Enter the Email To.”¬†Width=”200px”

Height=”23px”¬†ControlToValidate=”txtTo”></asp:RequiredFieldValidator>

<asp:RegularExpressionValidator¬†ID=”ToValidator2″¬†Style=”left: 100px; position: absolute;

top: 450px”¬†runat=”server”¬†ErrorMessage=”Please Enter a Valid To Email address”

ControlToValidate=”txtTo”¬†ValidationExpression=”\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)

*”></asp:RegularExpressionValidator>

<asp:Label¬†ID=”Label3″¬†Style=”left: 100px; position: absolute; top: 150px”

runat=”server”>Subject</asp:Label>

<asp:TextBox¬†ID=”txtSubject”¬†Style=”left: 200px; position: absolute; top: 150px”

runat=”server”></asp:TextBox>

<asp:Label¬†ID=”Label4″¬†Style=”left: 100px; position: absolute; top: 175px”¬†runat=”server”>Mail:

</asp:Label>

<textarea¬†runat=”server”¬†id=”txtContent”¬†style=”left: 200px; width: 400px; position: absolute;

top: 175px; height: 125px”¬†rows=”7″¬†cols=”24″>

</textarea>

<asp:Button¬†ID=”btnSend”¬†Style=”left: 200px; position: absolute; top: 350px”¬†runat=”server”

Text=”Send”¬†OnClick=”btnSend_Click”></asp:Button>

<asp:Label¬†ID=”lblStatus”¬†Style=”left: 250px; position: absolute; top: 350px”¬†runat=”server”>

</asp:Label>

</form>

</body>

</html>

Figure 1 : Email Form in action

Figure 2: Results

In order to specify another  SMTP server ,  use the SmtpServer field of the SmtpMail object as shown in figure 2 :

Listing 2: Use another mail server

private void btnSend_Click(object sender, System.EventArgs e)

{

MailMessage msg = new MailMessage();

msg.To = txtTo.Text;

msg.From = txtFrom.Text;

msg.Subject = txtSubject.Text;

msg.Body = txtContent.Value;

lblStatus.Text =¬†“Sending…”;

SmtpMail.SmtpServer =¬†“smtp.yourISP.com”;

SmtpMail.Send(msg);

lblStatus.Text =¬†“Sent email (”¬†+ txtSubject.Text +¬†“) to ”¬†+ txtTo.Text;
}

Here is a code snippet for adding attachments :

Listing 3: Send Attachments

{

….

StrFilePath =¬†“c:\\emps.txt”;

MailAttachment attach = new MailAttachment(strFilePath);

msg.Attachments.Add(attach);

….

}