Custom Error Handling in ASP.NET

Introduction
Structured exception handling is a fundamental part of the CLR and provides .Net programmers a great way of managing errors. In addition to CLR exception system, ASP.Net also provides ways of handling errors.

When a runtime or design-time error occurs in an application, ASP.Net shows a default error page that gives a brief description of the error along with the line number on which the error occurred. A developer would wish to view this default error page, during the testing of the application since the description helps him in rectifying the error. But he would never want a user trying to access his application, to view this error page. The user would be least bothered to know about the error. Instead of showing the default error page, it would be more sensible to show a customized error page that would let the user send notification of the error to the administrator.
Explanation
Consider an example of an ASP.Net application that generates an error intentionally to show how ASP.Net detects it and shows the default error page. The below given webform contains a label and a button server control. In the eventhandler for the button click event, the user will be redirected to another webform "Trial.aspx". Since the page being redirected to, is missing ASP.Net will show the default error page indicating it is a runtime error.

Unlike classic ASP, ASP.Net separates the code for the business logic from the content (i.e HTML and interface logic). The sample application has two files named "webform1.aspx" containing the content and "webform1.aspx.vb" containing the code.
WebForm1.aspx
<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="WebForm1.aspx.vb" Inherits="ErrorSample.WebForm1"%>
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.0 Transitional//EN">
<
HTML
><HEAD><title></title><meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0"><meta name="CODE_LANGUAGE" content="Visual Basic 7.0"><meta name="vs_defaultClientScript" content="JavaScript"><meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"></HEAD><body MS_POSITIONING="GridLayout"><form id="Form1" method="post" runat="server"><asp:Label id="Message" style="Z-INDEX: 101; LEFT: 34px;
POSITION: absolute; TOP: 46px"
runat="server"></asp:Label
><asp:Button id="ErrorButton" style="Z-INDEX: 102; LEFT: 268px;
POSITION: absolute; TOP: 41px"
runat="server" Text
="Generate
Error"></
asp:Button
></form></body>
</
HTML
>
WebForm1.aspx.vb
Public Class
WebForm1Inherits System.Web.UI.PageProtected WithEvents Message As System.Web.UI.WebControls.LabelProtected WithEvents ErrorButton As System.Web.UI.WebControls.ButtonPrivate Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles
MyBase.Load
Message.Text = "This sample page generates an Error..."
End
SubPublic Sub ErrorButton_Click(ByVal sender As Object, ByVal e AsSystem.EventArgs)Handles ErrorButton.Click
Response.Redirect("Trial.aspx")
End
Sub
End
Class
Now if you try to run the above web form by viewing it on the browser, you will get the below shown web page:



Now if you click on the button labeled "Generate Error", you will get the below shown default ASP.Net error page.


Customizing Error PageTo customize the default error page, one will have to change the default configuration settings of the application.

There are three error modes in which an ASP.Net application can work:

  1. Off Mode
  2. On Mode
  3. RemoteOnly Mode
The Error mode attribute determines whether or not an ASP.Net error message is displayed. By default, the mode value is set to "RemoteOnly".
  • Off ModeWhen the error attribute is set to "Off", ASP.Net uses its default error page for both local and remote users in case of an error.
  • On ModeIn case of "On" Mode, ASP.Net uses user-defined custom error page instead of its default error page for both local and remote users. If a custom error page is not specified, ASP.Net shows the error page describing how to enable remote viewing of errors.
  • RemoteOnlyASP.Net error page is shown only to local users. Remote requests will first check the configuration settings for the custom error page or finally show an IIS error.
Configuration File
Customization of error page can be implemented by adding a value for an attribute "defaultRedirect" in the <customErrors> tag of the configuration file "web.config". This file determines configuration settings for the underlying application.

  • Off ModeIn this scenario, set the mode attribute value to "Off" as shown below:
    Web.Config File
    <?xml version="1.0" encoding="utf-8"
    ?>
    <
    configuration
    ><system.web><customErrors mode="Off" /></system.web>
    </
    configuration
    >
    When the sample ASP.Net web page is viewed in the browser from the remote machine, one gets the below shown default error page.



    The above example thus shows that, whether it is local or remote access, ASP.Net error page is shown.
    On Mode
    In this scenario, set the mode attribute value to "On" as shown below:

    Web.Config File
    <?xml version="1.0" encoding="utf-8"
    ?>
    <
    configuration
    ><system.web><customErrors defaultRedirect="error.htm" mode="On" /></system.web>
    </
    configuration
    >
    As shown in the configuration file, the "defaultRedirect" attribute has been set to a user-defined page "error.htm". The user-defined error page can be an ASP.Net web page, classic ASP page or a simple HTML page.

    For example, the contents of the user-defined error page "error.htm" can be given as follows:
    Error.htm
    <HTML
    >
    <
    BODY
    ><b>We are very sorry for the inconvenience caused to you...<br></b>
    </
    BODY
    >
    </
    HTML
    >
    When the sample ASP.Net web page is viewed in the browser from the remote/local machine, one gets the below shown custom error page.


  • RemoteOnly Mode
    In this scenario, set the mode attribute value to "RemoteOnly" as shown below:
    Web.Config File<?xml version="1.0" encoding="utf-8" ?>configuration><system.web><customErrors defaultRedirect="error.htm" mode="RemoteOnly" /></system.web>
    </
    configuration
    >

    Since the "defaultRedirect" attribute has been set, if the page is requested from a remote machine page is redirected to "error.htm" and if the page is requested from the local machine the default error page is shown.
Notification of Error to the Administrator
In a practical web application, customization of error pages is not the only requirement. The error, if encountered, should be reported to the administrator so that it can be rectified thus enabling subsequent requests to work properly without any error.

Notification of the error can be sent to the administrator in one of the following two ways:

  1. Error can be registered as a log entry in the Windows Event Log on the administrator's machine.
  2. An Email can be sent to the administrator with a suitable error message.
  • Writing to the Event Log
    In ASP.Net, error can be handled programmatically by writing appropriate code in the page-level error event, for errors on an individual page or in the application-level error event for handling errors that may occur in any page of the application.
    Therefore, code for writing in the Event Log should be written in either of the events, depending on the requirement of the application. To illustrate this example, I have written the code in the application-level event with the error mode set to "RemoteOnly" and the "defaultRedirect" attribute to "error.htm". The application-level error event should be included in the global file "global.asax" within the same application folder.
    The contents of the global file can be given as follows:
    Writing Log Entry in the Event Log
    Imports System.WebImports System.Web.SessionStateImports System.DiagnosticsPublic Class GlobalInherits System.Web.HttpApplicationSub Application_Error(ByVal sender As Object, ByVal e As EventArgs)Dim ErrorDescription As String = Server.GetLastError.ToString'Creation of event log if it does not exist Dim EventLogName As String = "ErrorSample"If (Not EventLog.SourceExists(EventLogName)) ThenEventLog.CreateEventSource(EventLogName, EventLogName)End If' Inserting into event logDim Log As New EventLog
    Log.Source = EventLogName
    Log.WriteEntry(ErrorDescription, EventLogEntryType.Error)
    End Sub
    End
    Class
    Event Log support is provided in .Net through the namespace "System.Diagnostics". So, for the above code to work, it is very essential to add a reference to the above-mentioned namespace in the project. In the event handler for application-level error, a log named "ErrorSample" is created if it does not exist in the Event Log. If it already exists, the error entry is added to the existing list of events. After viewing the page on the browser from a remote machine, the event will get listed in the Event Log on the administrator's machine as shown below:


    Description of the error can be viewed by selecting the appropriate event and double clicking it. Another form pops up as shown below:


  • Sending an Email to the Administrator
    To illustrate this example, I have written the code for sending an Email to the administrator in the application-level error event. The contents of the global file can be given as follows:
    Sending Email To the Administrator
    Imports System.WebImports System.Web.SessionStateImports System.Web.MailPublic Class GlobalInherits System.Web.HttpApplicationSub Application_Error(ByVal sender As Object, ByVal e As EventArgs)Dim mail As New MailMessageDim ErrorMessage = "The error description is as follows : "
    & Server.GetLastError.ToStringmail.To = administrator@domain.com
    mail.Subject = "Error in the Site"
    mail.Priority = MailPriority.High
    mail.BodyFormat = MailFormat.Text
    mail.Body = ErrorMessage
    SmtpMail.Send(mail)
    End Sub
    End
    Class
    In the above code, SMTP service is being used to send the mail across. SMTP mail service support is provided in .Net through the namespace "System.Web.Mail". So, for the above code to work, it is very essential to add a reference to the above-mentioned namespace in the project.

SQL Keys

 A primary key is a column which uniquely identifies the records in a table. In a broad sense, a primary key is the mixture of a unique key and an index: A collumn with a primary key is indexed to deliver a faster query, and doesn't allow duplicate values to ensure specific data.

Most programmers recommend all tables having a primary key (and only one) to enhance the speed of queries and overall database performance.

An example of a primary key may be found in a table named "departments," which might have a collumn named "department_number" that uniquely identifies each department in the table with a number.

A foreign key is a column (the child collumn) in a table which has a corresponding relationship and a dependency on another collumn (the parent collumn) that is usually in a different table. Parent collumns can have multiple child collumns, but a child collumn can only have one parent collumn.

The child collumn is the collumn with the foreign key; the parent collumn does not have the foreign key "set" on it, but most databases require the parent collumn to be indexed.

Foreign keys are made to link data across multiple tables. A child collumn cannot have a record that its parent collumn does not have.

Say a table named "employees" has 20 employees (rows) in it. There are 4 departments in the "departments" table. All 20 employees must belong to a department, so a collumn in the "employees" table named "department" would point to the primary key in the "departments" table using a foreign key. Now all employees must belong to a department as specified by the "departments" table. If a department isn't specified in the "departments" table, the employee cannot be assigned to it.

A candidate key would be any key which could be used as the primary key, which means that the combination of the columns, or just the single column would create a unique key. You would then need to determine which of these candidate keys would work best as your primary key.


Using Cross Joins

Many SQL books and tutorials recommend that you “avoid cross joins” or “beware of Cartesian products” when writing your SELECT statements, which occur when you don't express joins between your tables.  It’s true that you need to ensure that your join conditions are adequately stated so that you don’t accidentally produce this effect, but it is not true that you should avoid these types of joins in every situation.
Cross Joins produce results that consist of every combination of rows from two or more tables.  That means if table A has 3 rows and table B has 2 rows, a CROSS JOIN will result in 6 rows.  There is no relationship established between the two tables – you literally just produce every possible combination.
The danger here, of course, is that if you have table A with 10,000 rows and Table B with 30,000 rows, and you accidentally create the product of these two tables, you will end up with a 300,000,000 row result -- probably not a good idea.  (Though it is great for creating test data and the like.)
So, how can this ever be useful?  Actually, if you do lots of report writing in SQL, a CROSS JOIN can be your best friend.
Suppose you need to write a report that returns total sales for each Store and each Product.  You might come up with this:
SELECT Store, Product, SUM(Sales) as TotalSales
FROM Sales
GROUP BY Store, Product
Easy enough – except when the requirement states “show $0 if a store had no sales of a particular product”.  The above query won’t do that – it returns no rows at all if a store had no sales for a particular product. 
The solution?  Well, hopefully in your database you have a table of Stores and a table of Products.  A cross join of the two results will return 1 row per combination of Store and Product:
SELECT S.Store, P.Product
FROM Stores S
CROSS JOIN Products P
That result is the perfect starting point for the results we wish to return -- now we just need to return the sales for each combination.  We already have written that in our first attempt, so now we just need to combine the two:
SELECT S.Store, P.Product, ISNULL(C.TotalSales,0) as TotalSales
FROM Stores S
CROSS JOIN Products P
LEFT OUTER JOIN
    (SELECT Store, Product, SUM(Sales) as TotalSales
     FROM Sales
     GROUP BY Store, Product) C
ON
  S.Store = C.Store AND
  P.Product = C.Product
The SELECT is derived logically from our requirements.  We start by considering all combinations of stores and products, and from there we show any matching sales data.  Our primary, driving rowset is actually not the transaction table, but rather the cross join of two entity tables!  It might seem very counter intuitive if you haven't approached the problem from this angle before, but it leads to very simple and elegant ways to solve rather complicated problems using SQL.
The solution uses what I call “the report writers magic formula”:
(A x B ) -> (C)
In my made up notation, the above reads “A cross joined with B, left outer joined to C ”.  A and B represent master tables of entities in your database, and C represents a summarized derived table of a transactional table in your database.
Some important things to note:
  • All criteria for the transactions, such as date ranges and/or transaction types, need to be done in the inner transaction summary query. 
  • The summarized transactional sub-query needs to be properly grouped so that it returns 1 row per combination of A and B.  Typically, this means that if the PK of table A is “A_ID” and the PK is table B is “B_ID”, then the derived table C should be grouped by A_ID, B_ID.
  • All criteria that determines which entities to show on your report – i.e., certain regions or only “active” products – should be done on the outer query.
Take the previous SELECT statement, for example: Note that the inner SELECT is grouped by Product and Store, which ensures that we return 1 row per combination of Product/Store -- which perfectly matches what the cross join creates.  If we wanted to show only data for 2005, we would put the filter on the TransactionDate column within the inner SELECT (since that is the part of the statement in which we collect and summarize our transactions), but if we want only ProductID #23, we do that in the outer SELECT (since that is where we determine the population of Stores and Products to return):
SELECT S.Store, P.Product, ISNULL(C.TotalSales,0) as TotalSales
FROM Stores S
CROSS JOIN Products P
LEFT OUTER JOIN
    (SELECT Store, Product, SUM(Sales) as TotalSales
     FROM Sales
     WHERE TransactionDate between '1/1/2005' and '12/31/2005'
     GROUP BY Store, Product) C
ON
  S.Store = C.Store AND
  P.Product = C.Product
WHERE
  P.Product = 23
The CROSS JOIN technique can apply to many situations – to return total labor cost by office by month, even if month X has no labor cost, you can do a cross join of Offices with a table of all months.   Another classic example is showing all GL transactions for a specific set of companies and accounts, returning all accounts and companies even when they have no activity.
The important thing is to practice with very small sets of sample data until you get a feel for how it works.  Also, you should explicitly state CROSS JOIN in your SELECT so that it is very clear that you intend for this to happen and it is not the result of missing joins. 

Explain about strong name in .NET.

They are the assemblies which can be uniquely identified by attaching the strong name to the dll name. It gives a unique name to each assembly of various versions. This allows solving the DLL hell problem.

Creating an Assembly with a Strong Name

   1. Use the Strong Name tool (Sn.exe) that comes with the .NET Framework Software Development Kit (SDK) to generate a cryptographic key pair.

      The following command uses the Strong Name tool to generate a new key pair and store it in a file called TestKey.snk:

      sn -k Testkey.snk
                             

   2. Add the proper custom attribute to your source for the compiler to emit the assembly with a strong name. Which attribute you use depends on whether the key pair that is used for the signing is contained in a file or in a key container within the Cryptographic Service Provider (CSP). For keys that are stored in a file, use the System.Reflection.AssemblyKeyFileAttribute attribute. For keys that are stored in the CSP, use the System.Reflection.AssemblyKeyNameAttribute attribute.

      The following code uses AssemblyKeyFileAttribute to specify the name of the file that contains the key pair.

      NOTE: In Microsoft Visual Basic, the assembly level attributes must appear as the first statements in the file.Visual Basic .NET Code

      Imports System
      Imports System.Reflection

      <assembly:AssemblyKeyFileAttribute("TestKey.snk")>
                         

      C# Code

      using System;
      using System.Reflection;

      [assembly:AssemblyKeyFileAttribute("TestKey.snk")]
                         
.........................................................................................................................................

A strong name is a reliable .NET assembly identifier,
comprised of the assembly’s simple text name, version
number, culture, public key and a digital signature. The
latter two are generated with the strong name (sn) tool,
while the remainder is part of the assemblies manifest …
usually specified in the AssemblyInfo source file.

........................................................................................................................


A strong name consists of the assembly's identity — its
simple text name, version number, and culture information
(if provided) — plus a public key and a digital signature.

In particular, strong names satisfy the following requirements:

Strong names guarantee name uniqueness by relying on unique
key pairs. No one can generate the same assembly name that
you can, because an assembly generated with one private key
has a different name than an assembly generated with another
private key.

Strong names protect the version lineage of an assembly. A
strong name can ensure that no one can produce a subsequent
version of your assembly. Users can be sure that a version
of the assembly they are loading comes from the same
publisher that created the version the application was built
with.

Strong names provide a strong integrity check. Passing the
.NET Framework security checks guarantees that the contents
of the assembly have not been changed since it was built.
Note, however, that strong names in and of themselves do not
imply a level of trust like that provided, for example, by a
digital signature and supporting certificate.

................................................................................................................................................................


A strong name consists of the assembly's identity — its simple text name, version number, and culture information (if provided) — plus a public key and a digital signature. It is generated from an assembly file (the file that contains the assembly manifest, which in turn contains the names and hashes of all the files that make up the assembly), using the corresponding private key. Microsoft® Visual Studio® .NET and other development tools provided in the .NET Framework SDK can assign strong names to an assembly. Assemblies with the same strong name are expected to be identical.

You can ensure that a name is globally unique by signing an assembly with a strong name. In particular, strong names satisfy the following requirements:

    * Strong names guarantee name uniqueness by relying on unique key pairs. No one can generate the same assembly name that you can, because an assembly generated with one private key has a different name than an assembly generated with another private key.
    * Strong names protect the version lineage of an assembly. A strong name can ensure that no one can produce a subsequent version of your assembly. Users can be sure that a version of the assembly they are loading comes from the same publisher that created the version the application was built with.
    * Strong names provide a strong integrity check. Passing the .NET Framework security checks guarantees that the contents of the assembly have not been changed since it was built. Note, however, that strong names in and of themselves do not imply a level of trust like that provided, for example, by a digital signature and supporting certificate.

When you reference a strong-named assembly, you expect to get certain benefits, such as versioning and naming protection. If the strong-named assembly then references an assembly with a simple name, which does not have these benefits, you lose the benefits you would derive from using a strong-named assembly and revert to DLL conflicts. Therefore, strong-named assemblies can only reference other strong-named assemblies.

difference between Server.Transfer and Response.Redirect

Server.Transfer() : client is shown as it is on the requesting page only, but the all the content is of the requested page. Data can be persist accros the pages using Context.Item collection, which is one of the best way to transfer data from one page to another keeping the page state alive.
Response.Dedirect() :client know the physical loation (page name and query string as well). Context.Items loses the persisitance when nevigate to destination page. In earlier versions of IIS, if we wanted to send a user to a new Web page, the only option we had was Response.Redirect. While this method does accomplish our goal, it has several important drawbacks. The biggest problem is that this method causes each page to be treated as a separate transaction. Besides making it difficult to maintain your transactional integrity, Response.Redirect introduces some additional headaches. First, it prevents good encapsulation of code. Second, you lose access to all of the properties in the Request object. Sure, there are workarounds, but they’re difficult. Finally, Response.Redirect necessitates a round trip to the client, which, on high-volume sites, causes scalability problems.
As you might suspect, Server.Transfer fixes all of these problems. It does this by performing the transfer on the server without requiring a roundtrip to the client.
......................................................................................................................................
Response.Redirect simply sends a message down to the browser, telling it to move to another page. So, you may run code like:
Response.Redirect("WebForm2.aspx")
or
Response.Redirect("http://www.karlmoore.com/")
to send the user to another page.
Server.Transfer is similar in that it sends the user to another page with a statement such as Server.Transfer("WebForm2.aspx"). However, the statement has a number of distinct advantages and disadvantages.
Firstly, transferring to another page using Server.Transfer conserves server resources. Instead of telling the browser to redirect, it simply changes the "focus" on the Web server and transfers the request. This means you don't get quite as many HTTP requests coming through, which therefore eases the pressure on your Web server and makes your applications run faster.
But watch out: because the "transfer" process can work on only those sites running on the server, you can't use Server.Transfer to send the user to an external site. Only Response.Redirect can do that.
Secondly, Server.Transfer maintains the original URL in the browser. This can really help streamline data entry techniques, although it may make for confusion when debugging.
That's not all: The Server.Transfer method also has a second parameter—"preserveForm". If you set this to True, using a statement such as Server.Transfer("WebForm2.aspx", True), the existing query string and any form variables will still be available to the page you are transferring to.
For example, if your WebForm1.aspx has a TextBox control called TextBox1 and you transferred to WebForm2.aspx with the preserveForm parameter set to True, you'd be able to retrieve the value of the original page TextBox control by referencing Request.Form("TextBox1").
This technique is great for wizard-style input forms split over multiple pages. But there's another thing you'll want to watch out for when using the preserveForm parameter. ASP.NET has a bug whereby, in certain situations, an error will occur when attempting to transfer the form and query string values. You'll find this documented at http://support.microsoft.com/default.aspx?id=kb;en-us;Q316920.
The unofficial solution is to set the enableViewStateMac property to True on the page you'll be transferring to, then set it back to False. This records that you want a definitive False value for this property and resolves the bug.
So, in brief: Response.Redirect simply tells the browser to visit another page. Server.Transfer helps reduce server requests, keeps the URL the same and, with a little bug-bashing, allows you to transfer the query string and form variables.
Top Tip: Don't confuse Server.Transfer with Server.Execute, which executes the page and returns the results. It was useful in the past, but, with ASP.NET, it's been replaced with fresher methods of development. Ignore it.

.........................................................................................................................................

A common misconception is the difference between Server.Transfer and Response.Redirect in ASP.NET applications. Redirect and Transfer both cause a new page to be processed, but the interaction between the client (web browser) and server (ASP.NET) is different in each situation.
Redirect: A redirect is just a suggestion – it’s like saying to the client “Hey, you might want to look at this”. All you tell the client is the new URL to look at, and if they comply, they do a second request for the new URL.
If you want to pass state from the source page to the new page, you have to pass it either on the URL (such as a database key, or message string), or you can store it in the Session object (caveat: there may be more than one browser window, and they’ll all use the same session object).
e.g. Redirect to the new.aspx page, passing an ID on the query string. "true" stops processing the current page:

Difference between Web.Config and Machine.Config File


Machine.Config:-
1) This is automatically installed when you install Visual Studio. Net.
2) This is also called machine level configuration file.
3)Only one machine.config file exists on a server.
4) This file is at the highest level in the configuration hierarchy.
Web.Config:-
1) This is automatically created when you create an ASP.Net web application project.
2) This is also called application level configuration file.
3)This file inherits setting from the machine.config
.........................................................................................................................................
1)Machine.config is used to store machine level settings
Web.config is used to store per application based settings
2)We can have more than one web.config files but only one
machine.config
3)Web.config overrides the machine.config file.
If we store different values on both for a single key, the
application will get the value from the web.config file
.........................................................................................................................................
The MACHINE.config file contains default and machnine-specific values for all supported setting.
Machine setting are normally controlled by the system admin and app should never be given write access to it.
An application can override most default values stored in the machine.config file by creating one or more web.config files.
At min an app creates a WEB config file in its root folder. The web.config file is a subset of machine.config written according to the same XML achema.

.........................................................................................................................................
Machine.Config:-
1) This is automatically installed when you install .Net Framework.
2)Only one machine.config file can exist on a server.
3) This file is at the highest level in the configuration hierarchy.
4)Its like a common repository for standard items and its over ridden by web.config file.
3)With out the Machine.Config file Application can not be executed.
Web.Config:-
1) This is automatically created when you create an ASP.Net web application project.
2)This file inherits the settings from the machine.config
3)With out the Web.Config file Application can still be executed.

 

difference between autopostback and ispostback?

Autopostback - Property of the control
IsPostback - Property of the Page class
Autopostback - get and set property to control postback on changes made for control.
for e.g.
this.ListBox1.AutoPostBack = true;
whenever user will select item, the page will get post back.
IsPostback - get property of the Page class, to check if page is post back i.e. if it is true then page has already executed Init function of the page else it is first time the page has requested to be executed.